-
-
[原创]KCTF2020秋季赛 第四题 突破重围 writeup
-
发表于: 2020-11-23 23:42 4220
-
com.kanxue.crackme.Crack.check
com.kanxue.crackme.Crack.crypt
找到cryptcontent的值为 "l+x7fKd2FBaaEY4NV4309A==\n"
crypt中的mkey有改变 "kaokaonio" -> "keepGoing"
S盒
AES扩展密钥算法
1、"l+x7fKd2FBaaEY4NV4309A==" -> bytes -> base64 -> crypto (mKey=keepGoing)
2、AES解密
3、解密字符串
crypto (mKey=kaokaonio)
System.loadLibrary(
"crack"
);
init();
-
> DexClassLoader
/
assets
/
b.txt
check() 反射执行 com.kanxue.crackme.Crack.check()
System.loadLibrary(
"crack"
);
init();
-
> DexClassLoader
/
assets
/
b.txt
check() 反射执行 com.kanxue.crackme.Crack.check()
public
class
MyCrack {
public static String crypt
=
"otVvmpP4ZI58pqB26OTaYw=="
;
public static native byte[] crackjni(byte[] bArr);
}
public
class
MyCrack {
public static String crypt
=
"otVvmpP4ZI58pqB26OTaYw=="
;
public static native byte[] crackjni(byte[] bArr);
}
public static boolean check(String content) {
if
(content
=
=
null || content.length() !
=
16
) {
return
false;
}
Class MyCrackClass
=
null;
Field cryptfield
=
null;
byte[] result
=
crypt(content.getBytes());
Method crackjni
=
null;
try
{
MyCrackClass
=
Crack.
class
.getClassLoader().loadClass(
"com.kanxue.crackme.MyCrack"
);
cryptfield
=
MyCrackClass.getDeclaredField(
"crypt"
);
Method[] methods
=
MyCrackClass.getDeclaredMethods();
for
(
int
i
=
0
; i < methods.length; i
+
+
) {
if
(methods[i].getName().equals(
"crackjni"
)) {
crackjni
=
methods[i];
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e2) {
e2.printStackTrace();
}
if
(crackjni !
=
null) {
try
{
result
=
(byte[]) crackjni.invoke(null, new
Object
[]{result});
} catch (IllegalAccessException e3) {
e3.printStackTrace();
} catch (InvocationTargetException e4) {
e4.printStackTrace();
}
}
String finalresult
=
Base64.encodeToString(crypt(result),
0
);
String cryptcontent
=
"test"
;
if
(!(cryptfield
=
=
null || MyCrackClass
=
=
null)) {
try
{
cryptcontent
=
(String) cryptfield.get(null);
} catch (IllegalAccessException e5) {
e5.printStackTrace();
}
}
if
(finalresult.equals(cryptcontent)) {
return
true;
}
return
false;
}
public static boolean check(String content) {
if
(content
=
=
null || content.length() !
=
16
) {
return
false;
}
Class MyCrackClass
=
null;
Field cryptfield
=
null;
byte[] result
=
crypt(content.getBytes());
Method crackjni
=
null;
try
{
MyCrackClass
=
Crack.
class
.getClassLoader().loadClass(
"com.kanxue.crackme.MyCrack"
);
cryptfield
=
MyCrackClass.getDeclaredField(
"crypt"
);
Method[] methods
=
MyCrackClass.getDeclaredMethods();
for
(
int
i
=
0
; i < methods.length; i
+
+
) {
if
(methods[i].getName().equals(
"crackjni"
)) {
crackjni
=
methods[i];
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e2) {
e2.printStackTrace();
}
if
(crackjni !
=
null) {
try
{
result
=
(byte[]) crackjni.invoke(null, new
Object
[]{result});
} catch (IllegalAccessException e3) {
e3.printStackTrace();
} catch (InvocationTargetException e4) {
e4.printStackTrace();
}
}
String finalresult
=
Base64.encodeToString(crypt(result),
0
);
String cryptcontent
=
"test"
;
if
(!(cryptfield
=
=
null || MyCrackClass
=
=
null)) {
try
{
cryptcontent
=
(String) cryptfield.get(null);
} catch (IllegalAccessException e5) {
e5.printStackTrace();
}
}
if
(finalresult.equals(cryptcontent)) {
return
true;
}
return
false;
}
public static byte[] crypt(byte[] b_data) {
String mKkey
=
"kaokaonio"
;
if
(b_data
=
=
null) {
return
null;
}
int
x
=
0
;
int
y
=
0
;
byte[] b_key
=
mKkey.getBytes();
byte[] key
=
new byte[
256
];
for
(
int
i
=
0
; i <
256
; i
+
+
) {
key[i]
=
(byte) i;
}
int
index1
=
0
;
int
index2
=
0
;
if
(b_key
=
=
null || b_key.length
=
=
0
) {
return
null;
}
for
(
int
i2
=
0
; i2 <
256
; i2
+
+
) {
index2
=
((b_key[index1] &
255
)
+
(key[i2] &
255
)
+
index2) &
255
;
byte tmp
=
key[i2];
key[i2]
=
key[index2];
key[index2]
=
tmp;
index1
=
(index1
+
1
)
%
b_key.length;
}
byte[] result
=
new byte[b_data.length];
for
(
int
i3
=
0
; i3 < b_data.length; i3
+
+
) {
x
=
(x
+
1
) &
255
;
y
=
((key[x] &
255
)
+
y) &
255
;
byte tmp2
=
key[x];
key[x]
=
key[y];
key[y]
=
tmp2;
result[i3]
=
(byte) (b_data[i3] ^ key[((key[x] &
255
)
+
(key[y] &
255
)) &
255
]);
}
return
result;
}
public static byte[] crypt(byte[] b_data) {
String mKkey
=
"kaokaonio"
;
if
(b_data
=
=
null) {
return
null;
}
int
x
=
0
;
int
y
=
0
;
byte[] b_key
=
mKkey.getBytes();
byte[] key
=
new byte[
256
];
for
(
int
i
=
0
; i <
256
; i
+
+
) {
key[i]
=
(byte) i;
}
int
index1
=
0
;
int
index2
=
0
;
if
(b_key
=
=
null || b_key.length
=
=
0
) {
return
null;
}
for
(
int
i2
=
0
; i2 <
256
; i2
+
+
) {
index2
=
((b_key[index1] &
255
)
+
(key[i2] &
255
)
+
index2) &
255
;
byte tmp
=
key[i2];
key[i2]
=
key[index2];
key[index2]
=
tmp;
index1
=
(index1
+
1
)
%
b_key.length;
}
byte[] result
=
new byte[b_data.length];
for
(
int
i3
=
0
; i3 < b_data.length; i3
+
+
) {
x
=
(x
+
1
) &
255
;
y
=
((key[x] &
255
)
+
y) &
255
;
byte tmp2
=
key[x];
key[x]
=
key[y];
key[y]
=
tmp2;
result[i3]
=
(byte) (b_data[i3] ^ key[((key[x] &
255
)
+
(key[y] &
255
)) &
255
]);
}
return
result;
}
1.
input
长度
16
2.
byte[] result
=
crypt(
input
) crypt方法中的 mkey
=
kaokaonio
3.
crackjni_reslut
=
libcarack.so
-
>crackjni(reslut) 对 reslut 进行加密
4.
reslut
=
crypt(crackjni_reslut) crypt方法中的 mkey
=
keepGoing
5.
base64(reslut) 与 cryptcontent
=
"l+x7fKd2FBaaEY4NV4309A==\n"
进行比较
1.
input
长度
16
2.
byte[] result
=
crypt(
input
) crypt方法中的 mkey
=
kaokaonio
3.
crackjni_reslut
=
libcarack.so
-
>crackjni(reslut) 对 reslut 进行加密
4.
reslut
=
crypt(crackjni_reslut) crypt方法中的 mkey
=
keepGoing
5.
base64(reslut) 与 cryptcontent
=
"l+x7fKd2FBaaEY4NV4309A==\n"
进行比较
int
__fastcall Java_com_kanxue_crackme_MyCrack_crackjni(_JNIEnv
*
a1,
int
a2,
int
a3)
{
v25
=
sub_CF79ECBC((void
*
)
0xFFFFFF9C
,
"/proc/self/maps"
,
0
,
0
);
/
/
frida anti
if
( v25 >
=
1
)
{
while
( sub_CF7A2168(v25, &s,
0x200
) >
=
1
)
{
if
( strstr(&s,
"frida"
) )
MEMORY[
0
]
=
0x63
;
if
( sscanf(&s,
"%x-%lx %4s %lx %*s %*s %s"
, &v31, &v30, &v33, &v32, &v39)
=
=
5
&& v33
=
=
0x72
&& v34
=
=
0x70
&& !v32
&& strlen(&v39)
&& v39 !
=
0x5B
&& (unsigned
int
)(v30
-
v31) >
0xF4240
&& !sub_CF7A22C0(&v39,
".oat"
)
&& sub_CF7A2228(v31)
=
=
1
&& sub_CF7A20D2(v31,
0
, v30, v30 >>
0x1F
)
=
=
1
)
{
MEMORY[
0
]
=
0x63
;
break
;
}
}
}
......
sub_CF79ED60(v5,
"kaokaonikaokaoni"
, v6);
/
/
AES加密
......
if
( dword_CF7D73E4 )
{
if
( dword_CF7D73D8 )
{
v12
=
dword_CF7D73D8
+
0x16D3A6
;
v13
=
*
(_BYTE
*
)(dword_CF7D73D8
+
0x16D3A6
);
v14
=
dword_CF7D73E4
+
+
;
*
(_BYTE
*
)(dword_CF7D73D8
+
0x16D3A6
)
=
v13
+
v14;
*
(_BYTE
*
)(v12
+
1
)
=
0x3D
;
v15
=
sub_CF7A38C2(v29,
"com/kanxue/crackme/MyCrack"
);
v16
=
sub_CF7A38EC(v29, v15,
"crypt"
,
"Ljava/lang/String;"
);
v17
=
sub_CF7A3934(v29,
"ZmxhZ3RyeWFnYWluP30="
);
sub_CF7A3960(v29, v15, v16, v17);
}
+
+
dword_CF7D73E4;
}
else
{
if
( dword_CF7D73D8 )
{
v8
=
dword_CF7D73D8
+
0x16D3A6
;
*
(_BYTE
*
)(dword_CF7D73D8
+
0x16D3A6
)
=
0xD3u
;
/
/
"kaokaonio"
-
>
"keepGoing"
*
(_BYTE
*
)(v8
+
1
)
=
0x3D
;
v9
=
sub_CF7A38C2(v29,
"com/kanxue/crackme/MyCrack"
);
v10
=
sub_CF7A38EC(v29, v9,
"crypt"
,
"Ljava/lang/String;"
);
v11
=
sub_CF7A3934(v29,
"l+x7fKd2FBaaEY4NV4309A==\n"
);
/
/
"otVvmpP4ZI58pqB26OTaYw=="
-
>
"l+x7fKd2FBaaEY4NV4309A=="
sub_CF7A3960(v29, v9, v10, v11);
}
+
+
dword_CF7D73E4;
}
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2020-11-24 07:56
被neilwu编辑
,原因:
赞赏记录
参与人
雪币
留言
时间
一笑人间万事
为你点赞~
2022-7-27 01:17
心游尘世外
为你点赞~
2022-7-26 23:05
飘零丶
为你点赞~
2022-7-17 02:46
supperlitt
为你点赞~
2020-11-25 17:48
number_Z
为你点赞~
2020-11-24 14:25
赞赏
他的文章
看原图
赞赏
雪币:
留言: