qu头条qdata字段unidbg逆向

qu头条qdata字段unidbg逆向

Java层

1240

com.jifen.qukan.lib.report.ReportEncryptManager.encryptBodyMap

1240

com.jifen.qukan.lib.report.ReportEncryptManager.encodeToString

1240

com.inno.innosecure.InnoSecureMain.innoSecureEncodeV2

1240

com.inno.innosecure.InnoSecureMain.secure

1240
1240

可以看到最后是在libInnoSecure.so里。

hook看看数据

android hooking watch class_method com.inno.innosecure.InnoSecureUtils.secure --dump-args --dump-return
1240

入参1是json数据,入参2是uuid,入参3,4是固定的(本机固定,不同设备未测试)。输出做个base64就是qdata

再用frida进行主动调用

function call_secure() {
    var Inno = Java.use("com.inno.innosecure.InnoSecureUtils");
    var p0 = "{\"name\":\"everhu\",\"version\":\"31061000\",\"OSVersion\":\"7.1.2\",\"dtu\":\"003\",\"network\":\"wifi\",\"versionName\":\"3.10.61.000.0927.1727\"}";
    var p1 = "9ba5e613-ab5d-4835-b7fa-84582f19c46e";
    var p2 = "3082021b30820184a0030201020204574beab6300d06092a864886f70d01010505003052310c300a06035504061303303231310b3009060355040813025348310b3009060355040713025348310b3009060355040a13025a48310b3009060355040b1302434e310e300c0603550403130551754b616e301e170d3136303533303037323433385a170d3431303532343037323433385a3052310c300a06035504061303303231310b3009060355040813025348310b3009060355040713025348310b3009060355040a13025a48310b3009060355040b1302434e310e300c0603550403130551754b616e30819f300d06092a864886f70d010101050003818d0030818902818100aa5bae49b771380e692444437b82b375cabdefb3f23307c29510653776b8e4115f776bea5eb6690285f97d4e6e8d0469e49f79ecba31e4b7fb85dd612ee6b27ef38502aa38d055ddad2aa7b52d19fb8d2aeeb59a830b91c341f1b467655e7313e9ff65feb6539bf1655f35a37e17faa94e506a08219df196730f45d9c1cd94d30203010001300d06092a864886f70d0101050500038181000e6cc9fb74aef11dd33d6603869a9db61b8dcedae77bc815433026693fe59fd4b75a3284170f8872737e55595c1fd40da3dfbe5ad8a4e96802f53637977f0eb6e9b0dc35161cbaed398b41ecd73c4009a1dae7bcb00b75c3f8d5792405bcc5e4602d9dff6a0dc4739240a3b42626f5efce4d7baea0fced2b13361cb4ded8ed0b";
    var p3 = [-119,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,10,0,0,0,10,8,2,0,0,0,2,80,88,-22,0,0,1,110,73,68,65,84,120,1,0,31,0,-32,-1,0,120,-62,101,-43,-19,-94,64,70,-80,-72,-87,-101,-104,-27,-46,84,-80,13,-16,29,-96,95,67,-46,-26,122,-63,82,104,-114,0,31,0,-32,-1,0,106,99,-21,15,-31,94,-30,-51,-90,-62,118,-49,-8,-97,-22,36,-60,86,-51,0,0,29,-62,101,-43,-6,-94,64,70,49,0,31,0,-32,-1,0,-22,-87,-101,-104,-19,-46,84,-80,7,-54,29,-96,95,115,-46,-26,122,33,-81,104,-114,106,-23,-21,15,-31,-127,76,-51,-90,0,31,0,-32,-1,0,-62,32,-49,-8,-97,100,-88,-60,86,-51,0,0,90,0,-122,-109,-127,27,51,18,-122,-41,-35,-27,40,23,-20,-42,-40,98,0,31,0,-32,-1,0,-52,83,121,-87,97,21,37,-10,-17,63,110,19,86,114,-52,93,84,34,-24,-43,-29,50,23,-13,-29,11,30,-17,64,-65,0,31,0,-32,-1,0,-51,-109,-103,-45,-112,37,-105,102,-87,85,-13,50,22,92,-63,92,121,-27,-22,-37,101,-76,40,-112,49,-88,49,-11,-106,90,0,31,0,-32,-1,0,-114,-34,-72,118,-14,-42,118,-98,-10,-127,-24,120,46,11,78,-5,127,27,-25,-124,-66,-34,-17,-47,123,-90,96,113,-122,-67,0,31,0,-32,-1,0,70,46,92,-79,-108,-62,78,-86,38,10,-4,-3,-50,-34,-70,0,-73,59,82,-79,54,120,114,-105,-33,27,30,-9,-11,-48,0,31,0,-32,-1,0,124,48,-27,113,-51,-97,70,92,-35,39,98,25,30,-47,-43,29,-62,-73,105,-15,96,71,92,4,-54,39,-122,-88,48,-117,1,31,0,-32,-1,0,-103,-32,67,-62,-95,95,-106,-31,5,-44,-28,-7,25,41,112,-92,-59,-11,105,-127,-34,115,-87,-121,-88,118,-74,76,-22,27,-17,-86,-94,53,-55,-88,5,74,0,0,0,0,73,69,78,68,-82,66,96,-126];
    var p4 = null;
    var p5 = 0;
    var ret = Inno.secure(p0, p1, p2, p3, p4, p5);
}
1240

