一
分析总结
二
目标选取
三
开发环境
四
模拟执行
五
算法移植
Find native function Java_com_bytedance_frameworks_encryptor_EncryptorUtil_ttEncrypt => RX@0x40007a38[libEncryptor.so]0x7a38
// 0x10为传进来的byte[]大小,这个是已知的
emulator.traceWrite(0x40358000, 0x40358000 + 0x10 + 118);
74 63 05 10 ==>0x10056374
00 00 ==> 0x2be0// 0x1c184
A0 BB 10 FA EC 38 50 03 EA 42 C6 94 15 ED CD 30(0x35038ecfa10bba0、0x30cded1594c642ea)
B6 5F F5 E8 25 43 A3 66 D4 B8 E7 FB D7 F3 89 77 (0x66a34325e8f55fb6、0x7789f3d7fbe7b8d4)// 0x2a58
[01:48:41 773] Memory WRITE at 0x40358026, data size = 8, data value = 0xeb12c44a6b02c09, PC=RX@0x40002a58[libEncryptor.so]0x2a58, LR=RX@0x40002a4c[libEncryptor.so]0x2a4c
[01:48:41 773] Memory WRITE at 0x4035802e, data size = 8, data value = 0x632b08e36313439e, PC=RX@0x40002a58[libEncryptor.so]0x2a58, LR=RX@0x40002a4c[libEncryptor.so]0x2a4c
[01:48:41 773] Memory WRITE at 0x40358036, data size = 8, data value = 0x241e2a664df9f031, PC=RX@0x40002a58[libEncryptor.so]0x2a58, LR=RX@0x40002a4c[libEncryptor.so]0x2a4c
[01:48:41 773] Memory WRITE at 0x4035803e, data size = 8, data value = 0x2bee5c58693bd0fc, PC=RX@0x40002a58[libEncryptor.so]0x2a58, LR=RX@0x40002a4c[libEncryptor.so]0x2a4c
[01:48:41 773] Memory WRITE at 0x40358046, data size = 8, data value = 0x468e9bebbf9629eb, PC=RX@0x40002a58[libEncryptor.so]0x2a58, LR=RX@0x40002a4c[libEncryptor.so]0x2a4c
[01:48:41 773] Memory WRITE at 0x4035804e, data size = 8, data value = 0x2a698ed9942a3431, PC=RX@0x40002a58[libEncryptor.so]0x2a58, LR=RX@0x40002a4c[libEncryptor.so]0x2a4c
[01:48:41 773] Memory WRITE at 0x40358056, data size = 8, data value = 0x713bbf110c38b4, PC=RX@0x40002a58[libEncryptor.so]0x2a58, LR=RX@0x40002a4c[libEncryptor.so]0x2a4c
[01:48:41 773] Memory WRITE at 0x4035805e, data size = 8, data value = 0x217a8beac056e0c6, PC=RX@0x40002a58[libEncryptor.so]0x2a58, LR=RX@0x40002a4c[libEncryptor.so]0x2a4c
[01:48:41 773] Memory WRITE at 0x40358066, data size = 8, data value = 0xdc330f68f180331e, PC=RX@0x40002a58[libEncryptor.so]0x2a58, LR=RX@0x40002a4c[libEncryptor.so]0x2a4c
[01:48:41 773] Memory WRITE at 0x4035806e, data size = 8, data value = 0xe121d61a37fcf7dc, PC=RX@0x40002a58[libEncryptor.so]0x2a58, LR=RX@0x40002a4c[libEncryptor.so]0x2a4c
[01:48:41 773] Memory WRITE at 0x40358076, data size = 8, data value = 0x77f78e1f1dd196d1, PC=RX@0x40002a88[libEncryptor.so]0x2a88, LR=RX@0x40002a84[libEncryptor.so]0x2a84
[01:48:41 773] Memory WRITE at 0x4035807e, data size = 8, data value = 0x2e7d43264681b810, PC=RX@0x40002a88[libEncryptor.so]0x2a88, LR=RX@0x40002a84[libEncryptor.so]0x2a8409 2C B0 A6 44 2C B1 0E 9E 43 .....w.,..D,...C
0030: 13 63 E3 08 2B 63 31 F0 F9 4D 66 2A 1E 24 FC D0 .c..+c1..Mf*.$..
0040: 3B 69 58 5C EE 2B EB 29 96 BF EB 9B 8E 46 31 34 ;iX\.+.).....F14
0050: 2A 94 D9 8E 69 2A B4 38 0C 11 BF 3B 71 00 C6 E0 *...i*.8...;q...
0060: 56 C0 EA 8B 7A 21 1E 33 80 F1 68 0F 33 DC DC F7 V...z!.3..h.3...
0070: FC 37 1A D6 21 E1 D1 96 D1 1D 1F 8E F7 77 10 B8 .7..!........w..
0080: 81 46 26 43 7D 2E .F&C}.
debugger.addBreakPoint(module, 0x3C28);
backend.hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == module.base + 0x3C28){
Number x0 = backend.reg_read(Arm64Const.UC_ARM64_REG_X0);
Number x20 = backend.reg_read(Arm64Const.UC_ARM64_REG_X20);
long m0 = x20.longValue()-module.base;
long m1 = x0.longValue()-module.base;
System.out.println("直接调用的是-->" + Long.toHexString(m0));
System.out.println("间接调用的是-->" + Long.toHexString(m1));
}
}@Override
public void onAttach(UnHook unHook) {}
@Override
public void detach() {}
}, module.base, module.base + module.size, null);
直接调用的是-->2c0c
间接调用的是-->2b40
直接调用的是-->2c0c
间接调用的是-->2b5c
直接调用的是-->2c0c
间接调用的是-->2b40
直接调用的是-->2c0c
间接调用的是-->2b40
直接调用的是-->2c0c
间接调用的是-->2b94
直接调用的是-->2c0c
间接调用的是-->2b40
直接调用的是-->2c0c
间接调用的是-->2ba8
直接调用的是-->2c0c
间接调用的是-->2bb8
直接调用的是-->2c0c
间接调用的是-->2bb8
直接调用的是-->2c0c
间接调用的是-->2bc8
直接调用的是-->2c0c
间接调用的是-->2be8
直接调用的是-->2c0c
间接调用的是-->2c04
直接调用的是-->2c0c
间接调用的是-->2c04
直接调用的是-->2c0c
间接调用的是-->2c04
Map<Integer, String> map = new HashMap<>();
map.put(0x2c0c, "跳板函数,x0为要执行的函数,x1为参数(指针)");
map.put(0x2b40, "malloc");
map.put(0x2b5c, "time、srand、rand随机数函数");
map.put(0x2b94, "又跳到另外一个大的函数过去了(跟入口的0x2C18是一致)");
map.put(0x2ba8, "散列家族算法(6A58)");
map.put(0x2bb8, "memcpy1");
map.put(0x2bc8, "memcpy2");
map.put(0x2be8, "aes相关函数");
map.put(0x2c04, "free");Backend backend = emulator.getBackend();
backend.hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == module.base + 0x3C28){
Number x0 = backend.reg_read(Arm64Const.UC_ARM64_REG_X0);
Number x20 = backend.reg_read(Arm64Const.UC_ARM64_REG_X20);
long m0 = x20.longValue()-module.base;
long m1 = x0.longValue()-module.base;
System.out.println("直接调用的是-->" + Long.toHexString(m0)+ "\t" + map.get((int)m0));
System.out.println("间接调用的是-->" + Long.toHexString(m1)+ "\t" + map.get((int)m1));
}
}@Override
public void onAttach(UnHook unHook) {}
@Override
public void detach() {}
}, module.base, module.base + module.size, null);
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2b40 malloc
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2b5c time、srand、rand随机数函数
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2b40 malloc
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2b40 malloc
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2b94 又跳到另外一个大的函数过去了(跟入口的0x2C18是一致)
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2b40 malloc
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2ba8 散列家族算法(6A58)
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2bb8 memcpy1
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2bb8 memcpy1
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2bc8 memcpy2
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2be8 aes相关函数
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2c04 free
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2c04 free
直接调用的是-->2c0c 跳板函数,x0为要执行的函数,x1为参数(指针)
间接调用的是-->2c04 free
Map<Integer, String> map = new HashMap<>();
map.put(0x2c0c, "跳板函数,x0为要执行的函数,x1为参数(指针)");
map.put(0x2b40, "malloc");
map.put(0x2b5c, "time、srand、rand随机数函数");
map.put(0x2b94, "又跳到另外一个大的函数过去了(跟入口的0x2C18是一致)");
map.put(0x2ba8, "散列家族算法(6A58)");
map.put(0x2bb8, "memcpy1");
map.put(0x2bc8, "memcpy2");
map.put(0x2be8, "aes相关函数");
map.put(0x2c04, "free");map.put(0x45bc, "跳板函数,x0为要执行的函数,x1为参数(指针)");
map.put(0x44c4, "malloc");
map.put(0x44e0, "散列家族算法(6A58)");
map.put(0x44f0, "memcpy");
map.put(0x4500, "查表");
map.put(0x45B4, "free");Backend backend = emulator.getBackend();
backend.hook_add_new(new CodeHook() {
@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == module.base + 0x3C28 || address == module.base + 0x55D8){
Number x0 = backend.reg_read(Arm64Const.UC_ARM64_REG_X0);
Number x20 = backend.reg_read(Arm64Const.UC_ARM64_REG_X20);
long m0 = x20.longValue()-module.base;
long m1 = x0.longValue()-module.base;
System.out.println("直接调用的是-->" + Long.toHexString(m0)+ "\t" + map.get((int)m0));
System.out.println("间接调用的是-->" + Long.toHexString(m1)+ "\t" + map.get((int)m1));
}
}@Override
public void onAttach(UnHook unHook) {}
@Override
public void detach() {}
}, module.base, module.base + module.size, null);
// 这里使用Dobby会异常,别问我为啥知道。嘿嘿。想知道这个又可以水一篇文章了,哈哈哈哈
IHookZz hookZz = HookZz.getInstance(emulator); // 加载HookZz,支持inline hook,文档看https://github.com/jmpews/HookZz
hookZz.wrap(module.base + 0x6A58, new WrapCallback<HookZzArm64RegisterContext>() { // inline wrap导出函数
@Override
public void preCall(Emulator<?> emulator, HookZzArm64RegisterContext ctx, HookEntryInfo info) {
UnidbgPointer x0 = ctx.getPointerArg(0);
int x1 = ctx.getIntArg(1);
UnidbgPointer x2 = ctx.getPointerArg(2);
byte[] input = x0.getByteArray(0, x1);
Inspector.inspect(input, "input(sha512)");
ctx.push(x2);
emulator.getUnwinder().unwind();
}
@Override
public void postCall(Emulator<?> emulator, HookZzArm64RegisterContext ctx, HookEntryInfo info) {
UnidbgPointer x2 = ctx.pop();
int length = 0x40;
Inspector.inspect(x2.getByteArray(0, length), "正式结果");
}
});
>-----------------------------------------------------------------------------<
[02:55:46 216]input(sha512), md5=7e6de8344f55d460143710510155b657, hex=2ad949a94f9867924645bdfc952302dea3193a95cbe9913e3bbea28a659eaa90
size: 32
0000: 2A D9 49 A9 4F 98 67 92 46 45 BD FC 95 23 02 DE *.I.O.g.FE...#..
0010: A3 19 3A 95 CB E9 91 3E 3B BE A2 8A 65 9E AA 90 ..:....>;...e...>-----------------------------------------------------------------------------<
[02:55:46 234]正式结果, md5=bed9304b171af26ae94b5fcaccd1fd6b, hex=17b4b1b1094010ca669a8c2116ad14a25b40302b693684f23686cad7817f5295064c06ab34f5f55a8dfceee08bd2ae3a8cb12d52fbc7981e0b4ed5f995b921eb
size: 64
0000: 17 B4 B1 B1 09 40 10 CA 66 9A 8C 21 16 AD 14 A2 [email protected]..!....
0010: 5B 40 30 2B 69 36 84 F2 36 86 CA D7 81 7F 52 95 [@0+i6..6.....R.
0020: 06 4C 06 AB 34 F5 F5 5A 8D FC EE E0 8B D2 AE 3A .L..4..Z.......:
0030: 8C B1 2D 52 FB C7 98 1E 0B 4E D5 F9 95 B9 21 EB ..-R.....N....!.
^-----------------------------------------------------------------------------^
hookZz.wrap(module.base + 0x2B5C, new WrapCallback<HookZzArm64RegisterContext>() { // inline wrap导出函数
@Override
public void preCall(Emulator<?> emulator, HookZzArm64RegisterContext ctx, HookEntryInfo info) {
UnidbgPointer x0 = ctx.getPointerArg(0);
ctx.push(x0);
}
@Override
public void postCall(Emulator<?> emulator, HookZzArm64RegisterContext ctx, HookEntryInfo info) {
UnidbgPointer x0 = ctx.pop();
Inspector.inspect(x0.getPointer(0).getByteArray(0, 0x100), "测试哦");
}
});
debugger.addBreakPoint(module, 0x2948);
hookZz.wrap(module.base + 0x2948, new WrapCallback<HookZzArm64RegisterContext>() { @Override
public void preCall(Emulator<?> emulator, HookZzArm64RegisterContext ctx, HookEntryInfo info) {
UnidbgPointer x0 = ctx.getPointerArg(0);
int x1 = ctx.getIntArg(1);
UnidbgPointer x2 = ctx.getPointerArg(2);
UnidbgPointer x3 = ctx.getPointerArg(3);
int x4 = ctx.getIntArg(4);byte[] key = x0.getByteArray(0, x1);
byte[] iv = x2.getByteArray(0, x1);
byte[] input = x3.getByteArray(0, x4);Inspector.inspect(key, "key");
Inspector.inspect(iv, "iv");
Inspector.inspect(input, "input(aes)");UnidbgPointer x5 = ctx.getPointerArg(5);
int x6 = ctx.getPointerArg(6).getInt(0);
ctx.push(x5, x6);
}
@Override
public void postCall(Emulator<?> emulator, HookZzArm64RegisterContext ctx, HookEntryInfo info) {
UnidbgPointer x5 = ctx.pop();
int x6 = ctx.pop();
Inspector.inspect(x5.getByteArray(0, x6), "aes加密结果");
}
});
0040: 4D D4 C2 E6 B8 31 62 09 0E 52 B3 C7 A6 73 3B A4 M....1b..R...s;.
0050: 1C B2 46 2B 82 9A B5 8A 19 6B 39 DB 57 17 75 24 ..F+.....k9.W.u$
0060: F4 9B AF 7F 08 E8 D6 8D 26 A7 2E 37 C1 A9 5A 2F ........&..7..Z/
0070: 1F 05 A5 18 92 AE F2 94 97 32 B6 2A 38 AA DD 58 .........2.*8..X
六
最后总结
七
2023年12月20日10点34分更新
debugger.addBreakPoint(module, 0x4500);
0-->80 60 35 40
1-->00 00 00 00
2-->40 00 00 00v1 = result[2];
v2 = *result;
v3 = result[1];就可以直到v1=0x40,v2为0x40356080,v3为0
v1 =
b0x4560
>>> q0=0xa43b73a6c7b3520e096231b8e6c2d44d(1.8056244479338115E-263, -3.7768713601031674E-134) q1=0x24751757db396b198ab59a822b46b21c(-4.496232995265719E-257, 4.642831181428702E-133)
q0=0x2f5aa9c1372ea7268dd6e8087faf9bf4(-5.367597597728704E-242, 1.4054386263309782E-80) q1=0x58ddaa382ab6329794f2ae9218a5051f(-9.09210480120694E-208, 1.1969099196948154E120)
0040: 4D D4 C2 E6 B8 31 62 09 0E 52 B3 C7 A6 73 3B A4 M....1b..R...s;.
0050: 1C B2 46 2B 82 9A B5 8A 19 6B 39 DB 57 17 75 24 ..F+.....k9.W.u$
0060: F4 9B AF 7F 08 E8 D6 8D 26 A7 2E 37 C1 A9 5A 2F ........&..7..Z/
0070: 1F 05 A5 18 92 AE F2 94 97 32 B6 2A 38 AA DD 58 .........2.*8..X
看雪ID:陈可牛
https://bbs.kanxue.com/user-home-794149.htm
# 往期推荐
2、在Windows平台使用VS2022的MSVC编译LLVM16
3、神挡杀神——揭开世界第一手游保护nProtect的神秘面纱
球分享
球点赞
球在看