资源编号: [复制编号]
提取密码 : ****
提取密码 : ****
下载权限 :
普通
(由网友上传,安全性未知,请谨慎下载)
KCTF2020秋季赛 第四题 突破重围 wp
一道Android题
Java层分析
1、com.kanxue.crackme.MainActivity
1
2
3
4
5
|
System.loadLibrary(
"crack"
);
init();
-
> DexClassLoader
/
assets
/
b.txt
check() 反射执行 com.kanxue.crackme.Crack.check()
|
2、com.kanxue.crackme.MyCrack
1
2
3
4
5
|
public
class
MyCrack {
public static String crypt
=
"otVvmpP4ZI58pqB26OTaYw=="
;
public static native byte[] crackjni(byte[] bArr);
}
|
3、/assets/b.txt -> /assets/b.dex
com.kanxue.crackme.Crack.check
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
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;
}
|
com.kanxue.crackme.Crack.crypt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
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;
}
|
对/assets/b.dex进行动态调试:
找到cryptcontent的值为 "l+x7fKd2FBaaEY4NV4309A==\n"
crypt中的mkey有改变 "kaokaonio" -> "keepGoing"
执行流程如下:
1
2
3
4
5
6
7
8
9
|
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"
进行比较
|
Native层分析
1、libcrack.so 使用了 aes 加密
S盒
2、Java_com_kanxue_crackme_MyCrack_crackjni
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
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;
}
}
|
AES扩展密钥算法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
int
sub_CF79EDE8()
{
unsigned __int8 v0;
/
/
ST04_1
unsigned
int
j;
/
/
[sp
+
8h
] [bp
-
18h
]
unsigned
int
i;
/
/
[sp
+
Ch] [bp
-
14h
]
unsigned __int8 v4;
/
/
[sp
+
10h
] [bp
-
10h
]
unsigned __int8 v5;
/
/
[sp
+
11h
] [bp
-
Fh]
unsigned __int8 v6;
/
/
[sp
+
12h
] [bp
-
Eh]
unsigned __int8 v7;
/
/
[sp
+
13h
] [bp
-
Dh]
for
( i
=
0
; i <
=
3
;
+
+
i )
{
byte_CF7B6318[
4
*
i]
=
*
(_BYTE
*
)(dword_CF7B6314
+
4
*
i);
byte_CF7B6318[
4
*
i
+
1
]
=
*
(_BYTE
*
)(dword_CF7B6314
+
4
*
i
+
1
);
byte_CF7B6318[
4
*
i
+
2
]
=
*
(_BYTE
*
)(dword_CF7B6314
+
4
*
i
+
2
);
byte_CF7B6318[
4
*
i
+
3
]
=
*
(_BYTE
*
)(dword_CF7B6314
+
4
*
i
+
3
);
}
while
( i <
=
0x2B
)
{
for
( j
=
0
; j <
=
3
;
+
+
j )
*
(&v4
+
j)
=
byte_CF7B6318[
4
*
i
-
4
+
j];
if
( !((unsigned __int8)i <<
0x1E
) )
{
v0
=
v4;
v4
=
v5;
v5
=
v6;
v6
=
v7;
v7
=
v0;
v4
=
sub_CF79F084(v4);
v5
=
sub_CF79F084(v5);
v6
=
sub_CF79F084(v6);
v7
=
sub_CF79F084(v7);
v4 ^
=
byte_CF7AFE5C[i >>
2
];
}
byte_CF7B6318[
4
*
i]
=
byte_CF7B6318[
4
*
i
-
0x10
] ^ v4;
byte_CF7B6318[
4
*
i
+
1
]
=
byte_CF7B6318[
4
*
i
-
0xF
] ^ v5;
byte_CF7B6318[
4
*
i
+
2
]
=
byte_CF7B6318[
4
*
i
-
0xE
] ^ v6;
byte_CF7B6318[
4
*
i
+
3
]
=
byte_CF7B6318[
4
*
i
-
0xD
] ^ v7;
+
+
i;
}
return
_stack_chk_guard;
}
|
获取flag
1、"l+x7fKd2FBaaEY4NV4309A==" -> bytes -> base64 -> crypto (mKey=keepGoing)
1
|
40
,
-
128
,
-
114
,
-
30
,
10
,
-
79
,
122
,
37
,
-
62
,
22
,
120
,
86
,
58
,
74
,
127
,
-
85
|
2、AES解密
3、解密字符串
crypto (mKey=kaokaonio)
更多【KCTF2020秋季赛 第四题 突破重围 writeup】相关视频教程:www.yxfzedu.com