主动调用了2次,结果不一样,说明可能有时间戳或随机数参与计算。

unidbg实现

public class Qutoutiao extends AbstractJni {
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;

    public static String pkgName = "com.jifen.qukan";
    public static String apkPath = "unidbg-android/src/test/java/com/qutoutiao/qutoutiao31061.apk";
    public static String soName = "InnoSecure";

    public Qutoutiao() {
        emulator = AndroidEmulatorBuilder.for32Bit().setProcessName(pkgName).build();
        Memory memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23));
        vm = emulator.createDalvikVM(new File(apkPath));
        vm.setJni(this);
        vm.setVerbose(true);
        DalvikModule dm = vm.loadLibrary(soName, true);
        module = dm.getModule();

        dm.callJNI_OnLoad(emulator);
    }

    public void call_secure() {
        String p0 = "{\"name\":\"everhu\",\"version\":\"31061000\",\"OSVersion\":\"7.1.2\",\"dtu\":\"003\",\"network\":\"wifi\",\"versionName\":\"3.10.61.000.0927.1727\"}";
        String p1 = "9ba5e613-ab5d-4835-b7fa-84582f19c46e";
        String p2 = "3082021b30820184a0030201020204574beab6300d06092a864886f70d01010505003052310c300a06035504061303303231310b3009060355040813025348310b3009060355040713025348310b3009060355040a13025a48310b3009060355040b1302434e310e300c0603550403130551754b616e301e170d3136303533303037323433385a170d3431303532343037323433385a3052310c300a06035504061303303231310b3009060355040813025348310b3009060355040713025348310b3009060355040a13025a48310b3009060355040b1302434e310e300c0603550403130551754b616e30819f300d06092a864886f70d010101050003818d0030818902818100aa5bae49b771380e692444437b82b375cabdefb3f23307c29510653776b8e4115f776bea5eb6690285f97d4e6e8d0469e49f79ecba31e4b7fb85dd612ee6b27ef38502aa38d055ddad2aa7b52d19fb8d2aeeb59a830b91c341f1b467655e7313e9ff65feb6539bf1655f35a37e17faa94e506a08219df196730f45d9c1cd94d30203010001300d06092a864886f70d0101050500038181000e6cc9fb74aef11dd33d6603869a9db61b8dcedae77bc815433026693fe59fd4b75a3284170f8872737e55595c1fd40da3dfbe5ad8a4e96802f53637977f0eb6e9b0dc35161cbaed398b41ecd73c4009a1dae7bcb00b75c3f8d5792405bcc5e4602d9dff6a0dc4739240a3b42626f5efce4d7baea0fced2b13361cb4ded8ed0b";
        byte[] barr = new byte[] {-119,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,10,0,0,0,10,8,2,0,0,0,2,80,88,-22,0,0,1,110,73,68,65,84,120,1,0,31,0,-32,-1,0,120,-62,101,-43,-19,-94,64,70,-80,-72,-87,-101,-104,-27,-46,84,-80,13,-16,29,-96,95,67,-46,-26,122,-63,82,104,-114,0,31,0,-32,-1,0,106,99,-21,15,-31,94,-30,-51,-90,-62,118,-49,-8,-97,-22,36,-60,86,-51,0,0,29,-62,101,-43,-6,-94,64,70,49,0,31,0,-32,-1,0,-22,-87,-101,-104,-19,-46,84,-80,7,-54,29,-96,95,115,-46,-26,122,33,-81,104,-114,106,-23,-21,15,-31,-127,76,-51,-90,0,31,0,-32,-1,0,-62,32,-49,-8,-97,100,-88,-60,86,-51,0,0,90,0,-122,-109,-127,27,51,18,-122,-41,-35,-27,40,23,-20,-42,-40,98,0,31,0,-32,-1,0,-52,83,121,-87,97,21,37,-10,-17,63,110,19,86,114,-52,93,84,34,-24,-43,-29,50,23,-13,-29,11,30,-17,64,-65,0,31,0,-32,-1,0,-51,-109,-103,-45,-112,37,-105,102,-87,85,-13,50,22,92,-63,92,121,-27,-22,-37,101,-76,40,-112,49,-88,49,-11,-106,90,0,31,0,-32,-1,0,-114,-34,-72,118,-14,-42,118,-98,-10,-127,-24,120,46,11,78,-5,127,27,-25,-124,-66,-34,-17,-47,123,-90,96,113,-122,-67,0,31,0,-32,-1,0,70,46,92,-79,-108,-62,78,-86,38,10,-4,-3,-50,-34,-70,0,-73,59,82,-79,54,120,114,-105,-33,27,30,-9,-11,-48,0,31,0,-32,-1,0,124,48,-27,113,-51,-97,70,92,-35,39,98,25,30,-47,-43,29,-62,-73,105,-15,96,71,92,4,-54,39,-122,-88,48,-117,1,31,0,-32,-1,0,-103,-32,67,-62,-95,95,-106,-31,5,-44,-28,-7,25,41,112,-92,-59,-11,105,-127,-34,115,-87,-121,-88,118,-74,76,-22,27,-17,-86,-94,53,-55,-88,5,74,0,0,0,0,73,69,78,68,-82,66,96,-126};
        DvmClass clz = vm.resolveClass("com/inno/innosecure/InnoSecureUtils");
        String methodSign = "secure(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;I)[B";
        ByteArray ret = clz.callStaticJniMethodObject(emulator, methodSign,
                new StringObject(vm, p0),
                new StringObject(vm, p1),
                new StringObject(vm, p2),
                new ByteArray(vm, barr),
                null,
                null);
        byte[] barr2 = ret.getValue();
        byte[] barr3 = Base64.encodeBase64(barr2);
        System.out.println(new String(barr3));
        System.out.println(Arrays.toString(barr2));
    }

    public static void main(String[] args) {
        Qutoutiao test = new Qutoutiao();
        test.call_secure();
    }
}
1240

运行多次后,发现结果不变,和frida调用表现不一致。这是因为unidbg的种子是固定的,导致生成的随机数序列是固定的,进而导致结果是固定的。

固定随机数

1240

ida跳转到0x5ead

1240
1240

innoSecure

1240
1240
1240
1240

innoSecure函数有900行左右,把很多东西都塞到这里实现了,看起来又臭又长。

其中有个arc4random函数,一看就是用于生成随机数的,hook它将随机数固定。

// fail
public void hook_libc() {
    IHookZz hookZz = HookZz.getInstance(emulator);
    hookZz.wrap(module.findSymbolByName("arc4random"), new WrapCallback() {
        @Override
        public void preCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
        }

        @Override
        public void postCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            ctx.setR0(1);
        }
    });
}
public static void main(String[] args) {
    Qutoutiao test = new Qutoutiao();
    test.hook_libc();
    test.call_secure();
}
1240

然后就报错了,跳转过去看看。

1240

这个函数没有实现,这我也不会啊。。

1240

换个思路,直接patch调用arc4random函数这条指令,将r0设为1,相当于每次随机数函数的返回值为1。

public void patch() {
    // mov r0,1
    emulator.getMemory().pointer(module.base + 0x77e8).setInt(0, 0x0001f04f);
}
public static void main(String[] args) {
    Qutoutiao test = new Qutoutiao();
    test.patch();
    test.call_secure();
}
1240

结果出来了,之后的逆向将基于此结果。

固定随机数的好处就是每次输出都不会变,方便分析。而且我们能一眼看出哪个是随机数,做到心中有数。

分析输出

真正开始逆向之前看看输出的组成方式,base64解码看看输出。

1240

可以大致看出输出由3部分组成,各部分用.连接,第1部分是32位字符串,应该是个MD5;第2部分是base64之后的字符串,第3部分是乱码,应该是加密后的数据。

base64解码第2部分看看

1240

比较容易构造。

第3部分的长度是147,比较奇怪,因为json数据的长度是125。AES,DES,RC4加密后都和这个长度搭不上边,可能还拼接了其他东西。

逆向

1240

一个比较容易看出来的就是MD5,x22对应update方法,x23对应final方法。hook看看

public void hook_MD5() {
    IHookZz hookZz = HookZz.getInstance(emulator);
    hookZz.enable_arm_arm64_b_branch();
    hookZz.wrap(module.base + 0x35EC + 1, new WrapCallback() {
        @Override
        public void preCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            Pointer input = ctx.getPointerArg(1);
            byte[] inputHex = input.getByteArray(0, ctx.getR2Int());
            Inspector.inspect(inputHex, "Input(x22)");
        }

        @Override
        public void postCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
        }
    });

    hookZz.wrap(module.base + 0x3E10 + 1, new WrapCallback() {
        @Override
        public void preCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            Pointer output = ctx.getR1Pointer();
            ctx.push(output);
        }

        @Override
        public void postCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            Pointer output = ctx.pop();
            byte[] outputHex = output.getByteArray(0, 16);
            Inspector.inspect(outputHex, "Output(x23)");
        }
    });
    hookZz.disable_arm_arm64_b_branch();
}
public static void main(String[] args) {
    Qutoutiao test = new Qutoutiao();
    test.patch();
    test.hook_MD5();
    test.call_secure();
}
1240
1240

进行了两轮MD5,每轮的第1个调用是真实数据,其他是算法填充。cyberchef验证是标准MD5。

可以看到第二轮的MD5结果就是最后输出的第1部分。而第二次MD5输入的前面部分则是最后输出的第3部分的后面部分。

1240

再看看第二轮MD5输入的后面32字节。可以看出偶数位拼接起来就是第一次MD5的输出,而奇数位反向拼接起来则是原始输入的第二个参数(去掉-符号)。

1240

至此,第1部分的计算方式已经出来了。

接下来先看看第3部分的后面部分的计算方式。

1240
1240
1240

这个是AES的常量,从代码可以看出是CBC,进行了13+1=14轮操作,所以应该是AES-CBC-256加密,key的长度位32。

由于实现的时候把大部分代码都写在一起了,没有一个函数入口来hook,得到输入,key,iv。因此只能分析代码,下断点看看对应的变量。

1240

由于v112初始值为0,所以先进入else语句

1240

这里是输入与iv进行异或操作的地方,下断点看看。

1240
emulator.attach().addBreakPoint(module.base+0x7F84);
1240
1240

由于之前固定了随机数,一眼就看出它是随机数,不需要继续往下分析了

1240

从代码也能看出。

然后是key

1240
1240

同样下断点

emulator.attach().addBreakPoint(module.base+0x7F9C);
1240
1240

有了输出,key,iv,尝试解密看看

1240

说明找的是对的。

固定住uuid和iv,更换输入的第一个参数,其他部分不变。此时有个取巧的方案,固定uuid和iv,这样剩下的就不用分析了。

继续分析key的来源

1240

其中要关注的变量有v206, v191,还有个常量innoSecureParityTable256

下断点看看

v206

1240

之前讲过它的构成了。

v191

1240

更换输入后发现它是不变的。

然后根据代码实现一下即可。

table = [
    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1,
    0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0,
    0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1,
    0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1,
    0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1,
    0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0,
    0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1,
    0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
    0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1,
    0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0,
    0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1,
    0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1,
    0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1,
    0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0,
    0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1,
    0,
]

def make_key(v206):
    # v206 = bytes.fromhex('70 6E C6 C4 3D 19 5C 2F DC 58 3F 84 A7 FA 97 B768 35 C9 48 6A 5D 1A AB 51 13 66 E6 24 A5 E7 9B')
    v191 = bytes.fromhex('C2 65 D5 A2 40 46 A9 9B 98 D2 54 B0 1D A0 5F D2E6 7A 68 8E 6A EB 0F E1 CD A6 C2 CF F8 9F C4 56')
    bucket = []
    for j in range(32):
        v67 = v206[j]
        if table[v67] == 1:
            v68 = 0
            v69 = 8
            while 1:
                v70 = v67 >> v69
                v69 -= 1
                v68 = v68 | (((v70 ^ (v67 >> v69)) & 1) << v69)
                if not v69:
                    break
            # v68 = v67 ^ (v67 >> 1)
            v71 = v191[j] ^ v68
        else:
            v72 = 0
            v73 = 7
            v74 = 0
            for v72 in range(8):
                v75 = ((v191[j] ^ 0xff) >> v73) & 1
                v73 -= 1
                v76 = v75 << v72
                v72 += 1
                v74 |= v76
            # x = f'{v191[j] ^ 0xff:08b}'
            # v74 = int(x[::-1], 2)
            v71 = v67 ^ v74
        bucket.append(v71)
    print(bytes(bucket))
    print(bytes(bucket).hex())
    return bytes(bucket)
1240

接下来是找输出的第3部分的前面部分,共19个字节。

1240

先分析后16字节

1240
1240

v205是iv

1240

v208是第一次MD5的结果。

1240

然后实现一下即可

v201 = bytes(map(lambda x, y: ~(x ^ y) & 0xff, s0, iv))

接着分析前3个字节。

先看第1,第3个字节。

1240

v201正是后面的16字节,然后实现一下即可。

def calc_var(v201):
    v43 = 15
    v42 = 0
    for v43 in range(15, -1, -1):
        v45 = v201[15-v43]
        v42 |= (((v45 >> 3) & 1) << v43)
    print(v42)
    print(hex(v42))

    v47 = 16
    v49 = 0
    v46 = 0
    v48 = 0
    while 1:
        v50 = v47 - 1
        v51 = ((v42 >> v47) ^ (v42 >> (v47 - 1))) & 1
        if v49 > 7:
            v48 |= (v51 << v50)
        else:
            v46 |= (v51 << (v47 - 9))
        v49 += 1
        v47 -= 1
        if not v50:
            break
    print(v46, hex(v46))
    print(v48, hex(v48))
    return v46, v48

最后分析第2个字节。

1240

同样根据代码实现即可

n2 = -sum(v201) & 0xff

全部分析完了,最后把代码整合一下即可

1240

unidbg代码

public class Qutoutiao extends AbstractJni {
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;

    public static String pkgName = "com.jifen.qukan";
    public static String apkPath = "unidbg-android/src/test/java/com/qutoutiao/qutoutiao31061.apk";
    public static String soName = "InnoSecure";

