Googlectf 2017 food writeup

google ctf 2017出了道安卓题,就一道,唉,拿了个三血。。。不难,从头到尾仔细分析了一遍。

转载请联系本人,否则作侵权处理。 相关文件链接:https://github.com/LeadroyaL/attachment_repo/tree/master/googlectf-food/

在Java层渲染GUI渲染到一半就跑到JNI里了,

1
2
3
4
5
6
protected void onCreate(Bundle arg2) {
super.onCreate(arg2);
this.setContentView(2130968601);
FoodActivity.activity = ((Activity)this);
System.loadLibrary("cook");
}

我所有的手机全部都无法运行,崩在了so里面,也不知道是什么骚套路,只能静态分析,不能偷鸡了。


下面是JNI,每个const-string均被加密处理过,需要手动解掉它们,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ddex = dec_string(
21,
0x25410F20,
274990436,
1534345504,
73731176,
107435040,
208625010,
57547381,
1193298532,
174394722,
174457445,
1331774752,
274992494,
1298351648,
7276911,
1142948971,
141449845,
90774900,
1394608492,
376589666,
326582639,
493161326);

解出来是

/data/data/com.google.ctf.food/files/d.dex

使用的脚本为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def dec_string(enc_data):
ret_len = len(enc_data)
ret = ""
chr1 = None
chr2 = None
"""
*result =
~(( ~ cur_int&0xff ((unsigned __int16)(cur_int & 0xFF00) >> 8)) & (~((unsigned __int16)(cur_int & 0xFF00) >> 8) cur_int));
result[1] = HIBYTE(cur_int) ^ ((cur_int & 0xFF0000) >> 16);
"""
for i in range(ret_len):
cur_int = enc_data[i]
chr1 = (~(((~cur_int & 0xff) ((cur_int & 0xff00) >> 8)) & ((~(cur_int & 0xff00) >> 8) cur_int))) & 0xff
chr2 = ((cur_int & 0xff000000) >> 24) ^ ((cur_int & 0xff0000) >> 16)
ret += chr(chr1)
ret += chr(chr2)
return ret

之后一行一行看代码,总体流程为:

  1. 解密一段数据后,创建并且写文件,是0x1770006大小的、在so中存放的明文,以dex035开头;
  2. 拿到systemClassLoader,加载创建好的d.dex文件,新建一个classloader;
  3. 删掉dex和odex的文件和目录
  4. 加载com/google/ctf/food/S这个类,调用其构造方法,参数用反射的方式拿到老的Activity
  5. 0x1098进行热补丁,通过读取/proc/self/maps,对内存中,距离dex035为0x720的位置,写为unk_2E88 xor 0x90,最后写到原来的位置。我们观察一下dex文件,刚好写掉了一个空的方法体,位于com/google/ctf/food/Broadcast的cc方法。
  6. 之后继续渲染即可。

全部修好的dex可以拖到JEB去查看(详见附件),显然是个RC4

1
2
3
rc4
enc = [ -19, 116, 58, 108, -1, 33, 9, 61, -61, -37, 108, -123, 3, 35, 97, -10, -15, 15, -85, -66, -31, -65, 17, 79, 31, 25, -39, 95, 93, 1, -110, -103, -118, -38, -57, -58, -51, -79]
key = [9, 10, 13, 7, 17, 1, 19, 2]

用python解一下

1
2
3
4
5
6
7
key = ''.join(chr(k) for k in key)
enc = ''.join(chr(k&0xff) for k in enc)

from Crypto.Cipher import ARC4
cipher = ARC4.new(key)
cipher.decrypt(enc)
# 'CTF{bacon_lettuce_tomato_lobster_soul}'

flag为

CTF{bacon_lettuce_tomato_lobster_soul}

搞定。。。