qu頭條qdata字段unidbg逆向
Java層
com.jifen.qukan.lib.report.ReportEncryptManager.encryptBodyMap
com.jifen.qukan.lib.report.ReportEncryptManager.encodeToString
com.inno.innosecure.InnoSecureMain.innoSecureEncodeV2
com.inno.innosecure.InnoSecureMain.secure
可以看到最后是在libInnoSecure.so
里蘸朋。
hook看看數(shù)據(jù)
android hooking watch class_method com.inno.innosecure.InnoSecureUtils.secure --dump-args --dump-return
入?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);
}
主動調(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();
}
}
運行多次后窑滞,發(fā)現(xiàn)結(jié)果不變琼牧,和frida調(diào)用表現(xiàn)不一致。這是因為unidbg的種子是固定的哀卫,導(dǎo)致生成的隨機數(shù)序列是固定的巨坊,進而導(dǎo)致結(jié)果是固定的。
固定隨機數(shù)
ida跳轉(zhuǎn)到0x5ead
innoSecure
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();
}
然后就報錯了移剪,跳轉(zhuǎn)過去看看究珊。
這個函數(shù)沒有實現(xiàn),這我也不會啊纵苛。剿涮。
換個思路言津,直接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();
}
結(jié)果出來了,之后的逆向?qū)⒒诖私Y(jié)果想括。
固定隨機數(shù)的好處就是每次輸出都不會變陷谱,方便分析。而且我們能一眼看出哪個是隨機數(shù)瑟蜈,做到心中有數(shù)烟逊。
分析輸出
真正開始逆向之前看看輸出的組成方式,base64解碼看看輸出铺根。
可以大致看出輸出由3部分組成宪躯,各部分用.
連接训枢,第1部分是32位字符串芒珠,應(yīng)該是個MD5;第2部分是base64之后的字符串遗嗽,第3部分是亂碼掂林,應(yīng)該是加密后的數(shù)據(jù)臣缀。
base64解碼第2部分看看
比較容易構(gòu)造。
第3部分的長度是147泻帮,比較奇怪精置,因為json數(shù)據(jù)的長度是125。AES锣杂,DES脂倦,RC4加密后都和這個長度搭不上邊,可能還拼接了其他東西元莫。
逆向
一個比較容易看出來的就是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();
}
進行了兩輪MD5火欧,每輪的第1個調(diào)用是真實數(shù)據(jù),其他是算法填充朽基。cyberchef驗證是標(biāo)準(zhǔn)MD5布隔。
可以看到第二輪的MD5結(jié)果就是最后輸出的第1部分离陶。而第二次MD5輸入的前面部分則是最后輸出的第3部分的后面部分稼虎。
再看看第二輪MD5輸入的后面32字節(jié)≌信伲可以看出偶數(shù)位拼接起來就是第一次MD5的輸出霎俩,而奇數(shù)位反向拼接起來則是原始輸入的第二個參數(shù)(去掉-
符號)。
至此,第1部分的計算方式已經(jīng)出來了打却。
接下來先看看第3部分的后面部分的計算方式杉适。
這個是AES的常量,從代碼可以看出是CBC柳击,進行了13+1=14
輪操作猿推,所以應(yīng)該是AES-CBC-256加密,key的長度位32捌肴。
由于實現(xiàn)的時候把大部分代碼都寫在一起了蹬叭,沒有一個函數(shù)入口來hook,得到輸入状知,key秽五,iv。因此只能分析代碼饥悴,下斷點看看對應(yīng)的變量坦喘。
由于v112初始值為0,所以先進入else
語句
這里是輸入與iv進行異或操作的地方西设,下斷點看看瓣铣。
emulator.attach().addBreakPoint(module.base+0x7F84);
由于之前固定了隨機數(shù),一眼就看出它是隨機數(shù)贷揽,不需要繼續(xù)往下分析了
從代碼也能看出坯沪。
然后是key
同樣下斷點
emulator.attach().addBreakPoint(module.base+0x7F9C);
有了輸出,key擒滑,iv腐晾,嘗試解密看看
說明找的是對的。
固定住uuid和iv丐一,更換輸入的第一個參數(shù)藻糖,其他部分不變。此時有個取巧的方案库车,固定uuid和iv巨柒,這樣剩下的就不用分析了。
繼續(xù)分析key的來源
其中要關(guān)注的變量有v206, v191
柠衍,還有個常量innoSecureParityTable256
下斷點看看
v206
之前講過它的構(gòu)成了洋满。
v191
更換輸入后發(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)
接下來是找輸出的第3部分的前面部分牺勾,共19個字節(jié)。
先分析后16字節(jié)
v205
是iv
v208
是第一次MD5的結(jié)果阵漏。
然后實現(xiàn)一下即可
v201 = bytes(map(lambda x, y: ~(x ^ y) & 0xff, s0, iv))
接著分析前3個字節(jié)驻民。
先看第1翻具,第3個字節(jié)。
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é)。
同樣根據(jù)代碼實現(xiàn)即可
n2 = -sum(v201) & 0xff
全部分析完了柠硕,最后把代碼整合一下即可
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();
}
}