首页
社区
课程
招聘
[原创]第四题解题思路
发表于: 2015-1-25 14:17 2466

[原创]第四题解题思路

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函数

    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直播授课

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//