-
-
[原创]第四题解题思路
-
发表于: 2015-1-25 14:17 2466
-
程序有反调试
运行apk,使用kill -19 <pid>使得程序暂停。
然后IDA附加上去,恢复程序运行,IDA启动。
此时会收到错误信号,屏蔽此信号。把产生信号的线程暂停。此时可以正常进行调试。
同之前的题目,通过gdvm-> userDexFiles 可以找到加载的JarFile结构,进而找到dex文件地址。
先dump dex文件大小,查看CodeOff,然后再次大范围dump,把代码完成dump出来
(PS:貌似要先运行一次程序,提交一次数据之后,才有正常的dex产生,程序运行后立刻dump出来的有很多问题)
简单修一下dex文件(忘记有没有修了),原则就是出错的地方,一律清零。
通过baksmali和smali就可以获得正常的dex文件了。
跟主流程,找到是把输入的内容传到了native函数ali$a.M$j里面。
然后搞SO,很难搞,所以采取直接调试的办法。
修改Android的ROM,发现调用Native函数的时候,判断函数名是不是"M$j",如果是的话,就输出method->insns,即native函数起始地址。同理,之后的M$d和M$z函数地址也是通过此种方法获取。
M$j经过了代码混淆,应对的办法就是在所有的BL和BLX处下断点,看系统调用。
发现是调用了bh.a函数。从dex里面查看bh.a函数
除了两个native函数M$d和M$z外,其他都能自己实现反函数(逆向还原函数)。
跟踪M$d和M$z流程。和M$j一样的方法
发现M$d是把byte[]的第4个字母(Index = 3)的值+8
M$z里面除了bh.a生成的字符串,还有一个字符串
"aJTCZnf6NyBPYJfbrBuLu0wOhRFbPtvqpYjiby5J81M=",并且比较了大小(内容比较通过函数调用看不到,所以不确定,猜测有)
所以,通过自己写的bh.a的反函数,解密"aJTCZnf6NyBPYJfbrBuLu0wOhRFbPtvqpYjiby5J81M="得到
"alibaba2345ba"
就是答案
最后附上写的反函数
运行apk,使用kill -19 <pid>使得程序暂停。
然后IDA附加上去,恢复程序运行,IDA启动。
此时会收到错误信号,屏蔽此信号。把产生信号的线程暂停。此时可以正常进行调试。
同之前的题目,通过gdvm-> userDexFiles 可以找到加载的JarFile结构,进而找到dex文件地址。
先dump dex文件大小,查看CodeOff,然后再次大范围dump,把代码完成dump出来
(PS:貌似要先运行一次程序,提交一次数据之后,才有正常的dex产生,程序运行后立刻dump出来的有很多问题)
简单修一下dex文件(忘记有没有修了),原则就是出错的地方,一律清零。
通过baksmali和smali就可以获得正常的dex文件了。
跟主流程,找到是把输入的内容传到了native函数ali$a.M$j里面。
然后搞SO,很难搞,所以采取直接调试的办法。
修改Android的ROM,发现调用Native函数的时候,判断函数名是不是"M$j",如果是的话,就输出method->insns,即native函数起始地址。同理,之后的M$d和M$z函数地址也是通过此种方法获取。
M$j经过了代码混淆,应对的办法就是在所有的BL和BLX处下断点,看系统调用。
发现是调用了bh.a函数。从dex里面查看bh.a函数
public static byte[] a(byte[] arg4, int arg5) { bKn.b(bKn.a()); int v0 = arg5 + 1; int v2 = v0 + 1; int v1 = v2 - 1; byte[] v0_1 = x.a(p.a(cC.a(cd.a(arg4, arg5), v0), v2), v1); v2 = v1 - 1; v0_1 = ali$a.M$d(v0_1, v1); v1 = v2 + 1; v0_1 = x.a(aS.a(v0_1, v2), v1); v2 = v1 + 1; return cC.a(cd.a(ali$a.M$z(v0_1, v1), v2), v2 + 1); }
除了两个native函数M$d和M$z外,其他都能自己实现反函数(逆向还原函数)。
跟踪M$d和M$z流程。和M$j一样的方法
发现M$d是把byte[]的第4个字母(Index = 3)的值+8
M$z里面除了bh.a生成的字符串,还有一个字符串
"aJTCZnf6NyBPYJfbrBuLu0wOhRFbPtvqpYjiby5J81M=",并且比较了大小(内容比较通过函数调用看不到,所以不确定,猜测有)
所以,通过自己写的bh.a的反函数,解密"aJTCZnf6NyBPYJfbrBuLu0wOhRFbPtvqpYjiby5J81M="得到
"alibaba2345ba"
就是答案
最后附上写的反函数
package me.test; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; public class test { public static byte [] cda(byte[] arg4, int arg5){ byte[] v1 = new byte[arg4.length]; int i; for(i = 0; i < arg4.length; i++){ v1[i] = (byte)(arg4[i] + 3); } return v1; } public static byte[] r_cda(byte [] in, int r){ byte [] v1 = new byte[in.length]; int i; for(i = 0; i < in.length; i++){ v1[i] = (byte)(in[i] - 3); } return v1; } public static byte [] cca(byte [] arg4, int arg5){ byte [] v1 = new byte[arg4.length]; int v0; for(v0 = 0; v0 < arg4.length; ++v0) { v1[v0] = ((byte)((arg4[v0] ^ arg5) + v0)); } return v1; } public static byte[] r_cca(byte [] arg4, int arg5){ byte [] v1 = new byte[arg4.length]; int v0; for(v0 = 0; v0 < arg4.length; ++v0) { v1[v0] = ((byte)((arg4[v0] - v0) ^ arg5)); } return v1; } public static byte [] pa(byte[] arg5, int arg6){ byte[] v0_1 = new byte[arg5.length]; int v1 = 1; while(v1 < arg5.length){ v0_1[v1 - 1] = arg5[v1]; ++v1; } v0_1[arg5.length - 1] = arg5[0]; return v0_1; } public static byte [] r_pa(byte [] arg5, int arg6){ byte[] v0_1 = new byte[arg5.length]; int v1 = 1; while(v1 < arg5.length){ v0_1[v1] = arg5[v1 - 1]; ++v1; } v0_1[0] = arg5[arg5.length - 1]; return v0_1; } public static byte [] xa(byte [] arg2, int arg3){ return Base64.encode(arg2, 2); } public static byte [] r_xa(byte[] in, int arg3){ return Base64.decode(in, 2); } public static byte[] M$d(byte[] arg1, int arg2) { arg1[3] += 8; return arg1; } public static byte [] r_M$d(byte[] in ,int arg2){ in[3] -= 8; return in; } public static byte[] asa(byte [] arg6, int arg7){ try { Cipher v0_1 = Cipher.getInstance("AES"); v0_1.init(1, new SecretKeySpec(Base64.decode("qqVJwt11yyLm7hVK1iI2aw==", 0), "AES")); arg6 = v0_1.doFinal(arg6); } catch(Exception v0) { } return arg6; } public static byte [] r_asa(byte [] arg6, int arg7){ try { Cipher v0_1 = Cipher.getInstance("AES"); v0_1.init(Cipher.DECRYPT_MODE, new SecretKeySpec(Base64.decode("qqVJwt11yyLm7hVK1iI2aw==", 0), "AES")); arg6 = v0_1.doFinal(arg6); } catch(Exception v0) { } return arg6; } public static byte[] M$z(byte[] arg1, int arg2) { return arg1; } public static void main(String argv[]) { decode("aJTCZnf6NyBPYJfbrBuLu0wOhRFbPtvqpYjiby5J81M=".getBytes(), 0x31); encode("1234567890", 0x30); } public static byte [] decode(byte [] b, int key){ int i1 = key; byte [] a1 = r_xa(b, i1); int i2 = i1 - 1; byte [] a2 = r_asa(a1, i2); int i3 = i2 + 1; byte [] a3 = r_M$d(a2, i3); byte [] a4 = r_xa(a3, i3); int i4 = i3 + 1; byte [] a5 = r_pa(a4, i4); int i5 = i4 - 1; byte [] a6 = r_cca(a5, i5); int i6 = i5 - 1; byte [] a7 = r_cda(a6, i6); return a7; } public static byte [] encode(String data, int key){ int i = key + 1; byte[] arrayOfByte1 = cda(data.getBytes(), key); int j = i + 1; byte[] arrayOfByte2 = cca(arrayOfByte1, i); int k = j - 1; byte[] tmp = pa(arrayOfByte2, j); byte[] arrayOfByte3 = xa(tmp, k); int m = k - 1; byte[] arrayOfByte4 = M$d(arrayOfByte3, k); int n = m + 1; byte [] tmp2 = asa(arrayOfByte4, m); byte[] arrayOfByte5 = xa(tmp2, n); int i1 = n + 1; byte[] arrayOfByte6 = M$z(arrayOfByte5, n); int i2 = i1 + 1; byte[] arrayOfByte7 = cda(arrayOfByte6, i1); return cca(arrayOfByte7, i2 + 1); } }
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
- Something about CVE 2016-3754 4885
- [分享]七年之痒 5828
- [原创]一个dex脱壳脚本 21125
- 简单吐槽一下dirtyCow 14009
- [原创]关于userDexFiles偏移获取 8014
看原图
赞赏
雪币:
留言: