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看看數(shù)據(jù)

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

入?yún)?是json數(shù)據(jù),入?yún)?是uuid齐婴,入?yún)?茄厘,4是固定的(本機固定矮冬,不同設(shè)備未測試)。輸出做個base64就是qdata

再用frida進行主動調(diào)用

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

主動調(diào)用了2次次哈,結(jié)果不一樣胎署,說明可能有時間戳或隨機數(shù)參與計算。

unidbg實現(xiàn)

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

運行多次后窑滞,發(fā)現(xiàn)結(jié)果不變琼牧,和frida調(diào)用表現(xiàn)不一致。這是因為unidbg的種子是固定的哀卫,導(dǎo)致生成的隨機數(shù)序列是固定的巨坊,進而導(dǎo)致結(jié)果是固定的。

固定隨機數(shù)

1240

ida跳轉(zhuǎn)到0x5ead

1240
1240

innoSecure

1240
1240
1240
1240

innoSecure函數(shù)有900行左右此改,把很多東西都塞到這里實現(xiàn)了趾撵,看起來又臭又長。

其中有個arc4random函數(shù)共啃,一看就是用于生成隨機數(shù)的占调,hook它將隨機數(shù)固定。

// fail
public void hook_libc() {
    IHookZz hookZz = HookZz.getInstance(emulator);
    hookZz.wrap(module.findSymbolByName("arc4random"), new WrapCallback<HookZzArm32RegisterContext>() {
        @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

然后就報錯了移剪,跳轉(zhuǎn)過去看看究珊。

1240

這個函數(shù)沒有實現(xiàn),這我也不會啊纵苛。剿涮。

1240

換個思路言津,直接patch調(diào)用arc4random函數(shù)這條指令,將r0設(shè)為1取试,相當(dāng)于每次隨機數(shù)函數(shù)的返回值為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

結(jié)果出來了,之后的逆向?qū)⒒诖私Y(jié)果想括。

固定隨機數(shù)的好處就是每次輸出都不會變陷谱,方便分析。而且我們能一眼看出哪個是隨機數(shù)瑟蜈,做到心中有數(shù)烟逊。

分析輸出

真正開始逆向之前看看輸出的組成方式,base64解碼看看輸出铺根。

1240

可以大致看出輸出由3部分組成宪躯,各部分用.連接训枢,第1部分是32位字符串芒珠,應(yīng)該是個MD5;第2部分是base64之后的字符串遗嗽,第3部分是亂碼掂林,應(yīng)該是加密后的數(shù)據(jù)臣缀。

base64解碼第2部分看看

1240

比較容易構(gòu)造。

第3部分的長度是147泻帮,比較奇怪精置,因為json數(shù)據(jù)的長度是125。AES锣杂,DES脂倦,RC4加密后都和這個長度搭不上邊,可能還拼接了其他東西元莫。

逆向

1240

一個比較容易看出來的就是MD5赖阻,x22對應(yīng)update方法,x23對應(yīng)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<HookZzArm32RegisterContext>() {
        @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<HookZzArm32RegisterContext>() {
        @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個調(diào)用是真實數(shù)據(jù),其他是算法填充朽基。cyberchef驗證是標(biāo)準(zhǔn)MD5布隔。

可以看到第二輪的MD5結(jié)果就是最后輸出的第1部分离陶。而第二次MD5輸入的前面部分則是最后輸出的第3部分的后面部分稼虎。

1240

再看看第二輪MD5輸入的后面32字節(jié)≌信伲可以看出偶數(shù)位拼接起來就是第一次MD5的輸出霎俩,而奇數(shù)位反向拼接起來則是原始輸入的第二個參數(shù)(去掉-符號)。

1240

至此,第1部分的計算方式已經(jīng)出來了打却。

接下來先看看第3部分的后面部分的計算方式杉适。

1240
1240
1240

這個是AES的常量,從代碼可以看出是CBC柳击,進行了13+1=14輪操作猿推,所以應(yīng)該是AES-CBC-256加密,key的長度位32捌肴。

由于實現(xiàn)的時候把大部分代碼都寫在一起了蹬叭,沒有一個函數(shù)入口來hook,得到輸入状知,key秽五,iv。因此只能分析代碼饥悴,下斷點看看對應(yīng)的變量坦喘。

1240

由于v112初始值為0,所以先進入else語句

1240

這里是輸入與iv進行異或操作的地方西设,下斷點看看瓣铣。

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

由于之前固定了隨機數(shù),一眼就看出它是隨機數(shù)贷揽,不需要繼續(xù)往下分析了

1240

從代碼也能看出坯沪。

然后是key

1240
1240

同樣下斷點

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

有了輸出,key擒滑,iv腐晾,嘗試解密看看

1240

說明找的是對的。

固定住uuid和iv丐一,更換輸入的第一個參數(shù)藻糖,其他部分不變。此時有個取巧的方案库车,固定uuid和iv巨柒,這樣剩下的就不用分析了。

繼續(xù)分析key的來源

1240

其中要關(guān)注的變量有v206, v191柠衍,還有個常量innoSecureParityTable256

下斷點看看

v206

1240

之前講過它的構(gòu)成了洋满。

v191

1240

更換輸入后發(fā)現(xiàn)它是不變的。

然后根據(jù)代碼實現(xiàn)一下即可珍坊。

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個字節(jié)。

1240

先分析后16字節(jié)

1240
1240

v205是iv

1240

v208是第一次MD5的結(jié)果阵漏。

1240

然后實現(xiàn)一下即可

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

接著分析前3個字節(jié)驻民。

先看第1翻具,第3個字節(jié)。

1240

v201正是后面的16字節(jié)回还,然后實現(xiàn)一下即可裆泳。

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個字節(jié)。

1240

同樣根據(jù)代碼實現(xiàn)即可

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<HookZzArm32RegisterContext>() {
            @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<HookZzArm32RegisterContext>() {
            @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<HookZzArm32RegisterContext>() {
            @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án)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載工禾,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末蝗柔,一起剝皮案震驚了整個濱河市帜篇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌诫咱,老刑警劉巖笙隙,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異坎缭,居然都是意外死亡竟痰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門掏呼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坏快,“玉大人,你說我怎么就攤上這事憎夷∶Ш瑁” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵拾给,是天一觀的道長祥得。 經(jīng)常有香客問我,道長蒋得,這世上最難降的妖魔是什么级及? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮额衙,結(jié)果婚禮上饮焦,老公的妹妹穿的比我還像新娘。我一直安慰自己窍侧,他們只是感情好县踢,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伟件,像睡著了一般硼啤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锋爪,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天丙曙,我揣著相機與錄音,去河邊找鬼其骄。 笑死亏镰,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拯爽。 我是一名探鬼主播索抓,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毯炮!你這毒婦竟也來了逼肯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤桃煎,失蹤者是張志新(化名)和其女友劉穎篮幢,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體为迈,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡三椿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了葫辐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搜锰。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖耿战,靈堂內(nèi)的尸體忽然破棺而出蛋叼,到底是詐尸還是另有隱情,我是刑警寧澤剂陡,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布狈涮,位于F島的核電站,受9級特大地震影響鸭栖,放射性物質(zhì)發(fā)生泄漏薯嗤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一纤泵、第九天 我趴在偏房一處隱蔽的房頂上張望骆姐。 院中可真熱鬧,春花似錦捏题、人聲如沸玻褪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽带射。三九已至,卻和暖如春循狰,著一層夾襖步出監(jiān)牢的瞬間窟社,已是汗流浹背券勺。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留灿里,地道東北人关炼。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像匣吊,于是被迫代替她去往敵國和親儒拂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容