上月的ctf木有机会参加,不过技术比较菜,不献丑也好。。。废话不多说,拿来看看。
--------------------------------------------------------------------------------
0x01 脱壳
脱壳方法和年初的MSC相同,看雪有各路大牛的技巧。 脱壳修复dex之后,用jd查看。
0x02 分析
从入口函数看起,根据布局文件,结合apk界面,可以知道基本的空间。关注btn的listerner:
其中:
try {
你好中国.__Db(this.b.c, 2130968577);//故意赋值不相同的空间类型,进入异常流程。
}
catch(Exception v0) {
try {
byte[] v0_1 = 你好中国.__Lb(你好中国.__Ib(你好中国.__m(this.a)), "UTF-8"); // 直接获取bytes
}
catch(Exception v0) {
goto label_39;
}
try {
if(v0_1.length >= 1 && (你好中国.__bb(v0_1))) {
你好中国.__Bb(你好中国.__Eb(this.b), 0); //这里可以断定为成功流程,结果字符串资源文件的GO!!!可以确定。
return;
}
你好中国.__Bb(你好中国.__Eb(this.b), 1);
}
catch(Exception v0) {
try {
你好中国.__Bb(你好中国.__Eb(this.b), 1);
}
catch(Exception v0) {
label_39:
throw new RuntimeException();
}
}
}
关键点就是__bb方法做了什么。oops拿起Indroid圣剑就开搞。
小弟木有圣剑,拿着补刀斧上了。反正不是比赛,也不用担心时间问题。
...
调试之后,找到各种Native函数地址。
...
再接着调试__bb方法,然后发现问题:
经常反射调用tn的a,b无用方法干扰我们。
输入数据经过__p方法后,进行了变换。 dd出内存,这个方法f5看得也是醉了:
跟踪之后,逆出一下代码:(JAVA)
public static void __p(byte[] arg3) {
int v0;
for(v0 = 0; v0 < arg3.length; ++v0) {
arg3[v0] = ((byte)(arg3[v0] + v0 * 3)); //经过3轮,每轮数值加上i,这里直接合并
}
}
再调试之后,发现还调用了s的a方法变换
....
调试发现,其反射调用了H的a方法:
public static byte[] a(byte[] arg7) {
你好中国.__n(你好中国.__Q());
Cipher v0 = 你好中国.__Fb("AES");
你好中国.__Zb("h01aJiqQsF/dl3g6LaZi7g==", 0);//base64字串,调试其反射调用了decode方法
你好中国.__Zb("h01aJiqQSF/dl3g6Lazi7g==", 0);
你好中国.__Zb("h01aJiqQSF/dI3g6LaZi7g==", 0);
你好中国.__Ab(v0, 1, new SecretKeySpec(你好中国.__Zb("h01aJiqQSF/dl3g6LaZi7g==", 0), "AES"));
你好中国.__Zb("h01aJiqQSF/pl3g6LaZi7g==", 0);
return 你好中国.__Vb(v0, arg7);//aes加密,密钥就是解密base64后的值
}
...
再调用了R的a方法,获得checkCode值.
public static byte[] a() {
你好中国.__n(你好中国.__Q());
int v0 = 0;
你好中国.__Zb("+by7eL4gwrnnaW3z3lPbbA==", 0);
byte[] v1 = 你好中国.__Zb("+by7eL4gwrmnaW3z3lPbbA==", 0);
你好中国.__Zb("+by7eL4gwrmnaW3z31PbbA==", 0);
你好中国.__Zb("+by7eL4gvrmnaW3z31PbbA==", 0);
while(v0 < v1.length) {
v1[v0] = ((byte)(v1[v0] ^ 5));
++v0;
}
return v1;
}
最后调用__x方法,返回比较结果。
猜测就是直接比较返回结果,故内存修改输入的code,结果不正确。
。。。再动态调试了__x方法,发现在java里面执行a()方法得出的checkCode与apk运行的checkCode不匹配。
fc b9 be 7d bb 25 c7 bc a2 6c 68 f6 da 56 de 69
fc b9 be 7d bb 25 c7 bc a2 6c 68 f6 [db] 56 de 69
真是要跪了。。。
根据逆过程,写下代码,得到正确结果。。。
------------------------------------------------------------
总的来说,调试要耐心,细节决定成败。