    public Qutoutiao() {
        emulator = AndroidEmulatorBuilder.for32Bit().setProcessName(pkgName).build();
        Memory memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23));
        vm = emulator.createDalvikVM(new File(apkPath));
        vm.setJni(this);
        vm.setVerbose(true);
        DalvikModule dm = vm.loadLibrary(soName, true);
        module = dm.getModule();

        dm.callJNI_OnLoad(emulator);
    }

    public void patch() {
        // mov r0,1
        emulator.getMemory().pointer(module.base + 0x77e8).setInt(0, 0x0001f04f);
    }

    public void hook_libc() {
        IHookZz hookZz = HookZz.getInstance(emulator);
        hookZz.wrap(module.findSymbolByName("arc4random"), new WrapCallback() {
            @Override
            public void preCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            }

            @Override
            public void postCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
                ctx.setR0(1);
            }
        });
    }

    public void hook_MD5() {
        IHookZz hookZz = HookZz.getInstance(emulator);
        hookZz.enable_arm_arm64_b_branch();
        hookZz.wrap(module.base + 0x35EC + 1, new WrapCallback() {
            @Override
            public void preCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
                Pointer input = ctx.getPointerArg(1);
                byte[] inputHex = input.getByteArray(0, ctx.getR2Int());
                Inspector.inspect(inputHex, "Input(x22)");
            }

            @Override
            public void postCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            }
        });

        hookZz.wrap(module.base + 0x3E10 + 1, new WrapCallback() {
            @Override
            public void preCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
                Pointer output = ctx.getR1Pointer();
                ctx.push(output);
            }

            @Override
            public void postCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
                Pointer output = ctx.pop();
                byte[] outputHex = output.getByteArray(0, 16);
                Inspector.inspect(outputHex, "Output(x23)");
            }
        });
        hookZz.disable_arm_arm64_b_branch();
    }

    public void call_secure() {
        String p0 = "{\"name\":\"everhu\",\"version\":\"31061000\",\"OSVersion\":\"7.1.2\",\"dtu\":\"003\",\"network\":\"wifi\",\"versionName\":\"3.10.61.000.0927.1727\"}";
        String p1 = "9ba5e613-ab5d-4835-b7fa-84582f19c46e";
        String p2 = "3082021b30820184a0030201020204574beab6300d06092a864886f70d01010505003052310c300a06035504061303303231310b3009060355040813025348310b3009060355040713025348310b3009060355040a13025a48310b3009060355040b1302434e310e300c0603550403130551754b616e301e170d3136303533303037323433385a170d3431303532343037323433385a3052310c300a06035504061303303231310b3009060355040813025348310b3009060355040713025348310b3009060355040a13025a48310b3009060355040b1302434e310e300c0603550403130551754b616e30819f300d06092a864886f70d010101050003818d0030818902818100aa5bae49b771380e692444437b82b375cabdefb3f23307c29510653776b8e4115f776bea5eb6690285f97d4e6e8d0469e49f79ecba31e4b7fb85dd612ee6b27ef38502aa38d055ddad2aa7b52d19fb8d2aeeb59a830b91c341f1b467655e7313e9ff65feb6539bf1655f35a37e17faa94e506a08219df196730f45d9c1cd94d30203010001300d06092a864886f70d0101050500038181000e6cc9fb74aef11dd33d6603869a9db61b8dcedae77bc815433026693fe59fd4b75a3284170f8872737e55595c1fd40da3dfbe5ad8a4e96802f53637977f0eb6e9b0dc35161cbaed398b41ecd73c4009a1dae7bcb00b75c3f8d5792405bcc5e4602d9dff6a0dc4739240a3b42626f5efce4d7baea0fced2b13361cb4ded8ed0b";
        byte[] barr = new byte[] {-119,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,10,0,0,0,10,8,2,0,0,0,2,80,88,-22,0,0,1,110,73,68,65,84,120,1,0,31,0,-32,-1,0,120,-62,101,-43,-19,-94,64,70,-80,-72,-87,-101,-104,-27,-46,84,-80,13,-16,29,-96,95,67,-46,-26,122,-63,82,104,-114,0,31,0,-32,-1,0,106,99,-21,15,-31,94,-30,-51,-90,-62,118,-49,-8,-97,-22,36,-60,86,-51,0,0,29,-62,101,-43,-6,-94,64,70,49,0,31,0,-32,-1,0,-22,-87,-101,-104,-19,-46,84,-80,7,-54,29,-96,95,115,-46,-26,122,33,-81,104,-114,106,-23,-21,15,-31,-127,76,-51,-90,0,31,0,-32,-1,0,-62,32,-49,-8,-97,100,-88,-60,86,-51,0,0,90,0,-122,-109,-127,27,51,18,-122,-41,-35,-27,40,23,-20,-42,-40,98,0,31,0,-32,-1,0,-52,83,121,-87,97,21,37,-10,-17,63,110,19,86,114,-52,93,84,34,-24,-43,-29,50,23,-13,-29,11,30,-17,64,-65,0,31,0,-32,-1,0,-51,-109,-103,-45,-112,37,-105,102,-87,85,-13,50,22,92,-63,92,121,-27,-22,-37,101,-76,40,-112,49,-88,49,-11,-106,90,0,31,0,-32,-1,0,-114,-34,-72,118,-14,-42,118,-98,-10,-127,-24,120,46,11,78,-5,127,27,-25,-124,-66,-34,-17,-47,123,-90,96,113,-122,-67,0,31,0,-32,-1,0,70,46,92,-79,-108,-62,78,-86,38,10,-4,-3,-50,-34,-70,0,-73,59,82,-79,54,120,114,-105,-33,27,30,-9,-11,-48,0,31,0,-32,-1,0,124,48,-27,113,-51,-97,70,92,-35,39,98,25,30,-47,-43,29,-62,-73,105,-15,96,71,92,4,-54,39,-122,-88,48,-117,1,31,0,-32,-1,0,-103,-32,67,-62,-95,95,-106,-31,5,-44,-28,-7,25,41,112,-92,-59,-11,105,-127,-34,115,-87,-121,-88,118,-74,76,-22,27,-17,-86,-94,53,-55,-88,5,74,0,0,0,0,73,69,78,68,-82,66,96,-126};
        DvmClass clz = vm.resolveClass("com/inno/innosecure/InnoSecureUtils");
        String methodSign = "secure(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;I)[B";
        ByteArray ret = clz.callStaticJniMethodObject(emulator, methodSign,
                new StringObject(vm, p0),
                new StringObject(vm, p1),
                new StringObject(vm, p2),
                new ByteArray(vm, barr),
                null,
                null);
        byte[] barr2 = ret.getValue();
        byte[] barr3 = Base64.encodeBase64(barr2);
        System.out.println(new String(barr3));
        System.out.println(Arrays.toString(barr2));
    }

    public static void main(String[] args) {
        Qutoutiao test = new Qutoutiao();
        test.patch();
        test.hook_MD5();
        test.call_secure();
    }
}

你可能感兴趣的:(qu头条qdata字段unidbg逆向)