某团外卖APP的风控分析(转).
本文目的只是学习逆向技巧和学习产品思路,比较敏感的部分不会详述,还请谅解,文章较长,慎
入。以下分析是本人拙见,如有不妥之处,还望多批评指正。理论上某团系所有APP只要用到这个sdk的都是一样的。(本文章转子看雪论坛 "我是小三")如有侵权,请作者联系删除.(由于原作者发帖不久被删帖,故转发该贴到本个人博客)
一、 电商类APP业务风险类型
二、 设备指纹在业务中的应用
三、 整体框架
四、 初始化流程分析
五、 反爬虫mtgsig签名
六、 设备指纹分析
七、 设备指纹攻击
八、 黑产工具特征检测
九、总结一、电商类APP业务风险类型:
1. 电商行业的各个业务场景面临不同的风险种类:客户端漏洞利用、协议逆向、注册小号、商品信息被
抓取、推广渠道作弊、营销活动被薅羊毛、商品秒杀等。
大多的防御方案是通过端上安全、链路安全、接口和数据传输安全保护,再借助设备安全核验技术、
人机识别及时发现各种模拟行为和异操作风险、同时集合风控策略实现多节点防护。二、设备指纹在业务中的应用
1. 设备指纹技术是使用更多的信息来完成对终端设备的唯一性识别,在业务中可以有效辨别设备是真实
用户还是机器在注册、登录,及时检测出单设备登入多帐号、防止批量注册、登录等操作行为。三、设备指纹在业务中的应用
1. 因为框架流程过于复杂,我将框架分为两个部分,一是初始化,二是设备指纹,这样会更清楚些,如图四、设备指纹在业务中的应用
1. 初始化准备
0x001. java层调用init()初始化,获取Context,包名,AppInfo,XML配置信息等,然后加载so libmtguard.so
在so中注册一个Native方法,该Native方法传入不同的数字代表不同的功能,代码如下所示:
Lcom/meituan/android/common/mtguard/MTGuard;->loadSo(Ljava/lang/String;)V
System.loadLibrary("mtguard");
//注册Native方法
private static native Object[] main(int arg0, Object[] arg1)//arg0:传入不同的编号走不同的逻辑,arg1:参数
2. 系统环境检测
0x001.调用Native层Object[] v12_2 = NBridge.main3(1, new Object[1]),传入参数为1,表示检测环境, 检测系统目录中是否有ls文件且是否为elf格式:
.text:B1BF744E 01 26 MOVS R6, #1
.text:B1BF7450 2E 70 STRB R6, [R5]
.text:B1BF7452 20 48 LDR R0, =(aSystemBinLs - 0xB1BF7458) ; "/system/bin/ls"
.text:B1BF7454 78 44 ADD R0, PC ; "/system/bin/ls" ; file
.text:B1BF7456 00 25 MOVS R5, #0
.text:B1BF7458 29 00 MOVS R1, R5 ; oflag
.text:B1BF745A CF F7 A0 EC BLX open
.text:B1BF745E 04 00 MOVS R4, R0
.text:B1BF7460 00 2C CMP R4, #0
.text:B1BF7462 25 DB BLT loc_B1BF74B0
.text:B1BF7464 01 AD ADD R5, SP, #0x28+buf
.text:B1BF7466 14 22 MOVS R2, #0x14 ; nbytes
.text:B1BF7468 20 00 MOVS R0, R4 ; fd
.text:B1BF746A 29 00 MOVS R1, R5 ; buf
.text:B1BF746C CF F7 10 EE BLX read
.text:B1BF7470 14 28 CMP R0, #0x14
.text:B1BF7472 18 D1 BNE loc_B1BF74A6
.text:B1BF7474 28 78 LDRB R0, [R5]
.text:B1BF7476 7F 28 CMP R0, #0x7F
.text:B1BF7478 15 D1 BNE loc_B1BF74A6
.text:B1BF747A 01 A8 ADD R0, SP, #0x28+buf
.text:B1BF747C 40 78 LDRB R0, [R0,#1]
.text:B1BF747E 45 28 CMP R0, #0x45 ; 'E'
.text:B1BF7480 11 D1 BNE loc_B1BF74A6
.text:B1BF7482 01 A8 ADD R0, SP, #0x28+buf
.text:B1BF7484 80 78 LDRB R0, [R0,#2]
.text:B1BF7486 4C 28 CMP R0, #0x4C ; 'L'
.text:B1BF7488 0D D1 BNE loc_B1BF74A6
.text:B1BF748A 01 A8 ADD R0, SP, #0x28+buf
.text:B1BF748C C0 78 LDRB R0, [R0,#3]
.text:B1BF748E 46 28 CMP R0, #0x46 ; 'F'
.text:B1BF7490 09 D1 BNE loc_B1BF74A6
.text:B1BF7492 01 A8 ADD R0, SP, #0x28+buf
.text:B1BF7494 80 7C LDRB R0, [R0,#0x12]
.text:B1BF7496 3E 28 CMP R0, #0x3E ; '>'
.text:B1BF7498 01 D0 BEQ loc_B1BF749E
.text:B1BF749A 03 28 CMP R0, #3
.text:B1BF749C 03 D1 BNE loc_B1BF74A6
.text:B1BF749E
.text:B1BF749E loc_B1BF749E
.text:B1BF749E 20 00 MOVS R0, R4 ; fd
.text:B1BF74A0 CF F7 88 EC BLX close
0x002.检测root:
//检测root 直接用svc指令,防止hook
.text:BB9F5444 ;faccessat
.text:BB9F5444 F0 B5 PUSH {R4-R7,LR}
.text:BB9F5446 03 AF ADD R7, SP, #0xC
.text:BB9F5448 0B 00 MOVS R3, R1
.text:BB9F544A 04 00 MOVS R4, R0
.text:BB9F544C 63 20 MOVS R0, #0x63 ; 'c'
.text:BB9F544E C5 43 MVNS R5, R0
.text:BB9F5450 A7 20 MOVS R0, #0xA7
.text:BB9F5452 46 00 LSLS R6, R0, #1
.text:BB9F5454 28 46 MOV R0, R5
.text:BB9F5456 21 46 MOV R1, R4
.text:BB9F5458 1A 46 MOV R2, R3
.text:BB9F545A 37 46 MOV R7, R6
.text:BB9F545C 00 DF SVC 0
.text:BB9F545E 03 46 MOV R3, R0
.text:BB9F5460 18 00 MOVS R0, R3
.text:BB9F5462 F0 BD POP {R4-R7,PC}
//检测文件特征
/system/bin/su
/system/bin/360s
/system/xbin/krdem
/system/xbin/ku.sud
/system/xbin/ksud
/system/bin/.usr/.ku
/system/xbin/ku.sud.tmp
/system/bin/ddexe_real
/system/bin/.krsh
/system/bin/.suv
/system/bin/debuggerd-ku.bak
/system/xbin/kugote
/system/xbin/kugote
/system/usr/ikm/ikmsu
/system/etc/kds
/system/xbin/start_kusud.sh
/system/bin/ddexe-tcs.bak
//检测结果
1|2|3|32 //字符串的编号
0x003.检测XPOSED、代理、ROM是否为自己编译的:
//检测
de.robv.android.xposed.XposedBridge
//检测代理
http.proxyHost
https.proxyHost
getProperty
0x004.检测关键方法是否被hook:
//检测方法是否被hook
传入方法首地址进行对比 0x780x5F 0xF8DF
//如果检测到第一个方法被hook,结果如下
1|
如果检测到第2个方法被hook,结果如下
1|2|
如果检测到第3个方法被hook,结果如下
1|2|3|
0x005.其它检测,代码如下:
boolean v2 = MTGuard.isEmu();
boolean v3 = MTGuard.isRoot();
boolean v4 = MTGuard.hasMalware();
boolean v5 = MTGuard.isDarkSystem();
boolean v6 = MTGuard.isVirtualLocation();
boolean v7 = MTGuard.isRemoteCall();
boolean v8 = MTGuard.isSigCheckOK();
boolean v11 = MTGuard.inSandBox();
boolean v13 = MTGuard.isHook();
boolean v14 = MTGuard.isDebug();
boolean v15 = MTGuard.isProxy();
boolean v16 = MTGuard.isCameraHack();
最终都会走到Native方法中去
private static native Object[] main(int arg0, Object[] arg1);
3. 读取资源文件并解密
0x001.读文件META-INF/SANKUAI.RSA计算MD5,代码如下:
.text:B65E1FE4 F0 B5 PUSH {R4-R7,LR}
.text:B65E1FE6 03 AF ADD R7, SP, #0xC
.text:B65E1FE8 8F B0 SUB SP, SP, #0x3C
.text:B65E1FEA 0E 00 MOVS R6, R1
.text:B65E1FEC 2D 49 LDR R1, =(__stack_chk_guard_ptr - 0xB65E1FF2)
.text:B65E1FEE 79 44 ADD R1, PC ; __stack_chk_guard_ptr
.text:B65E1FF0 0C 68 LDR R4, [R1] ; __stack_chk_guard
.text:B65E1FF2 21 68 LDR R1, [R4]
.text:B65E1FF4 0E 91 STR R1, [SP,#0x48+var_10]
.text:B65E1FF6 0A 21 MOVS R1, #0xA
.text:B65E1FF8 CA 43 MVNS R2, R1
.text:B65E1FFA 01 68 LDR R1, [R0] ; file
.text:B65E1FFC 48 1E SUBS R0, R1, #1
.text:B65E1FFE 82 58 LDR R2, [R0,R2]
.text:B65E2000 00 25 MOVS R5, #0
.text:B65E2002 E8 43 MVNS R0, R5
.text:B65E2004 00 2A CMP R2, #0
.text:B65E2006 43 D0 BEQ loc_B65E2090
.text:B65E2008 00 25 MOVS R5, #0
.text:B65E200A 05 95 STR R5, [SP,#0x48+var_34]
.text:B65E200C 04 90 STR R0, [SP,#0x48+var_38]
.text:B65E200E 06 90 STR R0, [SP,#0x48+var_30]
.text:B65E2010 07 95 STR R5, [SP,#0x48+var_2C]
.text:B65E2012 08 90 STR R0, [SP,#0x48+var_28]
.text:B65E2014 0C 90 STR R0, [SP,#0x48+var_18]
.text:B65E2016 0D 95 STR R5, [SP,#0x48+var_14]
.text:B65E2018 E8 43 MVNS R0, R5
.text:B65E201A 0B 90 STR R0, [SP,#0x48+var_1C]
.text:B65E201C 0A 90 STR R0, [SP,#0x48+var_20]
.text:B65E201E 04 A8 ADD R0, SP, #0x48+var_38 ; int
.text:B65E2020 0D F0 40 FF BL openfile_sub_C6BADEA4 ; R3:要读取的文件
.text:B65E2024 01 30 ADDS R0, #1
.text:B65E2026 30 D0 BEQ loc_B65E208A
.text:B65E2028 02 96 STR R6, [SP,#0x48+var_40]
.text:B65E202A 04 A8 ADD R0, SP, #0x48+var_38
.text:B65E202C 1E 49 LDR R1, =(sub_B65E20AC+1 - 0xB65E2032)
.text:B65E202E 79 44 ADD R1, PC ; sub_B65E20AC
.text:B65E2030 0E F0 C8 F9 BL size_sub_C6BAE3C4
.text:B65E2034 06 00 MOVS R6, R0
.text:B65E2036 00 2E CMP R6, #0
.text:B65E2038 27 D0 BEQ loc_B65E208A
.text:B65E203A 00 25 MOVS R5, #0
.text:B65E203C 03 95 STR R5, [SP,#0x48+byte_count]
.text:B65E203E 04 A8 ADD R0, SP, #0x48+var_38
.text:B65E2040 03 AA ADD R2, SP, #0x48+byte_count
.text:B65E2042 31 00 MOVS R1, R6
.text:B65E2044 0E F0 2E FB BL read_sub_C6BAE6A4
.text:B65E2048 03 99 LDR R1, [SP,#0x48+byte_count]
.text:B65E204A 00 29 CMP R1, #0
.text:B65E204C 1D D0 BEQ loc_B65E208A
.text:B65E204E 00 28 CMP R0, #0
.text:B65E2050 1B D0 BEQ loc_B65E208A
.text:B65E2052 08 00 MOVS R0, R1 ; byte_count
.text:B65E2054 01 91 STR R1, [SP,#0x48+var_44]
.text:B65E2056 EF F7 48 EE BLX malloc ; 分配存放空间
.text:B65E205A 02 00 MOVS R2, R0
.text:B65E205C 00 28 CMP R0, #0
.text:B65E205E 14 D0 BEQ loc_B65E208A
.text:B65E2060 00 21 MOVS R1, #0
.text:B65E2062 15 00 MOVS R5, R2
.text:B65E2064 28 00 MOVS R0, R5
.text:B65E2066 01 9A LDR R2, [SP,#0x48+var_44]
.text:B65E2068 16 F0 2A FA BL memset_sub_C6BB64C0
.text:B65E206C 04 A8 ADD R0, SP, #0x48+var_38
.text:B65E206E 31 00 MOVS R1, R6
.text:B65E2070 2A 00 MOVS R2, R5
.text:B65E2072 0E F0 6B FB BL ReadFile_unzip_sub_C6BAE74C ; 读取并解压
.text:B65E2076 00 28 CMP R0, #0
.text:B65E2078 03 D0 BEQ loc_B65E2082
.text:B65E207A 03 98 LDR R0, [SP,#0x48+byte_count]
.text:B65E207C 02 99 LDR R1, [SP,#0x48+var_40]
.text:B65E207E 08 60 STR R0, [R1]
0x002.读取的数据与APk包中的内容是一样的:
B3C7B000 30 82 03 F5 06 09 2A 86 48 86 F7 0D 01 07 02 A0 0.......H.......
B3C7B010 82 03 E6 30 82 03 E2 02 01 01 31 0F 30 0D 06 09 ..........1.0...
B3C7B020 60 86 48 01 65 03 04 02 01 05 00 30 0B 06 09 2A `.H.e......0...*
B3C7B030 86 48 86 F7 0D 01 07 01 A0 82 02 83 30 82 02 7F .H..........0...
B3C7B040 30 82 01 E8 A0 03 02 01 02 02 04 4D 69 1B B8 30 0..........Mi..0
B3C7B050 0D 06 09 2A 86 48 86 F7 0D 01 01 05 05 00 30 81 ...*.H........0.
B3C7B060 82 31 0B 30 09 06 03 55 04 06 13 02 43 4E 31 10 .1.0...U....CN1.
B3C7B070 30 0E 06 03 55 04 08 13 07 42 65 69 6A 69 6E 67 0...U....Beijing
B3C7B080 31 10 30 0E 06 03 55 04 07 13 07 42 65 69 6A 69 1.0...U....Beiji
B3C7B090 6E 67 31 24 30 22 06 03 55 04 0A 13 1B 53 61 6E ng1$0"..U....San
B3C7B0A0 6B 75 61 69 20 54 65 63 68 6E 6F 6C 6F 67 79 20 kuai Technology
B3C7B0B0 43 6F 2E 20 4C 74 64 2E 31 14 30 12 06 03 55 04 Co. Ltd.1.0...U.
B3C7B0C0 0B 13 0B 6D 65 69 74 75 61 6E 2E 63 6F 6D 31 13 ...meituan.com1.
0x003.检测是否为RSA文件:
.text:B65EFCBC isRSA_sub_CB471CBC
.text:B65EFCBC ; __unwind { // FDA46000
.text:B65EFCBC D0 B5 PUSH {R4,R6,R7,LR}
.text:B65EFCBE 02 AF ADD R7, SP, #8
.text:B65EFCC0 01 00 MOVS R1, R0
.text:B65EFCC2 00 20 MOVS R0, #0
.text:B65EFCC4 00 29 CMP R1, #0
.text:B65EFCC6 1B D0 BEQ locret_B65EFD00
.text:B65EFCC8 0A 78 LDRB R2, [R1]
.text:B65EFCCA 30 2A CMP R2, #0x30 ; '0'
.text:B65EFCCC 18 D1 BNE locret_B65EFD00
.text:B65EFCCE 01 22 MOVS R2, #1
.text:B65EFCD0 8C 56 LDRSB R4, [R1,R2]
.text:B65EFCD2 7F 22 MOVS R2, #0x7F
.text:B65EFCD4 22 40 ANDS R2, R4
.text:B65EFCD6 FF 23 MOVS R3, #0xFF
.text:B65EFCD8 23 40 ANDS R3, R4
.text:B65EFCDA 00 2C CMP R4, #0
.text:B65EFCDC 00 DB BLT loc_B65EFCE0
.text:B65EFCDE 1A 00 MOVS R2, R3
.text:B65EFCE0
.text:B65EFCE0 loc_B65EFCE0
.text:B65EFCE0 04 2A CMP R2, #4
.text:B65EFCE2 0D D8 BHI locret_B65EFD00
.text:B65EFCE4 00 2A CMP R2, #0
.text:B65EFCE6 0B D0 BEQ locret_B65EFD00
.text:B65EFCE8 02 31 ADDS R1, #2
.text:B65EFCEA D3 00 LSLS R3, R2, #3
.text:B65EFCEC 08 3B SUBS R3, #8
.text:B65EFCEE 00 20 MOVS R0, #0
.text:B65EFCF0
.text:B65EFCF0 loc_B65EFCF0
.text:B65EFCF0 0C 78 LDRB R4, [R1]
.text:B65EFCF2 9C 40 LSLS R4, R3
.text:B65EFCF4 20 43 ORRS R0, R4
.text:B65EFCF6 01 3A SUBS R2, #1
.text:B65EFCF8 08 3B SUBS R3, #8
.text:B65EFCFA 01 31 ADDS R1, #1
.text:B65EFCFC 00 2A CMP R2, #0
.text:B65EFCFE F7 D1 BNE loc_B65EFCF0
.text:B65EFD00
.text:B65EFD00 locret_B65EFD00
.text:B65EFD00 D0 BD POP {R4,R6,R7,PC}
0x004.计算MD5值:
int __fastcall md5_sub_C6FEF398(int a1, int a2, int a3)
{
int i; // r0
int v8[26]; // [sp+10h] [bp-68h] BYREF
memset_sub_C6BB64C0(v8, 0, 88);
v8[0] = 0;
v8[1] = 0;
v8[2] = 1732584193;
v8[3] = -271733879;
v8[4] = -1732584194;
v8[5] = 271733878;
sub_B65F11F4(v8, a1, a2);
sub_B65F1294(v8, a3);
for ( i = 0; i != 88; ++i )
*((_BYTE *)v8 + i) = 0;
return _stack_chk_guard - v8[22];
}
0x005.计算后的值为,该值会作为解密资源密钥的一部分:
638C81261479C2104EDE3F2518E91725
0x006.解密assets/ms_com.sankuai.meituan 组合密钥:包名+常量字符(WU@TEN)+META-INF/SANKUAI.RSA(md5):
com.sankuai.meituanWU@TEN638C81261479C2104EDE3F2518E91725
0x007.将组合后的字符串加密Sha1值:
.text:C1D52AA4 F0 B5 PUSH {R4-R7,LR}
.text:C1D52AA6 03 AF ADD R7, SP, #0xC
.text:C1D52AA8 8F B0 SUB SP, SP, #0x3C
.text:C1D52AAA 15 00 MOVS R5, R2
.text:C1D52AAC 0E 00 MOVS R6, R1
.text:C1D52AAE 02 90 STR R0, [SP,#0x48+var_40]
.text:C1D52AB0 1A 48 LDR R0, =(__stack_chk_guard_ptr - 0xC1D52AB6)
.text:C1D52AB2 78 44 ADD R0, PC ; __stack_chk_guard_ptr
.text:C1D52AB4 04 68 LDR R4, [R0] ; __stack_chk_guard
.text:C1D52AB6 20 68 LDR R0, [R4]
.text:C1D52AB8 0E 90 STR R0, [SP,#0x48+var_10]
.text:C1D52ABA 00 2E CMP R6, #0
.text:C1D52ABC 1F D0 BEQ loc_C1D52AFE
.text:C1D52ABE 00 2D CMP R5, #0
.text:C1D52AC0 1D D0 BEQ loc_C1D52AFE
.text:C1D52AC2 01 94 STR R4, [SP,#0x48+var_44]
.text:C1D52AC4 05 AC ADD R4, SP, #0x48+var_34
.text:C1D52AC6 21 21 MOVS R1, #0x21 ; '!'
.text:C1D52AC8 20 00 MOVS R0, R4
.text:C1D52ACA F2 F7 26 E9 BLX __aeabi_memclr4
.text:C1D52ACE 30 00 MOVS R0, R6
.text:C1D52AD0 29 00 MOVS R1, R5
.text:C1D52AD2 22 00 MOVS R2, R4
.text:C1D52AD4 12 F0 8E FB BL JMP_Sha1_256_sub_C6BB01F4 ; R0:原始值,R1:大小,R2:返回值
.text:C1D52AD8 03 A8 ADD R0, SP, #0x48+var_3C
.text:C1D52ADA 20 22 MOVS R2, #0x20 ; ' '
.text:C1D52ADC 21 00 MOVS R1, R4
.text:C1D52ADE 01 9C LDR R4, [SP,#0x48+var_44]
.text:C1D52AE0 FF F7 72 FF BL Hex2String_sub_C6B9D9C8 ; R1:返回值,R2:大小
.text:C1D52AE4 03 98 LDR R0, [SP,#0x48+var_3C]
.text:C1D52AE6 02 99 LDR R1, [SP,#0x48+var_40]
.text:C1D52AE8 08 60 STR R0, [R1]
.text:C1D52AEA 0D 48 LDR R0, =(off_C1DD8C48 - 0xC1D52AF0)
.text:C1D52AEC 78 44 ADD R0, PC ; off_C1DD8C48
.text:C1D52AEE 00 68 LDR R0, [R0] ; dword_C1DEAADC
.text:C1D52AF0 01 00 MOVS R1, R0
.text:C1D52AF2 0C 31 ADDS R1, #0xC
.text:C1D52AF4 03 91 STR R1, [SP,#0x48+var_3C]
.text:C1D52AF6 04 A9 ADD R1, SP, #0x48+var_38
.text:C1D52AF8 6B F0 26 FE BL free_sub_B2943748
0x008.加密后的值为:
//该值为解密assets/ms_com.sankuai.meituan的密钥
69fe5963f3b95d9718c8d3e4f924ad9379500e9b51d80686e65347890e1748fe
0x009.读取资源文件assets/ms_com.sankuai.meituan:
int __fastcall ReadFile_unzip_sub_C6BAE74C(int *a1, int a2, int a3)
{
int v5; // r0
int v6; // r5
int v7; // r0
int v8; // r6
int v9; // r5
int v10; // r0
__int64 v13; // [sp+24h] [bp-28h] BYREF
unsigned int v14; // [sp+30h] [bp-1Ch] BYREF
int v15; // [sp+34h] [bp-18h] BYREF
int v16; // [sp+38h] [bp-14h] BYREF
v5 = a2 - 10000;
v6 = 0;
if ( a2 >= 10000 && v5 < a1[8] )
{
if ( *(_DWORD *)(a1[9] + 8 * v5) )
{
v6 = 0;
if ( read_sub_C6BAE448(a1, a2, &v16, &v15, (int *)&v14, &v13, 0, 0) )
{
v7 = mapfile_sub_C6BAE6C0(a1, a2);
v8 = v7;
if ( v7 )
{
v9 = *(_DWORD *)(v7 + 24);
if ( v14 > 0x8000 )
sub_C1D62E3C(v7, 2);
if ( v16 )
{
v10 = unzip_sub_C6BAE820(a3, v9, v15, v14);
v6 = 0;
if ( !v10 )
{
LABEL_15:
free_sub_CA79DF8C(v8);
return v6;
}
}
else
{
getvalu_sub_C87B550A(a3, v9, v15);
}
if ( v14 > 0x8000 )
sub_C1D62E3C(v8, 0);
v6 = 1;
goto LABEL_15;
}
}
}
}
return v6;
}
0x010.读取后内容(部分):
BCF4A000 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 .PNG........IHDR
BCF4A010 00 00 00 3C 00 00 00 3C 08 06 00 00 00 3A FC D9 ...<...<.....:..
BCF4A020 72 00 00 13 56 49 44 41 54 78 DA ED 5A 79 70 55 r...VIDATx..ZypU
BCF4A030 D7 79 BF 42 AC C6 80 09 5E 00 DB 98 5D E0 64 92 ...B.ƀ .^...]...
BCF4A040 4E 92 76 6C 37 EE 4C 26 4D 5D A7 6E DA 74 49 26 N.vl7...M].n..I&
BCF4A050 53 B7 C9 8C FF 68 DC 75 9C DA 1D D7 F5 C4 4E 13 S.Ɍ .h..........
BCF4A060 63 D7 98 C5 80 36 90 90 D0 CA 62 83 84 D9 F4 F4 cט ŀ 6....b.....
BCF4A070 16 BD 4D CB D3 BE 20 24 10 9B 10 12 9B 04 48 08 ..M... $......H.
BCF4A080 B4 DE 5F 7F E7 DC E5 9D FB 24 40 24 B6 EB E9 F4 .........$@$....
0x011.解析解密图片得到PIC数据:
int __fastcall ParsePng_sub_CB4C8858(
int *a1,
unsigned int *a2,
unsigned int *a3,
_DWORD *a4,
unsigned int data,
unsigned int a6)
{
int *v54; // r4
void *v55; // r0
int (__fastcall *v56)(void **, int *, unsigned __int8 *, unsigned int, _DWORD *);
v7 = 0;
*a1 = 0;
*a3 = 0;
*a2 = 0;
result = CRC32_sub_CB4C7D08((int *)a2, (int *)a3, a4, (unsigned __int8 *)data, a6);
a4[92] = result;
if ( result )
return result;
v110 = a4 + 92;
v9 = a4[39];
v10 = a4[38];
v135 = a4 + 39;
v104 = a4 + 38;
v108 = a4;
v131 = a4 + 35;
v148 = (void *)*a3;
v11 = *a2;
v12 = 0;
if ( v10 <= 6 )
v12 = dword_C1DD1C40[v10];
v13 = v12 * v9;
v14 = v108[27];
v15 = v108[28];
if ( v14 <= 6 )
v7 = dword_C1DD1C40[v14];
if ( v13 <= v7 * v15 )
{
v18 = 0;
v17 = *a3;
if ( v14 <= 6 )
v18 = dword_C1DD1C40[v14];
v143 = v15 * v18;
}
else
{
v16 = 0;
v17 = *a3;
if ( v10 <= 6 )
v16 = dword_C1DD1C40[v10];
v143 = v9 * v16;
}
v19 = v11 * v17;
v20 = 0;
if ( v11 )
{
v21 = to1028_sub_CA812FD0(v11 * v17, v11);
v20 = 0;
v17 = (unsigned int)v148;
if ( (void *)v21 != v148 )
goto LABEL_125;
if ( v19 )
{
v22 = to1028_sub_CA812FD0(8 * v19, v19);
v20 = 0;
v17 = (unsigned int)v148;
if ( v22 != 8 )
goto LABEL_125;
}
if ( v11 >> 3 )
{
v23 = to1028_sub_CA812FD0((v11 >> 3) * v143, v11 >> 3);
v17 = (unsigned int)v148;
v20 = (v11 >> 3) * v143;
if ( v23 != v143 )
goto LABEL_125;
}
}
v24 = v20 + (((v11 & 7) * v143 + 7) >> 3);
if ( v24 < v20 || v24 > 0xFFFFFFFA || to1028_sub_CA812FD0(v17 * (v24 + 5), v24 + 5) != v17 )
{
LABEL_125:
result = 92;
*v110 = 92;
return result;
}
v25 = v108;
v111 = v108 + 1;
v26 = (unsigned __int8 *)(data + 33);
pdata = 0;
v129 = 0;
v119 = 0;
v116 = 1;
while ( 1 )
{
v27 = (unsigned int)&v26[-data + 12];
if ( (unsigned int)v26 < data || v27 > a6 )
{
if ( v25[7] )
goto LABEL_136;
v44 = 30;
goto LABEL_132;
}
v144 = v26;
v28 = v26;
v29 = _byteswap_ulong(*(_DWORD *)v26);
v30 = v110;
if ( v29 < 0 )
{
v25 = v108;
if ( v108[7] )
goto LABEL_136;
v44 = 63;
goto LABEL_133;
}
if ( v29 + v27 > a6 || (unsigned int)&v26[v29 + 12] < data )
break;
v31 = v26 + 8;
if ( !byte_C1DEAAB4 )
{
DecString((const char *)byte_C1DE8374, aXpvn, 17, 4);
v28 = v144;
byte_C1DE8378 = 0;
}
byte_C1DEAAB4 = 1;
if ( getIHDR_sub_CCBFBBC8(v28, byte_C1DE8374) )
{
v32 = v29 + v129;
if ( v29 + v129 < v29 )
{
v43 = 95;
goto LABEL_134;
}
v122 = v29 + v129;
if ( v119 >= v32 )
{
v34 = (int)pdata;
}
else
{
v33 = v29 + v129;
if ( v32 <= 2 * v119 )
v33 = (3 * v32) >> 1;
v119 = v33;
v34 = realloc(pdata);
if ( !v34 )
{
v43 = 83;
goto LABEL_134;
}
}
v35 = 0;
v116 = 3;
if ( v29 )
{
v37 = v129;
do
{
*(_BYTE *)(v34 + v37) = *v31++;
--v29;
++v37;
}
while ( v29 );
}
v129 = v122;
pdata = (unsigned __int8 *)v34;
goto LABEL_50;
}
if ( !byte_C1DEAAB5 )
{
DecString((const char *)byte_C1DE8379, aPv, 18, 4);
byte_C1DE837D = 0;
}
v35 = 1;
byte_C1DEAAB5 = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE8379) )
goto LABEL_50;
if ( !byte_C1DEAAA8 )
{
DecString((const char *)byte_C1DE8338, aSjI, 3, 4);
unk_C1DE833C = 0;
}
byte_C1DEAAA8 = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE8338) )
{
v36 = dec_sub_CA801FF0(v104, v31, v29);
*v110 = v36;
v35 = 0;
v116 = 2;
LABEL_67:
v25 = v108;
v38 = (unsigned int *)v144;
if ( v36 )
goto LABEL_136;
LABEL_51:
if ( !v25[5] )
{
v39 = gencrc_sub_CA800C08(v38);
v38 = (unsigned int *)v144;
if ( v39 )
{
v44 = 57;
LABEL_132:
v30 = v110;
LABEL_133:
*v30 = v44;
goto LABEL_136;
}
}
if ( v35 )
goto LABEL_136;
LABEL_55:
v40 = *v110;
goto LABEL_56;
}
if ( !byte_C1DEAAA9 )
{
DecString((const char *)byte_C1DE833D, aPud, 4, 4);
byte_C1DE8341 = 0;
}
byte_C1DEAAA9 = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE833D) )
{
v36 = sub_C1DB9080(v104, v31, v29);
LABEL_66:
*v110 = v36;
v35 = 0;
goto LABEL_67;
}
if ( !byte_C1DEAAAA )
{
DecString((const char *)byte_C1DE8342, aGclj, 5, 4);
byte_C1DE8346 = 0;
}
byte_C1DEAAAA = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE8342) )
{
v36 = sub_C1DB9100(v131, v31, v29);
goto LABEL_66;
}
if ( !byte_C1DEAAAB )
{
DecString((const char *)byte_C1DE8347, aRlt, 6, 4);
byte_C1DE834B = 0;
}
byte_C1DEAAAB = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE8347) )
{
v35 = 0;
if ( v108[9] )
{
v36 = sub_C1DB917C((int)v131, v31, v29);
LABEL_79:
*v110 = v36;
goto LABEL_67;
}
goto LABEL_50;
}
if ( !byte_C1DEAAAC )
{
DecString((const char *)byte_C1DE834C, aUd, 7, 4);
byte_C1DE8350 = 0;
}
byte_C1DEAAAC = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE834C) )
{
v35 = 0;
if ( v108[9] )
{
v36 = sub_C1DB923C(v131, v111, v31, v29);
goto LABEL_79;
}
LABEL_50:
v25 = v108;
v38 = (unsigned int *)v144;
goto LABEL_51;
}
if ( !byte_C1DEAAAD )
{
DecString((const char *)byte_C1DE8351, aAVe, 8, 4);
byte_C1DE8355 = 0;
}
byte_C1DEAAAD = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE8351) )
{
if ( v108[9] )
{
v41 = sub_C1DB936C(v131, v111, v31, v29);
*v110 = v41;
v25 = v108;
v38 = (unsigned int *)v144;
v35 = 0;
if ( v41 )
goto LABEL_136;
}
else
{
v25 = v108;
v38 = (unsigned int *)v144;
v35 = 0;
}
goto LABEL_51;
}
if ( !byte_C1DEAAAE )
{
DecString((const char *)byte_C1DE8356, aEbw, 9, 4);
unk_C1DE835A = 0;
}
byte_C1DEAAAE = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE8356) )
{
if ( v29 != 7 )
{
v43 = 73;
LABEL_134:
v30 = v110;
goto LABEL_135;
}
v108[58] = 1;
v38 = (unsigned int *)v144;
v108[59] = (v144[8] << 8) | v144[9];
v108[60] = v144[10];
v108[61] = v144[11];
v108[62] = v144[12];
v108[63] = v144[13];
v108[64] = v144[14];
LABEL_92:
v35 = 0;
*v110 = 0;
v25 = v108;
goto LABEL_51;
}
if ( !byte_C1DEAAAF )
{
DecString((const char *)byte_C1DE835B, aZei, 10, 4);
unk_C1DE835F = 0;
}
byte_C1DEAAAF = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE835B) )
{
v36 = sub_C1DB95FC(v131, (int)v31, v29);
goto LABEL_66;
}
if ( !byte_C1DEAAB0 )
{
DecString((const char *)byte_C1DE8360, aLoU, 11, 4);
unk_C1DE8364 = 0;
}
byte_C1DEAAB0 = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE8360) )
{
if ( v29 != 4 )
{
v43 = 96;
goto LABEL_134;
}
v108[69] = 1;
v38 = (unsigned int *)v144;
v108[70] = _byteswap_ulong(*((_DWORD *)v144 + 2));
goto LABEL_92;
}
if ( !byte_C1DEAAB1 )
{
DecString((const char *)byte_C1DE8365, aOgX, 12, 4);
unk_C1DE8369 = 0;
}
byte_C1DEAAB1 = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE8365) )
{
v36 = sub_C1DB9640(v131, (unsigned int *)v31, v29);
goto LABEL_66;
}
if ( !byte_C1DEAAB2 )
{
DecString((const char *)byte_C1DE836A, aBtt, 13, 4);
unk_C1DE836E = 0;
}
byte_C1DEAAB2 = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE836A) )
{
if ( v29 != 1 )
{
v43 = 98;
goto LABEL_134;
}
v108[80] = 1;
v108[81] = *v31;
v35 = 0;
*v110 = 0;
goto LABEL_50;
}
if ( !byte_C1DEAAB3 )
{
DecString((const char *)byte_C1DE836F, aGrwg, 14, 4);
unk_C1DE8373 = 0;
}
byte_C1DEAAB3 = 1;
if ( getIHDR_sub_CCBFBBC8(v144, byte_C1DE836F) )
{
v36 = sub_C1DB9714(v131, v111, v31, v29);
goto LABEL_66;
}
if ( !v108[6] && (v144[4] & 0x20) == 0 )
{
v43 = 69;
goto LABEL_134;
}
if ( !v108[10] )
{
v25 = v108;
v38 = (unsigned int *)v144;
goto LABEL_55;
}
v25 = v108;
v42 = sub_C1DB7CCE(&v108[v116 + 85], &v108[v116 + 88], (unsigned int *)v144);
v38 = (unsigned int *)v144;
*v110 = v42;
v40 = 0;
if ( v42 )
goto LABEL_136;
LABEL_56:
v26 = isPng_sub_CA800C80((unsigned __int8 *)v38);
if ( v40 )
goto LABEL_136;
}
v43 = 64;
LABEL_135:
*v30 = v43;
v25 = v108;
LABEL_136:
v154 = 0;
v152 = 0;
v153 = 0;
v45 = v25[37];
v123 = v25 + 37;
v46 = *a2;
if ( v45 )
{
v145 = *a3;
v47 = (*a3 + 7) >> 3;
v140 = sub_C1DBAC4C((v46 + 7) >> 3, v47, (unsigned int *)v104);
v48 = v46 + 3;
if ( v46 >= 5 )
{
v49 = sub_C1DBAC4C(v48 >> 3, v47, (unsigned int *)v104) + v140;
v48 = v46 + 3;
v140 = v49;
}
v50 = sub_C1DBAC4C(v48 >> 2, (v145 + 3) >> 3, (unsigned int *)v104) + v140;
v51 = v46 + 1;
if ( v46 >= 3 )
{
v50 += sub_C1DBAC4C(v51 >> 2, (v145 + 3) >> 2, (unsigned int *)v104);
v51 = v46 + 1;
}
v52 = sub_C1DBAC4C(v51 >> 1, (v145 + 1) >> 2, (unsigned int *)v104) + v50;
if ( v46 >= 2 )
v52 += sub_C1DBAC4C(v46 >> 1, (v145 + 1) >> 1, (unsigned int *)v104);
v53 = sub_C1DBAC4C(v46, v145 >> 1, (unsigned int *)v104) + v52;
}
else
{
v53 = sub_C1DBAC4C(*a2, *a3, (unsigned int *)v104);
}
v54 = v110;
if ( !*v110 )
{
if ( !v53 )
goto LABEL_149;
v55 = (void *)realloc(0);
if ( !v55 )
{
v57 = 83;
goto LABEL_157;
}
v152 = v55;
v154 = v53;
if ( !*v110 )
{
LABEL_149:
v56 = (int (__fastcall *)(void **, int *, unsigned __int8 *, unsigned int, _DWORD *))v108[2];
if ( v56 )
v57 = v56(&v152, &v153, pdata, v129, v111);
else
v57 = sub_C1DB7A98(&v152, &v153, pdata, v129, v111);
v58 = v57;
v54 = v110;
if ( v153 != v53 )
v58 = 91;
if ( !v57 )
v57 = v58;
LABEL_157:
*v54 = v57;
}
}
free(pdata);
if ( !*v54 )
{
v59 = *v135;
v107 = *a2;
v132 = *a3;
v146 = *v104;
v60 = sub_C1DB7DA4(*a2, *a3, *v104, *v135);
v61 = malloc(v60);
*a1 = v61;
v62 = 83;
if ( v61 )
{
if ( v60 )
{
for ( i = 0; i != v60; ++i )
{
*(_BYTE *)(v61 + i) = 0;
v61 = *a1;
}
v64 = v108[38];
v59 = *v135;
v132 = *a3;
v107 = *a2;
}
else
{
v64 = v146;
}
v147 = (char *)v152;
v65 = 0;
if ( v64 <= 6 )
v65 = dword_C1DD1C40[v64];
v66 = v59 * v65;
v62 = 31;
if ( v66 )
{
if ( *v123 )
{
v139 = v61;
sub_C1DBAF5C(v159, v158, v157, v156, v155, v107, v132, v66);
v67 = 0;
do
{
v68 = *(_DWORD *)&v158[v67];
v141 = v67;
v136 = &v147[*(_DWORD *)&v156[v67]];
v69 = *(_DWORD *)&v159[v67];
v62 = sub_C1DBAC80(v136);
if ( v62 )
{
v80 = 0;
v54 = v110;
goto LABEL_206;
}
if ( v66 <= 7 )
sub_C1DBAECC(&v147[*(_DWORD *)&v155[v141]], v136, v69 * v66, (v69 * v66 + 7) & 0xFFFFFFF8, v68);
v67 = v141 + 4;
}
while ( v141 != 24 );
sub_C1DBAF5C(v164, v163, v162, v161, v160, v107, v132, v66);
if ( v66 <= 7 )
{
v81 = 0;
v118 = v66;
do
{
v96 = v81;
v82 = v81;
v106 = v163[v82];
if ( v106 )
{
v134 = v164[v82];
v103 = &dword_C1DD1BAC[v82];
v101 = (_DWORD *)((char *)&unk_C1DD1BC8 + v82 * 4);
v99 = &dword_C1DD1BE4[v82];
v98 = &dword_C1DD1C00[v82];
v97 = &v160[v82 * 4];
for ( j = 0; j != v106; ++j )
{
if ( v134 )
{
pdatab = (void *)((*v99 * j + *v98) * v107 + *v101);
v125 = *v103;
v121 = 8 * *(_DWORD *)v97;
v83 = 0;
do
{
v84 = (v83 + v134 * j) * v66 + v121;
v138 = v83;
v85 = ((_DWORD)pdatab + v125 * v83) * v66;
v86 = v66;
do
{
v87 = ((unsigned __int8)v147[v84 >> 3] >> (~(_BYTE)v84 & 7)) & 1;
++v84;
if ( v87 )
*(_BYTE *)(v139 + (v85 >> 3)) |= (_BYTE)v87 << (~(_BYTE)v85 & 7);
--v86;
++v85;
}
while ( v86 );
v83 = v138 + 1;
v66 = v118;
}
while ( v138 + 1 != v134 );
}
}
}
v81 = v96 + 1;
}
while ( v96 != 6 );
}
else
{
v70 = v66 >> 3;
v71 = 0;
v149 = v66 >> 3;
do
{
v100 = v71;
v72 = v71;
pdataa = (void *)v163[v71];
if ( pdataa )
{
v120 = &dword_C1DD1BAC[v72];
v117 = (_DWORD *)((char *)&unk_C1DD1BC8 + v72 * 4);
v112 = &dword_C1DD1BE4[v72];
v105 = &dword_C1DD1C00[v72];
v102 = &v160[v72 * 4];
v142 = v164[v71];
v124 = v142 * v70;
v133 = 0;
v130 = v147;
do
{
if ( v142 )
{
v73 = &v130[*(_DWORD *)v102];
v137 = *v120 * v70;
v74 = (_BYTE *)(v139 + (*v117 + (*v105 + *v112 * (_DWORD)v133) * v107) * v70);
for ( k = 0; k != v142; ++k )
{
if ( v70 )
{
v76 = v73;
v77 = (char *)v149;
v78 = v74;
do
{
*v78 = *v76++;
--v77;
++v78;
}
while ( v77 );
}
v70 = v149;
v73 += v149;
v74 += v137;
}
}
v130 += v124;
v133 = (char *)v133 + 1;
}
while ( v133 != pdataa );
}
v71 = v100 + 1;
}
while ( v100 != 6 );
}
v62 = 0;
v54 = v110;
v80 = 1;
LABEL_206:
if ( v80 )
LABEL_207:
v62 = 0;
}
else if ( v66 > 7 || (v79 = v107 * v66, v107 * v66 == ((v107 * v66 + 7) & 0xFFFFFFF8)) )
{
v62 = sub_C1DBAC80(v61);
if ( !v62 )
goto LABEL_207;
}
else
{
v151 = (void *)((v107 * v66 + 7) & 0xFFFFFFF8);
v95 = v61;
v62 = sub_C1DBAC80(v152);
if ( !v62 )
{
sub_C1DBAECC(v95, v147, v79, v151, v132);
goto LABEL_207;
}
}
}
}
*v54 = v62;
}
v88 = 0;
v153 = 0;
v154 = 0;
free(v152);
result = *v54;
if ( !*v54 )
{
v89 = v108 + 27;
if ( v108[8] )
{
if ( !sub_C1DB8460(v108 + 27, v104) )
{
if ( (*v89 | 4) != 6 )
{
result = 56;
if ( v108[28] != 8 )
return result;
}
v150 = (void *)*a1;
v90 = *a3;
v91 = *a2;
v92 = sub_C1DB7DA4(*a2, *a3, *v89, v108[28]);
v93 = malloc(v92);
*a1 = v93;
v94 = 83;
if ( v93 )
v94 = sub_C1DB8064(v93, v150, v89, v104, v91, v90);
*v110 = v94;
free(v150);
return *v110;
}
}
else
{
result = sub_C1DB7D34(v108 + 27, v104);
*v110 = result;
if ( result )
return result;
}
return v88;
}
return result;
}
0x012.得到PIC数据(部分)(这个数据是伴随APP整个生命周期,主要用途是加解密密钥):
BDC74300 2E 50 49 43 90 01 00 00 10 02 00 00 B0 02 00 00 .PIC............
BDC74310 82 1B 33 E3 4F 0C 49 C7 00 00 00 00 2D AA F5 F4 ..3...I.....-...
BDC74320 52 22 D7 92 FB 3E EB AA 4A A2 74 C9 12 2D F9 92 R"ג .>....t..-..
BDC74330 F4 E7 CD 2C D8 33 1A B5 D4 8F F1 1E 11 6A 63 4D ........ԏ ....cM
BDC74340 73 AC 1E 88 BB E5 A5 D2 19 F4 46 8A 7D 13 57 F8 s.............W.
BDC74350 0C 14 F1 4C C7 E2 89 01 1A BD C8 72 66 3F F0 A9 ............f?..
BDC74360 C2 BA 6B 75 6D E3 03 FC 8F 61 20 96 6F 2C 44 2D º kum....a .o,D-
BDC74370 D6 19 DE F4 74 8E 6F 01 6B 9D 5F BB 6D C4 6C CD ....t.o.k._.m...
BDC74380 49 00 8F 36 F9 18 8E 50 2D 35 F3 6C F0 6C 75 84 I..6...P-5....u.
BDC74390 2C 78 A0 D7 8E 64 A1 E9 CC 5C 1A 59 C3 78 E3 7A ,x...d.....Y....
4. 采集系统环境信息加密
0x000.循环获取信息 0x34次:
.text:C1AF5224 02 98 LDR R0, [SP,#8]
.text:C1AF5226 06 59 LDR R6, [R0,R4]
.text:C1AF5228 D6 F7 46 F8 BL init_DecString_sub_C84582B8
.text:C1AF522C 06 90 STR R0, [SP,#0x18]
.text:C1AF522E 0A AD ADD R5, SP, #0x28 ; '('
.text:C1AF5230 28 00 MOVS R0, R5
.text:C1AF5232 04 99 LDR R1, [SP,#0x10]
.text:C1AF5234 05 9A LDR R2, [SP,#0x14]
.text:C1AF5236 33 00 MOVS R3, R6
.text:C1AF5238 FB F7 AC FE BL GetDeviceInfo_dispatch_loop_sub_C89F8F94 ; 获取设备信息1
.text:C1AF523C 06 98 LDR R0, [SP,#0x18]
.text:C1AF523E 31 00 MOVS R1, R6
.text:C1AF5240 2A 00 MOVS R2, R5
.text:C1AF5242 03 9D LDR R5, [SP,#0xC]
.text:C1AF5244 F9 F7 BE F9 BL jmp_checkField_sub_C89F65C4 ; 判断采集的设备信息是否等于如下特殊字符[],{},mtg_block,mtg_unsupport
.text:C1AF5248 0A 98 LDR R0, [SP,#0x28]
.text:C1AF524A 40 19 ADDS R0, R0, R5
.text:C1AF524C 09 A9 ADD R1, SP, #0x24 ; '$'
.text:C1AF524E 4C F0 7B FA BL free_sub_B2943748
.text:C1AF5252 04 34 ADDS R4, #4
.text:C1AF5254 34 2C CMP R4, #0x34 ; '4' ; 判断是否结束
.text:C1AF5256 E5 D1 BNE loc_C1AF5224
.text:C1AF5258 03 B5 PUSH {R0,R1,LR} ; 获取结束
0x001.在下面地方下是跳转到每一个采集信息方法入口的地方,下好断点:
.text:C207A134 80 00 LSLS R0, R0, #2 ; 跳到真实执行方法
.text:C207A136 02 A1 ADR R1, loc_C207A140
.text:C207A138 08 58 LDR R0, [R1,R0] ; 取方法表偏移
.text:C207A13A 08 18 ADDS R0, R1, R0
.text:C207A13C 87 46 MOV PC, R0
0x002.获取的系统环境信息:
{
"0": 2,
"1": ["-", "-", "-", "-", "-", "-", "-", "-", "google", "user", "-", "PQ2A.190305.002", "-", "-", "-", "sailfish", "-", "-", "Pixel", "-", "-", "-", "-", "adb", "-", "-", "-", "-", "-", "{\"1\":\"-\",\"2\":\"-\",\"3\":\"-\",\"4\":\"\",\"5\":\"\",\"6\":\"-\",\"7\":\"-\",\"8\":\"\",\"9\":\"\",\"10\":\"-\",\"11\":\"-\",\"12\":\"32\",\"13\":\"\",\"14\":\"-\",\"15\":\"\",\"33\":{\"0\":0,\"1\":\"-\",\"2\":\"-\",\"3\":\"-\",\"4\":\"-\",\"5\":\"-\",\"6\":\"-\",\"7\":\"-\",\"8\":\"-\",\"9\":\"-\",\"10\":\"-\",\"11\":\"-\",\"12\":\"-\",\"13\":\"-\",\"14\":\"-\",\"15\":\"-\"}}", "midi,adb", "midi,adb", "release-keys", "-", "1", "1", "-", "9"],
"2": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"],
"3": "{}"
}
0x003.加密设备信息(压缩信息):
result = deflateInit_(&strm, -1, a128, 56);
if ( !result )
{
v6 = deflate(&strm, 4);
if ( v6 == 1 )
{
*a4 = strm.total_out;
return deflateEnd(&strm);
}
deflateEnd(&strm);
if ( v6 != 2 )
{
if ( v6 != -5 )
return v6;
result = -3;
if ( strm.avail_in )
return v6;
return result;
}
return -3;
}
0x004.加密设备信息(压缩后信息):
C3904500 78 9C 9D 92 DB 0A C2 30 0C 86 DF 25 D7 CD E8 61 x...............
C3904510 53 B7 3B DF 60 5E 5B 2F 26 AB 5A 9C 0C 56 04 65 S.;..^[/&.Z..V.e
C3904520 F4 DD ED 0E B0 20 4E A6 17 81 2F E1 4F D2 9F B4 ..... N.../.....
C3904530 05 0E 99 64 20 20 DB 03 02 FB 1A E7 BA 3E 57 26 ...d ........W&
C3904540 C0 DD 99 66 AC E5 3B B9 8D 44 CA 15 4F 22 CE E5 ...f.....D..O"..
C3904550 5B 87 2B 6C 75 B2 EE 42 4A B9 7D 98 EA C3 F0 A2 [.+lu.....}.....
C3904560 3C CE AC 6D 35 08 0D 99 06 D4 C0 34 48 C2 8A 70 <ά m5......4H..p
C3904570 DC 73 8F C9 84 2B A2 58 13 DE 4C 92 74 42 C1 89 ...Ʉ +.X....tB..
C3904580 44 D0 AD 62 58 AB E4 90 29 D2 13 53 19 59 AD 3A DЭ bX......S.Y.:
C3904590 51 78 7C 37 93 B3 5F 4C 20 71 81 0B 6C 20 F1 81 Qx|7.._L q..l ..
0x005.解密PIC数据获取加密key 上面计算得到的sha256值,(包名+固定字符+SANKUAI.RSA的MD5值)->转换成hex 69fe5963f3b95d9718c8d3e4f924ad9379500e9b51d80686e65347890e1748fe
69 FE 59 63 F3 B9 5D 97 18 C8 D3 E4 F9 24 AD 93 79 50 0E 9B 51 D8 06 86 E6 53 47 89 0E 17 48 FE
0x006.取前0x10字节
69 FE 59 63 F3 B9 5D 97 18 C8 D3 E4 F9 24 AD 93
0x007.生成AES KEY
.text:C1AE9DA2 0A A8 ADD R0, SP, #0x28 ; '(' ; 生成AES key
.text:C1AE9DA4 08 90 STR R0, [SP,#0x20]
.text:C1AE9DA6 84 5D LDRB R4, [R0,R6]
.text:C1AE9DA8 82 B0 SUB SP, SP, #8
.text:C1AE9DAA 03 B5 PUSH {R0,R1,LR}
.text:C1AE9DAC DF F7 72 E9 BLX jmp_sub_B288C094
.text:C1AE9DB0 54 01 LSLS R4, R2, #5
.text:C1AE9DB2 00 00 MOVS R0, R0
.text:C1AE9DB4 01 BC POP {R0}
.text:C1AE9DB6 20 18 ADDS R0, R4, R0
.text:C1AE9DB8 29 00 MOVS R1, R5
.text:C1AE9DBA 63 F0 49 F9 BL sub_C1B4D050
.text:C1AE9DBE 07 91 STR R1, [SP,#0x1C]
.text:C1AE9DC0 82 B0 SUB SP, SP, #8
.text:C1AE9DC2 03 B5 PUSH {R0,R1,LR}
.text:C1AE9DC4 DF F7 66 E9 BLX jmp_sub_B288C094
.text:C1AE9DC8 40 01 LSLS R0, R0, #5
.text:C1AE9DCA 00 00 MOVS R0, R0
.text:C1AE9DCC 01 BC POP {R0}
.text:C1AE9DCE 20 18 ADDS R0, R4, R0
.text:C1AE9DD0 04 99 LDR R1, [SP,#0x10]
.text:C1AE9DD2 63 F0 3D F9 BL sub_C1B4D050
.text:C1AE9DD6 69 43 MULS R1, R5
.text:C1AE9DD8 07 98 LDR R0, [SP,#0x1C]
.text:C1AE9DDA 08 18 ADDS R0, R1, R0 ; 初始化密钥
.text:C1AE9DDC 03 21 MOVS R1, #3
.text:C1AE9DDE 41 43 MULS R1, R0
.text:C1AE9DE0 06 98 LDR R0, [SP,#0x18]
.text:C1AE9DE2 40 18 ADDS R0, R0, R1
.text:C1AE9DE4 80 78 LDRB R0, [R0,#2]
.text:C1AE9DE6 20 40 ANDS R0, R4
.text:C1AE9DE8 FE 21 MOVS R1, #0xFE
.text:C1AE9DEA 01 40 ANDS R1, R0
.text:C1AE9DEC 08 98 LDR R0, [SP,#0x20]
.text:C1AE9DEE 81 55 STRB R1, [R0,R6] ; 存储密钥
.text:C1AE9DF0 01 36 ADDS R6, #1
.text:C1AE9DF2 10 2E CMP R6, #0x10 ; 判断是否结束
.text:C1AE9DF4 D5 D1 BNE loc_C1AE9DA2 ; 生成AES key
0x008.生成最终的AES KEY
68 98 08 02 F2 80 1C 94 08 C8 90 E4 A0 04 AC 82
0x009.AES 解密pic
//IV 0102030405060708
.text:C1AE7598 57 F0 7A F8 BL AES_set_decrypt_key_sub_CB601690 ; R0:key,R1:大小,R2:初始AES_KEY返回结构
.text:C1AE759C 00 20 MOVS R0, #0
.text:C1AE759E 69 46 MOV R1, SP
.text:C1AE75A0 06 9A LDR R2, [SP,#0x128+var_110]
.text:C1AE75A2 0A 60 STR R2, [R1,#0x128+var_128]
.text:C1AE75A4 48 60 STR R0, [R1,#0x128+var_124]
.text:C1AE75A6 08 98 LDR R0, [SP,#0x128+var_108]
.text:C1AE75A8 04 9E LDR R6, [SP,#0x128+var_118]
.text:C1AE75AA 31 00 MOVS R1, R6
.text:C1AE75AC 07 9C LDR R4, [SP,#0x128+var_10C]
.text:C1AE75AE 22 00 MOVS R2, R4
.text:C1AE75B0 03 9B LDR R3, [SP,#0x128+var_11C]
.text:C1AE75B2 57 F0 35 FD BL AES_cbc_Dncrypt_sub_CB602020
.text:C1AE75B6 30 00 MOVS R0, R6
0x010.解密解压后PIC数据
{"a1":0,"a10":400,"a2":"com.sankuai.meituan","a11":"c1ee9178c95d9ec75f0f076a374df94a032d54c8576298d4f75e653de3705449","a3":"0a16ecd60eb56a6a3349f66cdcf7f7bf5190e5a42d6280d8dc0ee3be228398ec","a4":1100030200,"k0":{"k1":"meituan1sankuai0","k2":"meituan0sankuai1","k3":"$MXMYBS@HelloPay","k4":"Maoyan010iauknaS","k5":"34281a9dw2i701d4","k6":"X%rj@KiuU+|xY}?f"},"a5":"11.3.200","a0":"pw/LhTdeoTTyaxPHcHMy+/ssGNS1ihNkrJ+uBI74FIfd90KlTil1m0i7FF/n0bhY","a6":"/HntC9XIfdUyII/UiVfx020EQPpHz2XZY3qzM2aiNmM0i0pB1yeSO689TY9SBB3s","a7":"QsHnU6kFjTYR8Z6tHEvkGMO2Hrt+NRnVQhmxg6EtVBzuzQcBpma3AdhTWNMpesFT","c0":{"c1":true,"c2":false},"a9":"SDEzWXi5LHL/cuMCZ1zYyv+0hIViqWWf+ShbUYILWf4=","a8":1603800117167}
0x011.解析json获取key k6
X%rj@KiuU+|xY}?f
0x012.计算压缩后信息的CRC值
.text:C1B2C832 crc32_loc_CCBA9832
.text:C1B2C848↓j
.text:C1B2C832 FF 25 MOVS R5, #0xFF
.text:C1B2C834 05 40 ANDS R5, R0
.text:C1B2C836 16 78 LDRB R6, [R2]
.text:C1B2C838 6E 40 EORS R6, R5
.text:C1B2C83A B5 00 LSLS R5, R6, #2
.text:C1B2C83C 65 59 LDR R5, [R4,R5]
.text:C1B2C83E 00 0A LSRS R0, R0, #8
.text:C1B2C840 68 40 EORS R0, R5
.text:C1B2C842 01 39 SUBS R1, #1
.text:C1B2C844 01 32 ADDS R2, #1
.text:C1B2C846 00 29 CMP R1, #0
.text:C1B2C848 F3 D1 BNE crc32_loc_CCBA9832
0x013.计算后的CRC值为 744d7275 组合加密压缩后设备环境信息的key
744d7275X%rj@Kiu //crc32+k6前8字节
0x014.AES加密压缩后数据
.text:C1AE750E 32 00 MOVS R2, R6
.text:C1AE7510 56 F0 30 FF BL AES_set_Encrypt_key_sub_CB601374 ; R0:key,R1:长度,R2:返回值
.text:C1AE7514 06 9A LDR R2, [SP,#0x120+byte_count]
.text:C1AE7516 01 20 MOVS R0, #1
.text:C1AE7518 69 46 MOV R1, SP
.text:C1AE751A 04 9B LDR R3, [SP,#0x120+var_110]
.text:C1AE751C 0B 60 STR R3, [R1,#0x120+var_120]
.text:C1AE751E 48 60 STR R0, [R1,#0x120+var_11C]
.text:C1AE7520 05 98 LDR R0, [SP,#0x120+p]
.text:C1AE7522 02 9C LDR R4, [SP,#0x120+var_118]
.text:C1AE7524 21 00 MOVS R1, R4
.text:C1AE7526 33 00 MOVS R3, R6
.text:C1AE7528 57 F0 7A FD BL AES_cbc_Encrypt_sub_CB602020 ; R0:原始数据,R1:返回,R2:大小,R3:key
.text:C1AE752C 06 98 LDR R0, [SP,#0x120+byte_count]
.text:C1AE752E 03 99 LDR R1, [SP,#0x120+var_114]
0x015.加密后数据(部分)
C37514E0 2E 5D 33 AF C8 C3 6B 6A 7F C2 9F F6 39 16 52 57 .]3...kj.......W
C37514F0 1D CB 01 FF A2 FA 48 0B 2D 2B 7E 39 73 EB 65 E7 ......H.-+~9s...
C3751500 14 93 59 D9 15 F2 D7 CB C7 40 DC B5 9D 0D 34 16 ..Y......@....4.
C3751510 9C BF 69 C6 54 97 81 C8 69 7A 26 03 BF FA F3 D9 ..i......z&.....
C3751520 A3 D2 BE 38 B0 99 48 4A 5E 56 F0 C6 88 54 79 BD .Ҿ 8..HJ^V....y.
C3751530 56 86 96 A7 40 D4 61 32 6D A4 07 55 F1 46 46 EF V...@..2m..U....
C3751540 4E A1 CA 86 F8 1E 69 09 0B CF 6D 05 3B D3 0F B4 N.ʆ ..i.....;...
C3751550 63 78 65 6D AD F7 B2 C4 75 86 C5 35 B5 6F 42 BA cxem.........oB.
C3751560 FA AF E7 4C 56 41 CF 36 46 86 3E E0 11 A3 35 9E .....A..F.>...5.
0x016.base64编码:
.text:C1ACFE62 27 DB BLT loc_C1ACFEB4
.text:C1ACFE64 00 25 MOVS R5, #0
.text:C1ACFE66 3A 4A LDR R2, =(aAbcdefghijklmn - 0xC1ACFE6C) ; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm"...
.text:C1ACFE68 7A 44 ADD R2, PC ; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm"...
.text:C1ACFE6A 01 9E LDR R6, [SP,#0x28+var_24]
.text:C1ACFE6C
.text:C1ACFE6C loc_C1ACFE6C ; CODE XREF: base64_sub_C795AE10+A0↓j
.text:C1ACFE6C 43 5D LDRB R3, [R0,R5] ; 加密后数据
.text:C1ACFE6E 9B 08 LSRS R3, R3, #2
.text:C1ACFE70 D3 5C LDRB R3, [R2,R3] ; base64 key
.text:C1ACFE72 33 70 STRB R3, [R6]
.text:C1ACFE74 43 5D LDRB R3, [R0,R5]
.text:C1ACFE76 1B 01 LSLS R3, R3, #4
.text:C1ACFE78 30 24 MOVS R4, #0x30 ; '0'
.text:C1ACFE7A 1C 40 ANDS R4, R3
.text:C1ACFE7C 43 19 ADDS R3, R0, R5
.text:C1ACFE7E 08 00 MOVS R0, R1
.text:C1ACFE80 59 78 LDRB R1, [R3,#1]
.text:C1ACFE82 09 09 LSRS R1, R1, #4
.text:C1ACFE84 21 43 ORRS R1, R4
.text:C1ACFE86 51 5C LDRB R1, [R2,R1]
.text:C1ACFE88 71 70 STRB R1, [R6,#1]
.text:C1ACFE8A 59 78 LDRB R1, [R3,#1]
.text:C1ACFE8C 89 00 LSLS R1, R1, #2
.text:C1ACFE8E 3C 24 MOVS R4, #0x3C ; '<'
.text:C1ACFE90 0C 40 ANDS R4, R1
.text:C1ACFE92 99 78 LDRB R1, [R3,#2]
.text:C1ACFE94 89 09 LSRS R1, R1, #6
.text:C1ACFE96 21 43 ORRS R1, R4
.text:C1ACFE98 51 5C LDRB R1, [R2,R1]
.text:C1ACFE9A B1 70 STRB R1, [R6,#2]
.text:C1ACFE9C 99 78 LDRB R1, [R3,#2]
.text:C1ACFE9E 3F 23 MOVS R3, #0x3F ; '?'
.text:C1ACFEA0 0B 40 ANDS R3, R1
.text:C1ACFEA2 D1 5C LDRB R1, [R2,R3]
.text:C1ACFEA4 F1 70 STRB R1, [R6,#3]
.text:C1ACFEA6 01 00 MOVS R1, R0
.text:C1ACFEA8 04 98 LDR R0, [SP,#0x28+var_18]
.text:C1ACFEAA 04 36 ADDS R6, #4
.text:C1ACFEAC 03 35 ADDS R5, #3
.text:C1ACFEAE 8D 42 CMP R5, R1
.text:C1ACFEB0 DC DB BLT loc_C1ACFE6C ; 加密后数据
.text:C1ACFEB2 02 9A LDR R2, [SP,#0x28+var_20]
.text:C1ACFEB4
.text:C1ACFEB4 loc_C1ACFEB4 ; CODE XREF: base64_sub_C795AE10+52↑j
.text:C1ACFEB4 95 42 CMP R5, R2
.text:C1ACFEB6 1F DA BGE loc_C1ACFEF8
.text:C1ACFEB8 41 5D LDRB R1, [R0,R5]
.text:C1ACFEBA 14 00 MOVS R4, R2
.text:C1ACFEBC 8A 08 LSRS R2, R1, #2
.text:C1ACFEBE 25 49 LDR R1, =(aAbcdefghijklmn - 0xC1ACFEC4) ; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm"...
.text:C1ACFEC0 79 44 ADD R1, PC ; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm"...
.text:C1ACFEC2 8A 5C LDRB R2, [R1,R2]
.text:C1ACFEC4 32 70 STRB R2, [R6]
.text:C1ACFEC6 42 5D LDRB R2, [R0,R5]
.text:C1ACFEC8 13 01 LSLS R3, R2, #4
.text:C1ACFECA 30 22 MOVS R2, #0x30 ; '0'
.text:C1ACFECC 1A 40 ANDS R2, R3
.text:C1ACFECE 63 1E SUBS R3, R4, #1
.text:C1ACFED0 9D 42 CMP R5, R3
.text:C1ACFED2 14 D1 BNE loc_C1ACFEFE
.text:C1ACFED4 89 5C LDRB R1, [R1,R2]
.text:C1ACFED6 71 70 STRB R1, [R6,#1]
.text:C1ACFED8 3D 21 MOVS R1, #0x3D ; '='
.text:C1ACFEDA 1B E0 B loc_C1ACFF14
0x016.Base64编码后
Ll0zr8jDa2p/wp/2ORZSVx3LAf+i+kgLLSt+OXPrZecUk1nZFfLXy8dA3LWdDTQWnL9pxlSXgchpeiYDv/rz2aPSvjiwmUhKXlbwxohUeb1WhpanQNRhMm2kB1XxRkbvTqHKhvgeaQkLz20FO9MPtGN4ZW2t97LEdYbFNbVvQrr6r+dMVkHPNkaGPuARozWeaQGSSMkoMMJ+ve9rA1L+aQTgGSootSpmPnT3TPLrCPN0Z6HzPKtpxopqfsjfcIV7YcP7M8Wc847wXfhMA2hYTRO24or97heGubGuxo8hQyw=
0x017.将CRC值与Base64加密后值组合,(签名时使用到)
744d7275Ll0zr8jDa2p/wp/2ORZSVx3LAf+i+kgLLSt+OXPrZecUk1nZFfLXy8dA3LWdDTQWnL9pxlSXgchpeiYDv/rz2aPSvjiwmUhKXlbwxohUeb1WhpanQNRhMm2kB1XxRkbvTqHKhvgeaQkLz20FO9MPtGN4ZW2t97LEdYbFNbVvQrr6r+dMVkHPNkaGPuARozWeaQGSSMkoMMJ+ve9rA1L+aQTgGSootSpmPnT3TPLrCPN0Z6HzPKtpxopqfsjfcIV7YcP7M8Wc847wXfhMA2hYTRO24or97heGubGuxo8hQyw=
5. 第二次加密设备信息
0x001.设备信息数据:
{"voltage":"1","type":"user","brand":"google","psuc":"adb","temp":"1","suc":"midi,adb","id":"PQ2A.190305.002","sus":"midi,adb","tags":"release-keys","timestamp":"1631688160837","hardware":"sailfish","version":"9","model":"Pixel"}
0x002.压缩数据(解密PIC数据获取key(k1),流程和上面一样)解密后得到key meituan1sankuai0:
C42FEF80 78 9C 55 8E 41 12 82 30 0C 45 EF D2 35 32 2D 8C x.U.A..0.E...2-.
C42FEF90 08 EE BC 81 1E 21 D8 08 19 5B CA 34 80 32 8E 77 . .!...[...2.w
C42FEFA0 37 15 37 AE 92 FF F2 93 FC 97 5A 82 9B A0 43 75 7.7.......Z...Cu
C42FEFB0 54 46 65 6A 5A C7 D4 CE 8C 51 54 1B 61 B0 22 BB TFejZ..Ό QT.a.".
C42FEFC0 10 3A 87 02 46 9E AF A2 C1 B6 C9 8B 7E FC AD 6D .:..F.....ɋ ~..m
C42FEFD0 D8 93 A5 6C 9B 51 5A 3B 5F 8A 53 6E 1A 5D EA 7D ...l.QZ;_.Sn.]..
C42FEFE0 AE 75 F1 F5 F1 BF 4F 5E 27 12 D1 21 30 EE EE B8 .u....O^'...0...
C42FEFF0 72 A2 E4 91 27 D8 CE 57 A5 A9 EA DA 54 BA 2E 0F r......W........
0x003.AES 加密压缩后数据:
.text:C1AE7510 56 F0 30 FF BL AES_set_Encrypt_key_sub_CB601374 ; R0:key,R1:长度,R2:返回值
.text:C1AE7514 06 9A LDR R2, [SP,#0x120+byte_count]
.text:C1AE7516 01 20 MOVS R0, #1
.text:C1AE7518 69 46 MOV R1, SP
.text:C1AE751A 04 9B LDR R3, [SP,#0x120+var_110]
.text:C1AE751C 0B 60 STR R3, [R1,#0x120+var_120]
.text:C1AE751E 48 60 STR R0, [R1,#0x120+var_11C]
.text:C1AE7520 05 98 LDR R0, [SP,#0x120+p]
.text:C1AE7522 02 9C LDR R4, [SP,#0x120+var_118]
.text:C1AE7524 21 00 MOVS R1, R4
.text:C1AE7526 33 00 MOVS R3, R6
.text:C1AE7528 57 F0 7A FD BL AES_cbc_Encrypt_sub_CB602020 ; R0:原始数据,R1:返回,R2:大小,R3:key
.text:C1AE752C 06 98 LDR R0, [SP,#0x120+byte_count]
0x004.加密后数据(部分):
DEED6F00 2E 0F E3 72 62 1C 2B FB 35 B0 A9 CA E5 29 9F 79 ......+.5....).y
DEED6F10 C6 37 F0 02 CB 17 12 AE 6E 3D 5E AC EB A6 B5 DD ........n=^.릵 .
DEED6F20 33 B9 24 A9 F4 E0 6D 6C 64 D6 76 E4 65 88 6C 6F 3.$.....d.....lo
DEED6F30 F3 53 20 FA B3 F8 02 6C 6D BC 75 C9 87 66 92 CE .......lm.uɇ f..
DEED6F40 51 7A BC 09 BF 69 5D C0 C3 0A 71 77 46 5B E0 81 Qz...i]...qwF[..
DEED6F50 E2 15 67 05 5B 87 48 2D 0D D4 FA 99 EF 1C AC BD ....[.H-........
DEED6F60 53 26 56 13 16 91 68 A8 EC 5B 1F D8 5F F4 61 BB S&V...h.........
DEED6F70 FA 2A 2F 03 B5 3F 6E 02 6E 57 ED 46 8B A1 1A 0A .*/..?n.nW......
DEED6F80 F5 C5 E7 38 9F E5 8E 70 B1 8C D6 CF E8 D5 16 6F ...............o
DEED6F90 F6 36 3B A5 D8 2B 3D D9 83 BD 17 C5 3F AA 3D 96 ......=ك .....=.
0x005.Base64编码后数据:
Lg/jcmIcK/s1sKnK5SmfecY38ALLFxKubj1erOumtd0zuSSp9OBtbGTWduRliGxv81Mg+rP4AmxtvHXJh2aSzlF6vAm/aV3Awwpxd0Zb4IHiFWcFW4dILQ3U+pnvHKy9UyZWExaRaKjsWx/YX/Rhu/oqLwO1P24CblftRouhGgr1xec4n+WOcLGM1s/o1RZv9jY7pdgrPdmDvRfFP6o9liGe0rCXBoG85J1mm/6GmqQ=
6. 代码混淆
0x001.代码逻辑跳转动态计算:
模板1
.text:B845707C 01 10 CE E3 BIC R1, LR, #1
.text:B8457080 00 11 91 E7 LDR R1, [R1,R0,LSL#2]
.text:B8457084 0E 10 81 E0 ADD R1, R1, LR
.text:B8457088 08 E0 9D E5 LDR LR, [SP,#arg_8]
.text:B845708C 08 10 8D E5 STR R1, [SP,#arg_8]
.text:B8457090 03 80 BD E8 POP {R0,R1,PC}
模板2
.text:C18BDAC0 7F B5 PUSH {R0-R6,LR}
.text:C18BDAC2 7F B5 PUSH {R0-R6,LR}
.text:C18BDAC4 0D 26 MOVS R6, #0xD
.text:C18BDAC6 63 21 MOVS R1, #0x63 ; 'c'
.text:C18BDAC8 68 46 MOV R0, SP
.text:C18BDACA 10 30 ADDS R0, #0x10
.text:C18BDACC 02 26 MOVS R6, #2
.text:C18BDACE 08 30 ADDS R0, #8
.text:C18BDAD0 01 1D ADDS R1, R0, #4
.text:C18BDAD2 8D 46 MOV SP, R1
.text:C18BDAD4 04 A6 05 36 ADRL R6, byte_C18BDAED
.text:C18BDAD8 02 21 MOVS R1, #2
.text:C18BDADA 0A 36 ADDS R6, #0xA
.text:C18BDADC 76 18 ADDS R6, R6, R1
.text:C18BDADE 46 62 STR R6, [R0,#0x24]
.text:C18BDAE0 40 BC POP {R6}
.text:C18BDAE2 01 E0 B loc_C18BDAE8
.text:C18BDAE4 ;
.text:C18BDAE4 84 44 ADD R12, R0
.text:C18BDAE6 12 34 ADDS R4, #0x12
.text:C18BDAE8
.text:C18BDAE8 loc_C18BDAE8
.text:C18BDAE8 00 46 MOV R0, R0
.text:C18BDAEA 7F BD POP {R0-R6,PC}
0x002.字符串解密:
.text:C1D46060 DecString
.text:C1D46060 ; __unwind { // 91B9000
.text:C1D46060 10 B5 PUSH {R4,LR}
.text:C1D46062 01 2B CMP R3, #1
.text:C1D46064 08 DB BLT locret_C1D46078
.text:C1D46066
.text:C1D46066 loc_C1D46066
.text:C1D46066 0C 78 LDRB R4, [R1]
.text:C1D46068 54 40 EORS R4, R2
.text:C1D4606A 04 70 STRB R4, [R0]
.text:C1D4606C 01 3B SUBS R3, #1
.text:C1D4606E 01 30 ADDS R0, #1
.text:C1D46070 01 31 ADDS R1, #1
.text:C1D46072 03 32 ADDS R2, #3
.text:C1D46074 00 2B CMP R3, #0
.text:C1D46076 F6 D1 BNE loc_C1D46066
.text:C1D46078
.text:C1D46078 locret_C1D46078
.text:C1D46078 10 BD POP {R4,PC}
0x003.流程混淆:
.text:C1AF41F0 00 2C CMP R4, #0
.text:C1AF41F2 01 DA BGE loc_C1AF41F8
.text:C1AF41F4 FC F7 C8 FF BL loc_C1AF1188
.text:C1AF41F8
.text:C1AF41F8 loc_C1AF41F8 ; CODE XREF: .text:C1AF41F2↑j
.text:C1AF41F8 03 B5 PUSH {R0,R1,LR}
.text:C1AF41FA 01 48 LDR R0, =0x4A
.text:C1AF41FC FC F7 F0 FE BL ret_sub_CA67BFE0
.text:C1AF0FE0 ret_sub_CA67BFE0
.text:C1AF0FE0
.text:C1AF0FE0 D8 F7 4C E8 BLX jmp_sub_B288C07C
.text:C1AF0FE4 F0 1D ADDS R0, R6, #7
五、反爬虫mtgsig签名
1. 基本流程
0x001. APP每一个业务网络请求的请求头中都有mtgsig参数,该参数是请求体与其它参数计算的签名值。(最终会走到Native层进行签名计算)
java层代码如下:
public static String makeHeader(byte[] arg13, MODE arg14) {
Object[] v8 = new Object[]{arg13, arg14};
ChangeQuickRedirect v11 = WTSign.changeQuickRedirect;
if(PatchProxy.isSupport(v8, null, v11, true, "4371e5fcb0c4ae2bd761bbf35c1a43bf", 0x6000000000000000L)) {
return (String)PatchProxy.accessDispatch(v8, null, v11, true, "4371e5fcb0c4ae2bd761bbf35c1a43bf");
}
if(arg13 == null) {
return "-2003";
}
Object[] v13 = NBridge.main3(2, new Object[]{MTGuard.sAppKey, arg13, ((int)arg14.mode)});
if(v13 == null) {
return "-1001";
}
return (v13[0] instanceof Integer) ? v13[0] : ((String)v13[0]);
}
0x002. 加密系统环境信息:
// 是否root、ADB调试状态、USB调试模式等
{
"b1": "{\"1\":\"\",\"2\":\"1|2|3\",\"3\":\"\",\"4\":\"\",\"5\":\"\",\"6\":\"\",\"7\":\"2\",\"8\":\"\",\"9\":\"\",\"10\":\"\",\"11\":\"\",\"12\":\"32\",\"13\":\"\",\"14\":\"\",\"15\":\"\",\"33\":{\"0\":2,\"1\":\"\",\"2\":\"\",\"3\":\"\",\"4\":\"2|22\",\"5\":\"\",\"6\":\"\",\"7\":\"\",\"8\":\"\",\"9\":\"\",\"10\":\"\",\"11\":\"\",\"12\":\"\",\"13\":\"\",\"14\":\"2\",\"15\":\"\"}}",
"b2": 35,
"b3": 0,
"b4": "com.sankuai.meituan",
"b5": "11.12.204",
"b6": "1100120204",
"b7": 1631754559
}
0x003. 加密系统环境信息:
E53E7D80 78 9C 9D 91 C1 0E C2 20 10 44 FF 65 CF 0D 61 76 x........D.e..av
E53E7D90 81 2A DF C2 A5 35 1E 1A D3 7A D0 9E DA FE BB 40 .*...5....О ...@
E53E7DA0 4D C0 A4 C6 C4 D3 3E 66 17 66 36 2C D4 83 3C 2D M......f.f6,ԃ <-
E53E7DB0 81 10 C8 07 0A D4 04 E2 8C 58 79 95 7C 96 D2 32 ..........y.|...
E53E7DC0 05 6D 41 57 B0 CD C8 99 4F 45 3E 17 84 AE B8 72 .mAW....OE>....r
E53E7DD0 C5 6E 2B FB 5D 54 A6 A8 5C 51 D9 4A 9A 89 D1 D3 ..+.]T..\Q......
E53E7DE0 83 DC 1C AC 70 9C 9E 57 E6 9F 1B FC BF C0 B7 F8 ....p..W........
E53E7DF0 FC 99 7F DB A8 A1 9E C9 8B 8D 55 C8 EB 58 4C FC .......ɋ .U..XL.
E53E7E00 8B CB 7D 54 8F 6E BA CD DD A0 C6 EB F0 9C BB 29 ...T.n..........
E53E7E10 4D DA D8 02 14 58 B1 36 49 70 59 D0 1A AC DF 4A M....X.6IpY.....
0x004. 组合密钥:
1631754963 9b69f861-e054-4bc4-9daf-d36ae205ed3e //当前时间加APPkey
0x005. RC4加密压缩后数据:
.text:C881966C 11 99 LDR R1, [SP,#0x44]
.text:C881966E 0E 9E LDR R6, [SP,#0x38]
.text:C8819670 8A 59 LDR R2, [R1,R6]
.text:C8819672 16 A8 ADD R0, SP, #0x58 ; 'X'
.text:C8819674 1A F0 B0 FF BL initkey_sub_C79725D8 ; R1:key 15525971099b69f861-e054-4bc4-9daf-d36ae205ed3e R2:长度0x2E
.text:C8819678 10 9B LDR R3, [SP,#0x40]
.text:C881967A 29 00 MOVS R1, R5
.text:C881967C 2A 00 MOVS R2, R5
.text:C881967E 1A F0 B2 FF BL RC4_sub_C79725E6 ; R0:初始化的KEY,R1:压缩后数据,R3:压缩后大小
.text:C8819682 11 98 LDR R0, [SP,#0x44]
0x006.加密后:
E53E7D80 62 16 1F 8D D5 8D AF 42 8B D2 2C 32 77 29 5A 5F b...Ս .B...2w)Z_
E53E7D90 1B ED 38 9E F7 85 82 50 E0 FA D1 0A CD C4 6F 29 ..............o)
E53E7DA0 69 0C FA 10 AE 63 57 E1 11 EA A4 DF 12 36 B2 4D i....cW......6.M
E53E7DB0 A0 A2 78 3B 5A 60 E6 AB E9 4C A1 13 CD DB EB F0 ..x;Z`...L......
E53E7DC0 1B FC 49 D2 6C CE 5A 96 C6 6B 71 45 80 8B 5D B7 ..I.......qE..].
E53E7DD0 97 54 D5 58 0F F8 5E 68 25 CE 31 58 2D 04 C0 F2 .T....^h%..X-...
E53E7DE0 70 E7 D4 2E E7 C9 2C DD 07 F2 7A F4 CA 06 F3 CB p...............
E53E7DF0 C3 CC 14 76 0A 44 2C 48 A2 35 6B 7D 0D 8C 51 60 ...v.D,H.5k}..Q`
E53E7E00 3F A9 F8 C6 D1 02 04 2B A3 BF 86 3F 54 83 D4 43 ?......+...?T...
E53E7E10 39 9C AB 66 0D DD 21 90 2B 73 B9 1F C3 C2 B8 86 9..f....+s......
0x007.Base64加密:
An2sai6nXEuFYeKbDUk/qEo/7am8Jtn3O2Has5efofCux7iubGRCS8TKpjUgotJ6MGdQrBsvwh/peZwuikT+5rCr4RzN8SXXCeDOtZQ6sbo/snVdESSJweNqd6i/WbIwDOgv5eaWRQoISjdgNfW3hk7tf0QhsZFbOELcPxz5pRzo6d6EsBLFu5Mq8DbVNgsYF+6aqZ7302/G+Rr7MlUT2M9y3EjgjH01L39q/eRJ
0x008.获取dfpid (设备指纹)判断本地是否有存储,如果有优先读取本地,如果无反谢java层从服务器端获取,这部分详细分析见后面设备指纹部分:
.text:C8A93C78 F0 B5 PUSH {R4-R7,LR}
.text:C8A93C7A 03 AF ADD R7, SP, #0xC
.text:C8A93C7C 91 B0 SUB SP, SP, #0x44
.text:C8A93C7E 09 92 STR R2, [SP,#0x50+var_2C]
.text:C8A93C80 0A 91 STR R1, [SP,#0x50+var_28]
.text:C8A93C82 01 B4 PUSH {R0}
.text:C8A93C84 10 BC POP {R4}
.text:C8A93C86 8E 48 LDR R0, =(__stack_chk_guard_ptr - 0xC8A93C8C)
.text:C8A93C88 78 44 ADD R0, PC ; __stack_chk_guard_ptr
.text:C8A93C8A 05 68 LDR R5, [R0] ; __stack_chk_guard
.text:C8A93C8C 28 68 LDR R0, [R5]
.text:C8A93C8E 10 90 STR R0, [SP,#0x50+var_10]
.text:C8A93C90 20 00 MOVS R0, R4
.text:C8A93C92 00 F0 3F F9 BL getClassLoader_sub_C6FD9F14
.text:C8A93C96 00 26 MOVS R6, #0
.text:C8A93C98 00 28 CMP R0, #0
.text:C8A93C9A 00 D1 BNE loc_C8A93C9E
.text:C8A93C9C 06 E1 B loc_C8A93EAC
.text:C8A93C9E ; ---------------------------------------------------------------------------
.text:C8A93C9E
.text:C8A93C9E loc_C8A93C9E ; CODE XREF: main2_sub_B6891C78+22↑j
.text:C8A93C9E 0B 90 STR R0, [SP,#0x50+var_24]
.text:C8A93CA0 F6 F7 EE FC BL malloc_sub_C8BC6680
.text:C8A93CA4 9C 21 MOVS R1, #0x9C
.text:C8A93CA6 41 58 LDR R1, [R0,R1] ; char *
.text:C8A93CA8 0E AE ADD R6, SP, #0x50+var_18
.text:C8A93CAA 0D AA ADD R2, SP, #0x50+var_1C
.text:C8A93CAC 30 00 MOVS R0, R6 ; int
.text:C8A93CAE 6F F0 F7 FF BL basic_string_sub_B2943CA0
.text:C8A93CB2 20 00 MOVS R0, R4
.text:C8A93CB4 31 00 MOVS R1, R6
.text:C8A93CB6 03 F0 35 FF BL NewStringUTF_sub_C6B9DB24
.text:C8A93CBA 26 00 MOVS R6, R4
.text:C8A93CBC 04 00 MOVS R4, R0
.text:C8A93CBE 0E 98 LDR R0, [SP,#0x50+var_18]
.text:C8A93CC0 0C 38 SUBS R0, #0xC
.text:C8A93CC2 0F A9 ADD R1, SP, #0x50+var_14
.text:C8A93CC4 6F F0 40 FD BL free_sub_B2943748
.text:C8A93CC8 0C 96 STR R6, [SP,#0x50+var_20]
.text:C8A93CCA 30 00 MOVS R0, R6
.text:C8A93CCC 07 F0 FC FD BL ExceptionCheck_sub_C6BA18C8
.text:C8A93CD0 00 26 MOVS R6, #0
.text:C8A93CD2 00 28 CMP R0, #0
.text:C8A93CD4 07 D0 BEQ loc_C8A93CE6
.text:C8A93CD6 00 2C CMP R4, #0
.text:C8A93CD8 00 D1 BNE loc_C8A93CDC
.text:C8A93CDA E2 E0 B loc_C8A93EA2
.text:C8A93CDC ; ---------------------------------------------------------------------------
.text:C8A93CDC
.text:C8A93CDC loc_C8A93CDC ; CODE XREF: main2_sub_B6891C78+60↑j
.text:C8A93CDC 08 94 STR R4, [SP,#0x50+var_30]
.text:C8A93CDE 07 95 STR R5, [SP,#0x50+var_34]
.text:C8A93CE0 00 26 MOVS R6, #0
.text:C8A93CE2 0C 9C LDR R4, [SP,#0x50+var_20]
.text:C8A93CE4 D7 E0 B loc_C8A93E96
.text:C8A93CE6 ; ---------------------------------------------------------------------------
.text:C8A93CE6
.text:C8A93CE6 loc_C8A93CE6 ; CODE XREF: main2_sub_B6891C78+5C↑j
.text:C8A93CE6 00 2C CMP R4, #0
.text:C8A93CE8 00 D1 BNE loc_C8A93CEC
.text:C8A93CEA DA E0 B loc_C8A93EA2
.text:C8A93CEC ; ---------------------------------------------------------------------------
.text:C8A93CEC
.text:C8A93CEC loc_C8A93CEC ; CODE XREF: main2_sub_B6891C78+70↑j
.text:C8A93CEC 08 94 STR R4, [SP,#0x50+var_30]
.text:C8A93CEE 07 95 STR R5, [SP,#0x50+var_34]
.text:C8A93CF0 74 4E LDR R6, =(byte_C8B2D4E0 - 0xC8A93CF6)
.text:C8A93CF2 7E 44 ADD R6, PC ; byte_C8B2D4E0
.text:C8A93CF4 30 78 LDRB R0, [R6]
.text:C8A93CF6 00 28 CMP R0, #0
.text:C8A93CF8 0A D1 BNE loc_C8A93D10
.text:C8A93CFA 73 4C LDR R4, =(aJavaLangClassl - 0xC8A93D00) ; "java/lang/ClassLoader"
.text:C8A93CFC 7C 44 ADD R4, PC ; "java/lang/ClassLoader"
.text:C8A93CFE 73 49 LDR R1, =(unk_C8B1E8A0 - 0xC8A93D04)
.text:C8A93D00 79 44 ADD R1, PC ; unk_C8B1E8A0
.text:C8A93D02 00 25 MOVS R5, #0
.text:C8A93D04 15 23 MOVS R3, #0x15
.text:C8A93D06 20 00 MOVS R0, R4
.text:C8A93D08 2A 00 MOVS R2, R5
.text:C8A93D0A F7 F7 A9 F9 BL DecString
.text:C8A93D0E 65 75 STRB R5, [R4,#(aJavaLangClassl+0x15 - 0xC8B1E489)] ; ""
.text:C8A93D10
.text:C8A93D10 loc_C8A93D10 ; CODE XREF: main2_sub_B6891C78+80↑j
.text:C8A93D10 01 20 MOVS R0, #1
.text:C8A93D12 06 90 STR R0, [SP,#0x50+var_38]
.text:C8A93D14 30 70 STRB R0, [R6]
.text:C8A93D16 0C 9C LDR R4, [SP,#0x50+var_20]
.text:C8A93D18 20 68 LDR R0, [R4]
.text:C8A93D1A 82 69 LDR R2, [R0,#0x18]
.text:C8A93D1C 6C 49 LDR R1, =(aJavaLangClassl - 0xC8A93D22) ; "java/lang/ClassLoader"
.text:C8A93D1E 79 44 ADD R1, PC ; "java/lang/ClassLoader"
.text:C8A93D20 20 00 MOVS R0, R4
.text:C8A93D22 90 47 BLX R2
.text:C8A93D24 05 00 MOVS R5, R0
.text:C8A93D26 20 00 MOVS R0, R4
.text:C8A93D28 07 F0 CE FD BL ExceptionCheck_sub_C6BA18C8
.text:C8A93D2C 00 26 MOVS R6, #0
.text:C8A93D2E 00 28 CMP R0, #0
.text:C8A93D30 05 D0 BEQ loc_C8A93D3E
.text:C8A93D32 00 2D CMP R5, #0
.text:C8A93D34 20 B4 PUSH {R5}
.text:C8A93D36 02 BC POP {R1}
.text:C8A93D38 00 D0 BEQ loc_C8A93D3C
.text:C8A93D3A A8 E0 B loc_C8A93E8E
.text:C8A93D3C ; ---------------------------------------------------------------------------
.text:C8A93D3C
.text:C8A93D3C loc_C8A93D3C ; CODE XREF: main2_sub_B6891C78+C0↑j
.text:C8A93D3C AB E0 B loc_C8A93E96
.text:C8A93D3E ; ---------------------------------------------------------------------------
.text:C8A93D3E
.text:C8A93D3E loc_C8A93D3E ; CODE XREF: main2_sub_B6891C78+B8↑j
.text:C8A93D3E 00 2D CMP R5, #0
.text:C8A93D40 00 D1 BNE loc_C8A93D44
.text:C8A93D42 A8 E0 B loc_C8A93E96
.text:C8A93D44 ; ---------------------------------------------------------------------------
.text:C8A93D44
.text:C8A93D44 loc_C8A93D44 ; CODE XREF: main2_sub_B6891C78+C8↑j
.text:C8A93D44 05 95 STR R5, [SP,#0x50+var_3C]
.text:C8A93D46 63 4E LDR R6, =(byte_C8B2D4E1 - 0xC8A93D4C)
.text:C8A93D48 7E 44 ADD R6, PC ; byte_C8B2D4E1
.text:C8A93D4A 30 78 LDRB R0, [R6]
.text:C8A93D4C 00 28 CMP R0, #0
.text:C8A93D4E 0A D1 BNE loc_C8A93D66
.text:C8A93D50 61 4D LDR R5, =(aLoadclass - 0xC8A93D56) ; "loadClass"
.text:C8A93D52 7D 44 ADD R5, PC ; "loadClass"
.text:C8A93D54 61 49 LDR R1, =(aMkfnnRej - 0xC8A93D5A) ; "mkfnN|rej"
.text:C8A93D56 79 44 ADD R1, PC ; "mkfnN|rej"
.text:C8A93D58 01 22 MOVS R2, #1
.text:C8A93D5A 09 23 MOVS R3, #9
.text:C8A93D5C 28 00 MOVS R0, R5
.text:C8A93D5E F7 F7 7F F9 BL DecString
.text:C8A93D62 00 20 MOVS R0, #0
.text:C8A93D64 68 72 STRB R0, [R5,#(aLoadclass+9 - 0xC8B1E49F)] ; ""
.text:C8A93D66
.text:C8A93D66 loc_C8A93D66 ; CODE XREF: main2_sub_B6891C78+D6↑j
.text:C8A93D66 06 9D LDR R5, [SP,#0x50+var_38]
.text:C8A93D68 35 70 STRB R5, [R6]
.text:C8A93D6A 5D 4E LDR R6, =(byte_C8B2D4E2 - 0xC8A93D70)
.text:C8A93D6C 7E 44 ADD R6, PC ; byte_C8B2D4E2
.text:C8A93D6E 30 78 LDRB R0, [R6]
.text:C8A93D70 00 28 CMP R0, #0
.text:C8A93D72 0E D1 BNE loc_C8A93D92
.text:C8A93D74 5B 48 LDR R0, =(aLjavaLangStrin - 0xC8A93D7A) ; "(Ljava/lang/String;)Ljava/lang/Class;"
.text:C8A93D76 78 44 ADD R0, PC ; "(Ljava/lang/String;)Ljava/lang/Class;"
.text:C8A93D78 03 90 STR R0, [SP,#0x50+var_44]
.text:C8A93D7A 5B 49 LDR R1, =(unk_C8B1E8C0 - 0xC8A93D80)
.text:C8A93D7C 79 44 ADD R1, PC ; unk_C8B1E8C0
.text:C8A93D7E 02 22 MOVS R2, #2
.text:C8A93D80 25 23 MOVS R3, #0x25 ; '%'
.text:C8A93D82 04 93 STR R3, [SP,#0x50+var_40]
.text:C8A93D84 04 9B LDR R3, [SP,#0x50+var_40]
.text:C8A93D86 F7 F7 6B F9 BL DecString
.text:C8A93D8A 00 20 MOVS R0, #0
.text:C8A93D8C 04 99 LDR R1, [SP,#0x50+var_40]
.text:C8A93D8E 03 9A LDR R2, [SP,#0x50+var_44]
.text:C8A93D90 50 54 STRB R0, [R2,R1]
.text:C8A93D92
.text:C8A93D92 loc_C8A93D92 ; CODE XREF: main2_sub_B6891C78+FA↑j
.text:C8A93D92 35 70 STRB R5, [R6]
.text:C8A93D94 20 68 LDR R0, [R4]
.text:C8A93D96 84 21 MOVS R1, #0x84
.text:C8A93D98 46 58 LDR R6, [R0,R1]
.text:C8A93D9A 54 4A LDR R2, =(aLoadclass - 0xC8A93DA0) ; "loadClass"
.text:C8A93D9C 7A 44 ADD R2, PC ; "loadClass"
.text:C8A93D9E 54 4B LDR R3, =(aLjavaLangStrin - 0xC8A93DA4) ; "(Ljava/lang/String;)Ljava/lang/Class;"
.text:C8A93DA0 7B 44 ADD R3, PC ; "(Ljava/lang/String;)Ljava/lang/Class;"
.text:C8A93DA2 20 00 MOVS R0, R4
.text:C8A93DA4 05 99 LDR R1, [SP,#0x50+var_3C]
.text:C8A93DA6 B0 47 BLX R6
.text:C8A93DA8 05 00 MOVS R5, R0
.text:C8A93DAA 20 00 MOVS R0, R4
.text:C8A93DAC 07 F0 8C FD BL ExceptionCheck_sub_C6BA18C8
.text:C8A93DB0 00 26 MOVS R6, #0
.text:C8A93DB2 00 28 CMP R0, #0
.text:C8A93DB4 6A D1 BNE loc_C8A93E8C
.text:C8A93DB6 00 2D CMP R5, #0
.text:C8A93DB8 68 D0 BEQ loc_C8A93E8C
.text:C8A93DBA 20 00 MOVS R0, R4
.text:C8A93DBC 0B 99 LDR R1, [SP,#0x50+var_24]
.text:C8A93DBE 2A 00 MOVS R2, R5
.text:C8A93DC0 08 9B LDR R3, [SP,#0x50+var_30]
.text:C8A93DC2 00 F0 13 F9 BL CallObjectMethodV_sub_C6B99FEC
.text:C8A93DC6 05 00 MOVS R5, R0
.text:C8A93DC8 20 00 MOVS R0, R4
.text:C8A93DCA 07 F0 7D FD BL ExceptionCheck_sub_C6BA18C8
.text:C8A93DCE 00 28 CMP R0, #0
.text:C8A93DD0 04 D0 BEQ loc_C8A93DDC
.text:C8A93DD2 00 26 MOVS R6, #0
.text:C8A93DD4 00 2D CMP R5, #0
.text:C8A93DD6 05 99 LDR R1, [SP,#0x50+var_3C]
.text:C8A93DD8 53 D1 BNE loc_C8A93E82
.text:C8A93DDA 58 E0 B loc_C8A93E8E
.text:C8A93DDC ; ---------------------------------------------------------------------------
.text:C8A93DDC
.text:C8A93DDC loc_C8A93DDC ; CODE XREF: main2_sub_B6891C78+158↑j
.text:C8A93DDC 00 2D CMP R5, #0
.text:C8A93DDE 05 99 LDR R1, [SP,#0x50+var_3C]
.text:C8A93DE0 55 D0 BEQ loc_C8A93E8E
.text:C8A93DE2 04 95 STR R5, [SP,#0x50+var_40]
.text:C8A93DE4 43 4E LDR R6, =(byte_C8B2D4E3 - 0xC8A93DEA)
.text:C8A93DE6 7E 44 ADD R6, PC ; byte_C8B2D4E3
.text:C8A93DE8 30 78 LDRB R0, [R6]
.text:C8A93DEA 00 28 CMP R0, #0
.text:C8A93DEC 0A D1 BNE loc_C8A93E04
.text:C8A93DEE 42 4D LDR R5, =(aMain2 - 0xC8A93DF4) ; "main2"
.text:C8A93DF0 7D 44 ADD R5, PC ; "main2"
.text:C8A93DF2 42 49 LDR R1, =(aNgB - 0xC8A93DF8) ; "ng`b="
.text:C8A93DF4 79 44 ADD R1, PC ; "ng`b="
.text:C8A93DF6 03 22 MOVS R2, #3
.text:C8A93DF8 05 23 MOVS R3, #5
.text:C8A93DFA 28 00 MOVS R0, R5
.text:C8A93DFC F7 F7 30 F9 BL DecString
.text:C8A93E00 00 20 MOVS R0, #0
.text:C8A93E02 68 71 STRB R0, [R5,#(aMain2+5 - 0xC8B1E4CF)] ; ""
.text:C8A93E04
.text:C8A93E04 loc_C8A93E04 ; CODE XREF: main2_sub_B6891C78+174↑j
.text:C8A93E04 06 9D LDR R5, [SP,#0x50+var_38]
.text:C8A93E06 35 70 STRB R5, [R6]
.text:C8A93E08 3D 4E LDR R6, =(byte_C8B2D4E4 - 0xC8A93E0E)
.text:C8A93E0A 7E 44 ADD R6, PC ; byte_C8B2D4E4
.text:C8A93E0C 30 78 LDRB R0, [R6]
.text:C8A93E0E 00 28 CMP R0, #0
.text:C8A93E10 0E D1 BNE loc_C8A93E30
.text:C8A93E12 3C 48 LDR R0, =(aILjavaLangObje_0 - 0xC8A93E18) ; "(I[Ljava/lang/Object;)Ljava/lang/Object"...
.text:C8A93E14 78 44 ADD R0, PC ; "(I[Ljava/lang/Object;)Ljava/lang/Object"...
.text:C8A93E16 02 90 STR R0, [SP,#0x50+var_48]
.text:C8A93E18 3B 49 LDR R1, =(unk_C8B1E8F0 - 0xC8A93E1E)
.text:C8A93E1A 79 44 ADD R1, PC ; unk_C8B1E8F0
.text:C8A93E1C 04 22 MOVS R2, #4
.text:C8A93E1E 28 23 MOVS R3, #0x28 ; '('
.text:C8A93E20 03 93 STR R3, [SP,#0x50+var_44]
.text:C8A93E22 03 9B LDR R3, [SP,#0x50+var_44]
.text:C8A93E24 F7 F7 1C F9 BL DecString
.text:C8A93E28 00 20 MOVS R0, #0
.text:C8A93E2A 03 99 LDR R1, [SP,#0x50+var_44]
.text:C8A93E2C 02 9A LDR R2, [SP,#0x50+var_48]
.text:C8A93E2E 50 54 STRB R0, [R2,R1]
.text:C8A93E30
.text:C8A93E30 loc_C8A93E30 ; CODE XREF: main2_sub_B6891C78+198↑j
.text:C8A93E30 35 70 STRB R5, [R6]
.text:C8A93E32 71 20 80 00 MOVS R0, #0x1C4
.text:C8A93E36 21 68 LDR R1, [R4]
.text:C8A93E38 0D 58 LDR R5, [R1,R0]
.text:C8A93E3A 34 4A LDR R2, =(aMain2 - 0xC8A93E40) ; "main2"
.text:C8A93E3C 7A 44 ADD R2, PC ; "main2"
.text:C8A93E3E 34 4B LDR R3, =(aILjavaLangObje_0 - 0xC8A93E44) ; "(I[Ljava/lang/Object;)Ljava/lang/Object"...
.text:C8A93E40 7B 44 ADD R3, PC ; "(I[Ljava/lang/Object;)Ljava/lang/Object"...
.text:C8A93E42 20 00 MOVS R0, R4
.text:C8A93E44 04 99 LDR R1, [SP,#0x50+var_40]
.text:C8A93E46 A8 47 BLX R5
.text:C8A93E48 05 00 MOVS R5, R0
.text:C8A93E4A 20 00 MOVS R0, R4
.text:C8A93E4C 07 F0 3C FD BL ExceptionCheck_sub_C6BA18C8
.text:C8A93E50 00 26 MOVS R6, #0
.text:C8A93E52 00 28 CMP R0, #0
.text:C8A93E54 14 D1 BNE loc_C8A93E80
.text:C8A93E56 2A 00 MOVS R2, R5
.text:C8A93E58 00 2D CMP R5, #0
.text:C8A93E5A 04 9D LDR R5, [SP,#0x50+var_40]
.text:C8A93E5C 11 D0 BEQ loc_C8A93E82
.text:C8A93E5E 68 46 MOV R0, SP
.text:C8A93E60 09 99 LDR R1, [SP,#0x50+var_2C]
.text:C8A93E62 01 60 STR R1, [R0,#0x50+var_50]
.text:C8A93E64 20 00 MOVS R0, R4
.text:C8A93E66 29 00 MOVS R1, R5
.text:C8A93E68 0A 9B LDR R3, [SP,#0x50+var_28]
.text:C8A93E6A 00 F0 DD F8 BL CallStaticObjectMethodV_sub_B6892028
.text:C8A93E6E 0A 90 STR R0, [SP,#0x50+var_28]
.text:C8A93E70 20 00 MOVS R0, R4
.text:C8A93E72 07 F0 29 FD BL ExceptionCheck_sub_C6BA18C8
.text:C8A93E76 00 26 MOVS R6, #0
.text:C8A93E78 00 28 CMP R0, #0
.text:C8A93E7A 02 D1 BNE loc_C8A93E82
.text:C8A93E7C 0A 9E LDR R6, [SP,#0x50+var_28]
.text:C8A93E7E 00 E0 B loc_C8A93E82
.text:C8A93E80 ; ---------------------------------------------------------------------------
.text:C8A93E80
.text:C8A93E80 loc_C8A93E80 ; CODE XREF: main2_sub_B6891C78+1DC↑j
.text:C8A93E80 04 9D LDR R5, [SP,#0x50+var_40]
.text:C8A93E82
.text:C8A93E82 loc_C8A93E82 ; CODE XREF: main2_sub_B6891C78+160↑j
.text:C8A93E82 ; main2_sub_B6891C78+1E4↑j ...
.text:C8A93E82 20 68 LDR R0, [R4]
.text:C8A93E84 C2 6D LDR R2, [R0,#0x5C]
.text:C8A93E86 20 00 MOVS R0, R4
.text:C8A93E88 29 00 MOVS R1, R5
.text:C8A93E8A 90 47 BLX R2
.text:C8A93E8C
.text:C8A93E8C loc_C8A93E8C ; CODE XREF: main2_sub_B6891C78+13C↑j
.text:C8A93E8C ; main2_sub_B6891C78+140↑j
.text:C8A93E8C 05 99 LDR R1, [SP,#0x50+var_3C]
0x009.获取到的dfpid如下:
DAD796C46B5A6525F4B89DF661A97C7A218A219FC24B93F689DEBD92
0x010.获取xid (设备指纹)判断本地是否有存储,如果有优先读取本地,如果无反谢java层从服务器端获取,APP第一次运行进就用UUID与时间加密生成一个,这部分详细分析见后面设备指纹部分:
.text:C8AEE3A4 F0 B5 PUSH {R4-R7,LR}
.text:C8AEE3A6 03 AF ADD R7, SP, #0xC
.text:C8AEE3A8 81 B0 SUB SP, SP, #4
.text:C8AEE3AA 0C 00 MOVS R4, R1
.text:C8AEE3AC 06 00 MOVS R6, R0
.text:C8AEE3AE 00 23 MOVS R3, #0
.text:C8AEE3B0 20 00 MOVS R0, R4
.text:C8AEE3B2 11 00 MOVS R1, R2
.text:C8AEE3B4 1A 00 MOVS R2, R3
.text:C8AEE3B6 A5 F7 5F FC BL main2_sub_B6891C78 ; 反射调用java层
.text:C8AEE3BA 05 00 MOVS R5, R0
.text:C8AEE3BC 20 00 MOVS R0, R4
.text:C8AEE3BE AD F7 83 FA BL ExceptionCheck_sub_C6BA18C8
.text:C8AEE3C2 00 28 CMP R0, #0
.text:C8AEE3C4 09 D0 BEQ loc_C8AEE3DA
.text:C8AEE3C6 9C F7 5B F9 BL malloc_sub_C8BC6680
.text:C8AEE3CA 01 00 MOVS R1, R0
.text:C8AEE3CC 7C 31 ADDS R1, #0x7C ; '|'
.text:C8AEE3CE 30 00 MOVS R0, R6
.text:C8AEE3D0 15 F0 30 FA BL empty_sub_C6C09834
.text:C8AEE3D4 00 2D CMP R5, #0
.text:C8AEE3D6 07 D1 BNE loc_C8AEE3E8
.text:C8AEE3D8 13 E0 B loc_C8AEE402
.text:C8AEE3DA ; ---------------------------------------------------------------------------
.text:C8AEE3DA
.text:C8AEE3DA loc_C8AEE3DA ; CODE XREF: main2_sub_B292E3A4+20↑j
.text:C8AEE3DA 00 2D CMP R5, #0
.text:C8AEE3DC 0A D0 BEQ loc_C8AEE3F4
.text:C8AEE3DE 30 00 MOVS R0, R6
.text:C8AEE3E0 21 00 MOVS R1, R4
.text:C8AEE3E2 2A 00 MOVS R2, R5
.text:C8AEE3E4 A9 F7 CE FC BL String_sub_B28D7D84 ; 出现字符串
0x011.获取到的xid如下:
Rs8NOy0BFS5JQxfdOoIxpMnKV3iqYWcblAjp0vpnWZyNzyF9rfsi3ekpm4ScaIZgeImizX/5AbS3e838Or4el4+PPPI2kD8XW+8vbvjDBSM=
0x012.组合json(每一个字段的解释,a0:版本,a1:appkey, a3:版本,a4:时间,a5:加密的设备环境,a6:固定数字,a7:xid,a8:dfpid,a9:初始化时加密的设备环境信息(前8字符中CRC:f4ec12ef)):
{
"a0": "2.0",
"a1": "9b69f861-e054-4bc4-9daf-d36ae205ed3e",
"a3": 2,
"a4": 1631754963,
"a5": "An2sai6nXEuFYeKbDUk/qEo/7am8Jtn3O2Has5efofCux7iubGRCS8TKpjUgotJ6MGdQrBsvwh/peZwuikT+5rCr4RzN8SXXCeDOtZQ6sbo/snVdESSJweNqd6i/WbIwDOgv5eaWRQoISjdgNfW3hk7tf0QhsZFbOELcPxz5pRzo6d6EsBLFu5Mq8DbVNgsYF+6aqZ7302/G+Rr7MlUT2M9y3EjgjH01L39q/eRJ",
"a6": 1025,
"a7": "Rs8NOy0BFS5JQxfdOoIxpMnKV3iqYWcblAjp0vpnWZyNzyF9rfsi3ekpm4ScaIZgeImizX/5AbS3e838Or4el4+PPPI2kD8XW+8vbvjDBSM=",
"a8": "DAD796C46B5A6525F4B89DF661A97C7A218A219FC24B93F689DEBD92",
"a9": "f4ec12efNkQBqdtVlV78x1/Mln2Us/xw171NuJjdEXrGWsFDdMV5Te45wqjL0nPO8OFFKjvKthvva+lS9xqhMhSt1WZRjDYpsWc/eh3z4F2JTv3MOh8NEDmk7Frthx5/bczdDIKvRP0QneTfNKSm116fUjdLhOEYlNbym/xI+5jZAEJGfGjltFLEOmtOwgxasgHQh2woMl/vAyr7ePuoVC6wEcbv2+w6n/+Pl1U1KO2YcTw4peiZDqC7iHpTVQH4fWri9R5+Ev1zx/xObVqoxqe3TEW/t2EIRqQ4QoRZRix0xC6C280faz8U5vOqafUnm+qev7tjs7SOV4SNxBv+LEJTxr5IJU302FJEk/CqhKoz5eWRYtT5Z52kEanlfu4AGHcJLC343kpI3GxYw7uPeewA/Ye0qDgZUyfj0MPpaYMPj0UmtvnbXEU4+FaRaCb/LsQtWdOtEiEKveUQU9bTW4NfHch2+6gcHP2/E+UQSlREX67PPa9XN8tgL4H6qzghiE1NL3gYw0rrjzEXiO6jsjvIdzwDjeab9woJyr8W3xSACz3sezUS+AJAKohnJvlQkFM9cdG3lPYS7gByAK++K2/vI714kxJHqCZQQMbVNsoWj5w64YL+sE1A4byzOPgK71oPb9w6Cb+KwVlDtqH8F5vlVkO23Iq8E28BI2vQuq5TLRzMunjo45Ks2Py9ZZuHkGb+QIVpUz6ViB+JlUONKinIJF1p6g==",
"a10": "{}",
"x0": 1
}
2. 计算请求体签名值
0x001. 获取请求体数据:
.text:C8A8FA4C 29 68 LDR R1, [R5]
.text:C8A8FA4E 0A 58 LDR R2, [R1,R0]
.text:C8A8FA50 28 00 MOVS R0, R5
.text:C8A8FA52 31 00 MOVS R1, R6
.text:C8A8FA54 90 47 BLX R2 ; 获取body长度
.text:C8A8FA56 0A 90 STR R0, [SP,#0x28]
.text:C8A8FA58 28 00 MOVS R0, R5
.text:C8A8FA5A 0B F0 35 FF BL ExceptionCheck_sub_C6BA18C8
.text:C8A8FA5E 00 28 CMP R0, #0
.text:C8A8FAF0 00 00 MOVS R0, R0
.text:C8A8FAF2 00 00 MOVS R0, R0
.text:C8A8FAF4 D8 74 STRB R0, [R3,#0x13]
.text:C8A8FAF6 86 1B SUBS R6, R0, R6
.text:C8A8FAF8 10 99 LDR R1, [SP,#0xC+arg_34] ; 获取body
.text:C8A8FAFA 0B 20 MOVS R0, #0xB
.text:C8A8FAFC C2 43 MVNS R2, R0
.text:C8A8FAFE 03 91 STR R1, [SP,#0xC+arg_0]
.text:C8A8FB00 08 68 LDR R0, [R1]
.text:C8A8FB02 02 92 STR R2, [SP,#0xC+var_4]
.text:C8A8FB04 80 58 LDR R0, [R0,R2]
.text:C8A8FB06 0A 9C LDR R4, [SP,#0xC+arg_1C]
.text:C8A8FB08 00 19 ADDS R0, R0, R4
.text:C8A8FB0A 04 90 STR R0, [SP,#0xC+arg_4]
.text:C8A8FB0C 46 1C ADDS R6, R0, #1
.text:C8A8FB0E 30 00 MOVS R0, R6
.text:C8A8FB10 FA F7 EA E8 BLX malloc ; 分配body存储空间
.text:C8A8FB14 00 21 MOVS R1, #0
.text:C8A8FB16 06 91 STR R1, [SP,#0xC+arg_C]
.text:C8A8FB18 32 00 MOVS R2, R6
.text:C8A8FB1A 06 00 MOVS R6, R0
.text:C8A8FB1C 20 F0 D0 FC BL memset_sub_C6BB64C0
.text:C8A8FB20 19 20 40 01 MOVS R0, #0x320
.text:C8A8FB24 29 68 LDR R1, [R5]
.text:C8A8FB26 08 58 LDR R0, [R1,R0]
.text:C8A8FB28 05 90 STR R0, [SP,#0xC+arg_8]
.text:C8A8FB2A 68 46 MOV R0, SP
.text:C8A8FB2C 06 60 STR R6, [R0,#0xC+var_C]
.text:C8A8FB2E 28 00 MOVS R0, R5
.text:C8A8FB30 07 99 LDR R1, [SP,#0xC+arg_10]
.text:C8A8FB32 06 9A LDR R2, [SP,#0xC+arg_C]
.text:C8A8FB34 23 00 MOVS R3, R4
.text:C8A8FB36 05 9C LDR R4, [SP,#0xC+arg_8]
.text:C8A8FB38 A0 47 BLX R4 ; GetByteArrayRegion
.text:C8A8FB38 ; 获取要计算签名的body值
.text:C8A8FB3A 28 00 MOVS R0, R5
.text:C8A8FB3C 0B F0 C4 FE BL ExceptionCheck_sub_C6BA18C8
.text:C8A8FB40 00 28 CMP R0, #0
0x002. 获取的数据(部分):
CB092000 50 4F 53 54 20 2F 76 35 2F 73 69 67 6E 20 7B 22 POST /v5/sign {"
CB092010 64 61 74 61 22 3A 22 62 4A 62 50 67 72 4B 49 42 data":"bJbPgrKIB
CB092020 6A 6D 4E 4E 2B 6B 63 30 39 66 66 6F 54 70 67 48 jmNN+kc09ffoTpgH
CB092030 57 39 57 46 7A 43 6B 67 75 4D 4E 71 50 52 57 68 W9WFzCkguMNqPRWh
CB092040 6A 70 41 67 2B 4E 62 45 70 76 47 62 44 42 54 47 jpAg+NbEpvGbDBTG
CB092050 6E 79 31 38 6C 6C 39 38 75 43 37 44 68 67 2B 33 ny18ll98uC7Dhg+3
CB092060 56 44 39 31 62 38 50 67 67 47 2F 47 56 61 52 59 VD91b8PggG/GVaRY
CB092070 71 4D 4C 37 33 36 30 6E 63 71 41 59 57 37 68 4A qML7360ncqAYW7hJ
CB092080 4A 52 69 34 44 59 73 50 31 66 73 59 35 38 4F 79 JRi4DYsP1fsY58Oy
0x003. 解密PIC数据获取key (a7),解密流程与初始化时一样。解密后的值:
{"a1":0,"a10":400,"a2":"com.sankuai.meituan","a11":"c1ee9178c95d9ec75f0f076a374df94a032d54c8576298d4f75e653de3705449","a3":"0a16ecd60eb56a6a3349f66cdcf7f7bf5190e5a42d6280d8dc0ee3be228398ec","a4":1100030200,"k0":{"k1":"meituan1sankuai0","k2":"meituan0sankuai1","k3":"$MXMYBS@HelloPay","k4":"Maoyan010iauknaS","k5":"34281a9dw2i701d4","k6":"X%rj@KiuU+|xY}?f"},"a5":"11.3.200","a0":"pw/LhTdeoTTyaxPHcHMy+/ssGNS1ihNkrJ+uBI74FIfd90KlTil1m0i7FF/n0bhY","a6":"/HntC9XIfdUyII/UiVfx020EQPpHz2XZY3qzM2aiNmM0i0pB1yeSO689TY9SBB3s","a7":"QsHnU6kFjTYR8Z6tHEvkGMO2Hrt+NRnVQhmxg6EtVBzuzQcBpma3AdhTWNMpesFT","c0":{"c1":true,"c2":false},"a9":"SDEzWXi5LHL/cuMCZ1zYyv+0hIViqWWf+ShbUYILWf4=","a8":1603800117167}
0x004. 解析json获取a7:
QsHnU6kFjTYR8Z6tHEvkGMO2Hrt+NRnVQhmxg6EtVBzuzQcBpma3AdhTWNMpesFT
0x005. appkey与pic中的a7异或:
.text:C8A90424 20 00 MOVS R0, R4
.text:C8A90426 02 99 LDR R1, [SP,#8]
.text:C8A90428 7E F0 12 FE BL sub_C8B0F050
.text:C8A9042C 03 98 LDR R0, [SP,#0xC]
.text:C8A9042E 00 5D LDRB R0, [R0,R4] ; 取a7 QsHnU6kFjTYR8Z6tHEvkGMO2Hrt+NRnVQhmxg6EtVBzuzQcBpma3AdhTWNMpesFT
.text:C8A90430 72 5C LDRB R2, [R6,R1] ; appkey 9b69f861-e054-4bc4-9daf-d36ae205ed3e
.text:C8A90432 42 40 EORS R2, R0
.text:C8A90434 6A 54 STRB R2, [R5,R1]
.text:C8A90436 01 34 ADDS R4, #1
.text:C8A90438 04 98 LDR R0, [SP,#0x10]
.text:C8A9043A A0 42 CMP R0, R4 ; 判断是否结束
.text:C8A9043C F2 D1 BNE loc_C8A90424
.text:C8A9043E 03 B5 PUSH {R0,R1,LR}
.text:C8A90440 01 48 LDR R0, =0
.text:C8A90442 FF F7 DB FF BL loc_C8A903FC
0x006. 异或后的值:
BC79D120 5E 54 73 4D 30 7A 4C 44 57 34 53 77 44 40 55 51 ^TsM0zLDW4SwD@UQ
BC79D130 22 50 45 6D 33 2F 2B 5D 01 40 70 35 2B 60 5E 63 "PEm3/+].@p5+`^c
BC79D140 34 0C 5E 1D
0x007. 再次异或:
.text:C8A91C00 loc_C8A91C00 ; CODE XREF: hmac_sha256_sub_BB754BAC+6C↓j
.text:C8A91C00 43 A9 ADD R1, SP, #0x160+var_54
.text:C8A91C02 09 5C LDRB R1, [R1,R0] ; 取APPkey与a7加密后数据
.text:C8A91C04 5C 22 MOVS R2, #0x5C ; '\'
.text:C8A91C06 4A 40 EORS R2, R1
.text:C8A91C08 32 AB ADD R3, SP, #0x160+var_98
.text:C8A91C0A 1A 54 STRB R2, [R3,R0] ; 存值
.text:C8A91C0C 36 22 MOVS R2, #0x36 ; '6'
.text:C8A91C0E 4A 40 EORS R2, R1
.text:C8A91C10 21 A9 ADD R1, SP, #0x160+var_DC
.text:C8A91C12 0A 54 STRB R2, [R1,R0] ; 存值
.text:C8A91C14 01 30 ADDS R0, #1
.text:C8A91C16 40 28 CMP R0, #0x40 ; '@' ; 判断是否结束
.text:C8A91C18 F2 D1 BNE loc_C8A91C00
0x008. 异或后的值:
CB0D3000 68 62 45 7B 06 4C 7A 72 61 02 65 41 72 76 63 67 hbE{.Lzra.eArvcg
CB0D3010 14 66 73 5B 05 19 1D 6B 37 76 46 03 1D 56 68 55 .fs[...k7vF..VhU
CB0D3020 02 3A 68 2B 36 36 36 36 36 36 36 36 36 36 36 36 .:h+666666666666
CB0D3030 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 6666666666666666
0x009. 将异或后的值与请求体组合:
CB0D3000 68 62 45 7B 06 4C 7A 72 61 02 65 41 72 76 63 67 hbE{.Lzra.eArvcg
CB0D3010 14 66 73 5B 05 19 1D 6B 37 76 46 03 1D 56 68 55 .fs[...k7vF..VhU
CB0D3020 02 3A 68 2B 36 36 36 36 36 36 36 36 36 36 36 36 .:h+666666666666
CB0D3030 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 6666666666666666
CB0D3040 50 4F 53 54 20 2F 76 35 2F 73 69 67 6E 20 7B 22 POST /v5/sign {"
CB0D3050 64 61 74 61 22 3A 22 62 4A 62 50 67 72 4B 49 42 data":"bJbPgrKIB
CB0D3060 6A 6D 4E 4E 2B 6B 63 30 39 66 66 6F 54 70 67 48 jmNN+kc09ffoTpgH
CB0D3070 57 39 57 46 7A 43 6B 67 75 4D 4E 71 50 52 57 68 W9WFzCkguMNqPRWh
CB0D3080 6A 70 41 67 2B 4E 62 45 70 76 47 62 44 42 54 47 jpAg+NbEpvGbDBTG
CB0D3090 6E 79 31 38 6C 6C 39 38 75 43 37 44 68 67 2B 33 ny18ll98uC7Dhg+3
CB0D30A0 56 44 39 31 62 38 50 67 67 47 2F 47 56 61 52 59 VD91b8PggG/GVaRY
CB0D30B0 71 4D 4C 37 33 36 30 6E 63 71 41 59 57 37 68 4A qML7360ncqAYW7hJ
0x010. 计算组合值的MD5:
.text:C8A91C60 2A 00 MOVS R2, R5
.text:C8A91C62 00 F0 79 F9 BL md5_sub_BB7CFF58 ; R0:原始数后,R1:大小,R2:返回
.text:C8A91C66 05 AE ADD R6, SP, #0x160+var_14C
.text:C8A91C68 55 21 MOVS R1, #0x55 ; 'U'
.text:C8A91C6A 30 00 MOVS R0, R6
.text:C8A91C6C F8 F7 54 E8 BLX __aeabi_memclr4
.text:C8A91C70 32 A9 ADD R1, SP, #0x160+var_98
.text:C8A91C72 30 00 MOVS R0, R6
.text:C8A91C74 02 9A LDR R2, [SP,#0x160+var_158]
.text:C8A91C76 1E F0 48 FC BL getvalu_sub_C87B550A
.text:C8A91C7A 30 00 MOVS R0, R6
.text:C8A91C7C 40 30 ADDS R0, #0x40 ; '@'
.text:C8A91C7E 14 22 MOVS R2, #0x14
.text:C8A91C80 29 00 MOVS R1, R5
.text:C8A91C82 1E F0 42 FC BL getvalu_sub_C87B550A
.text:C8A91C86 54 21 MOVS R1, #0x54 ; 'T'
.text:C8A91C88 30 00 MOVS R0, R6
.text:C8A91C8A 01 9A LDR R2, [SP,#0x160+var_15C]
.text:C8A91C8C 00 F0 64 F9 BL md5_sub_BB7CFF58 ; R0:原始数后,R1:大小,R2:返回
.text:C8A91C90 20 00 MOVS R0, R4 ; p
.text:C8A91C92 F8 F7 30 E8 BLX free
0x011. 计算后得到的值:
F0 EF 16 F8 BD C6 7B CC 8C B4 8F AC 4C EC 7A DB A8 A8 D1 05
0x012. 解密PIC数据获取KEY(a9)
解析json获取a3:0a16ecd60eb56a6a3349f66cdcf7f7bf5190e5a42d6280d8dc0ee3be228398ec
a3为AES KEY解密a9解密后数据,该值作为加密body md5值的key:
3ey2scPxek170m6K
0x013. AES加密Body计算得到的MD5值:
IV 0102030405060708
key:3ey2scPxek170m6K
.text:C8AA94F0 E0 F7 FA EB BLX malloc
.text:C8AA94F4 00 26 MOVS R6, #0
.text:C8AA94F6 00 28 CMP R0, #0
.text:C8AA94F8 1C D0 BEQ loc_C8AA9534
.text:C8AA94FA 4A 99 LDR R1, [SP,#0x120+arg_0]
.text:C8AA94FC 03 91 STR R1, [SP,#0x120+var_114]
.text:C8AA94FE 07 AE ADD R6, SP, #0x120+var_104
.text:C8AA9500 F4 21 MOVS R1, #0xF4
.text:C8AA9502 02 90 STR R0, [SP,#0x120+var_118]
.text:C8AA9504 30 00 MOVS R0, R6
.text:C8AA9506 E0 F7 08 EC BLX __aeabi_memclr4
.text:C8AA950A 80 21 MOVS R1, #0x80
.text:C8AA950C 20 00 MOVS R0, R4
.text:C8AA950E 32 00 MOVS R2, R6
.text:C8AA9510 56 F0 30 FF BL AES_set_Encrypt_key_sub_CB601374 ; R0:key,R1:长度,R2:返回值
.text:C8AA9514 06 9A LDR R2, [SP,#0x120+byte_count]
.text:C8AA9516 01 20 MOVS R0, #1
.text:C8AA9518 69 46 MOV R1, SP
.text:C8AA951A 04 9B LDR R3, [SP,#0x120+var_110]
.text:C8AA951C 0B 60 STR R3, [R1,#0x120+var_120]
.text:C8AA951E 48 60 STR R0, [R1,#0x120+var_11C]
.text:C8AA9520 05 98 LDR R0, [SP,#0x120+p]
.text:C8AA9522 02 9C LDR R4, [SP,#0x120+var_118]
.text:C8AA9524 21 00 MOVS R1, R4
.text:C8AA9526 33 00 MOVS R3, R6
.text:C8AA9528 57 F0 7A FD BL AES_cbc_Encrypt_sub_CB602020 ; R0:原始数据,R1:返回,R2:大小,R3:key
.text:C8AA952C 06 98 LDR R0, [SP,#0x120+byte_count]
.text:C8AA952E 03 99 LDR R1, [SP,#0x120+var_114]
.text:C8AA9530 08 60 STR R0, [R1]
.text:C8AA9532 26 00 MOVS R6, R4
.text:C8AA9534
.text:C8AA9534 loc_C8AA9534 ; CODE XREF: Aes_sub_CB5AA4B8+40↑j
.text:C8AA9534 05 98 LDR R0, [SP,#0x120+p] ; p
.text:C8AA9536 E0 F7 DE EB BLX free
0x014. 加密后数据:
C7B9C460 06 34 4B B7 17 3B 29 9D FE B9 85 8D 24 6C 52 AE
C7B9C470 BB AF 22 3F 8E 43 FB C5 66 2B 54 E2 C6 6A 54 EA
0x015. 转换成字符串:
06344bb7173b299dfeb9858d246c52aebbaf223f8e43fbc5662b54e2c66a54ea
0x016. 组合json,生成签名(a2:就是请求体签名值,其它字段上面已经解释过,然后将签名值返回到java层,整个签名流程就完成了):
{
"a0": "2.0",
"a1": "9b69f861-e054-4bc4-9daf-d36ae205ed3e",
"a3": 2,
"a4": 1631754963,
"a5": "An2sai6nXEuFYeKbDUk/qEo/7am8Jtn3O2Has5efofCux7iubGRCS8TKpjUgotJ6MGdQrBsvwh/peZwuikT+5rCr4RzN8SXXCeDOtZQ6sbo/snVdESSJweNqd6i/WbIwDOgv5eaWRQoISjdgNfW3hk7tf0QhsZFbOELcPxz5pRzo6d6EsBLFu5Mq8DbVNgsYF+6aqZ7302/G+Rr7MlUT2M9y3EjgjH01L39q/eRJ",
"a6": 1025,
"a7": "Rs8NOy0BFS5JQxfdOoIxpMnKV3iqYWcblAjp0vpnWZyNzyF9rfsi3ekpm4ScaIZgeImizX/5AbS3e838Or4el4+PPPI2kD8XW+8vbvjDBSM=",
"a8": "DAD796C46B5A6525F4B89DF661A97C7A218A219FC24B93F689DEBD92",
"a9": "f4ec12efNkQBqdtVlV78x1/Mln2Us/xw171NuJjdEXrGWsFDdMV5Te45wqjL0nPO8OFFKjvKthvva+lS9xqhMhSt1WZRjDYpsWc/eh3z4F2JTv3MOh8NEDmk7Frthx5/bczdDIKvRP0QneTfNKSm116fUjdLhOEYlNbym/xI+5jZAEJGfGjltFLEOmtOwgxasgHQh2woMl/vAyr7ePuoVC6wEcbv2+w6n/+Pl1U1KO2YcTw4peiZDqC7iHpTVQH4fWri9R5+Ev1zx/xObVqoxqe3TEW/t2EIRqQ4QoRZRix0xC6C280faz8U5vOqafUnm+qev7tjs7SOV4SNxBv+LEJTxr5IJU302FJEk/CqhKoz5eWRYtT5Z52kEanlfu4AGHcJLC343kpI3GxYw7uPeewA/Ye0qDgZUyfj0MPpaYMPj0UmtvnbXEU4+FaRaCb/LsQtWdOtEiEKveUQU9bTW4NfHch2+6gcHP2/E+UQSlREX67PPa9XN8tgL4H6qzghiE1NL3gYw0rrjzEXiO6jsjvIdzwDjeab9woJyr8W3xSACz3sezUS+AJAKohnJvlQkFM9cdG3lPYS7gByAK++K2/vI714kxJHqCZQQMbVNsoWj5w64YL+sE1A4byzOPgK71oPb9w6Cb+KwVlDtqH8F5vlVkO23Iq8E28BI2vQuq5TLRzMunjo45Ks2Py9ZZuHkGb+QIVpUz6ViB+JlUONKinIJF1p6g==",
"a10": "{}",
"x0": 1,
"a2": "06344bb7173b299dfeb9858d246c52aebbaf223f8e43fbc5662b54e2c66a54ea"
}
六、设备指纹分析
1. dfpid基本流程
0x001. java层调用fetchDfpId()获取dfpid
java层代码如下:
public boolean fetchDfpId(boolean arg13) {
Object[] v8 = new Object[]{((byte)(((byte)arg13)))};
ChangeQuickRedirect v10 = DFPManager.changeQuickRedirect;
if(PatchProxy.isSupport(v8, this, v10, false, "19489f6702cf81011acff69ff203e6a7", 0x4000000000000000L)) {
return ((Boolean)PatchProxy.accessDispatch(v8, this, v10, false, "19489f6702cf81011acff69ff203e6a7")).booleanValue();
}
try {
if(this.isOutDate()) {
label_49:
if(!this.postDFPID(this.encDfpDataForId())) { // 服务器获取
this.ensureLocalID(); // 读取本地ID
}
}
else {
if(arg13) {
goto label_49;
}
String v4 = this.idStore.getLocalDFPId();
if(!TextUtils.isEmpty(v4)) {
goto label_38;
}
if(!this.postDFPID(this.encDfpDataForId())) {
this.ensureLocalID();
return 1;
label_38:
this.idCallback.onSuccess(v4, ((long)DFPManager.ONE_HOUR) * ((long)this.idStore.getInterval()) + ((long)this.idStore.getLastUpdateTime()), "get dfp from local store");
long v7 = System.currentTimeMillis();
this.doPersistence(v4, this.idStore.getInterval().longValue(), v7);
return 1;
}
}
}
catch(Throwable unused_ex) {
}
return 1;
}
0x002. 调用encDfpDataForId()方法走到Native层获取请求体
java层代码如下:
public String encDfpDataForId() {
Object[] v8 = new Object[0];
ChangeQuickRedirect v9 = DFPManager.changeQuickRedirect;
if(PatchProxy.isSupport(v8, this, v9, false, "c899af894ac6d9a1a9df952ed8770d17", 0x4000000000000000L)) {
return (String)PatchProxy.accessDispatch(v8, this, v9, false, "c899af894ac6d9a1a9df952ed8770d17");
}
FamaCollector.hasCollected = true;
return NBridge.main1(41, new Object[0]); // 请求体
}
0x003. 调用postDFPID(String arg12)发送网络请求获取dfpid
java层代码如下:
//url: https://appsec-mobile.meituan.com/v5/sign
public boolean postDFPID(String arg12) {
Object[] v0 = new Object[]{null};
v0[0] = arg12;
ChangeQuickRedirect v9 = IDFPManager.changeQuickRedirect;
if(PatchProxy.isSupport(v0, this, v9, false, "f625ba5594fc8256be5f644877e817ae", 0x4000000000000000L)) {
return ((Boolean)PatchProxy.accessDispatch(v0, this, v9, false, "f625ba5594fc8256be5f644877e817ae")).booleanValue();
}
Interceptor v0_1 = this.getInterceptor();
String v1 = this.getMtgVersion();
DFPReporter v0_2 = new Builder().addInterceptor(v0_1).addResponseParser(new IResponseParser() {
public static ChangeQuickRedirect changeQuickRedirect;
@Override // com.meituan.android.common.dfingerprint.network.IResponseParser
public boolean onError(Call arg11, IOException arg12) {
Object[] v0 = new Object[]{arg11, arg12};
ChangeQuickRedirect v12 = com.meituan.android.common.dfingerprint.interfaces.IDFPManager.1.changeQuickRedirect;
if(PatchProxy.isSupport(v0, this, v12, false, "0231e3e90aba1d77b6009d4f4e808ce1", 0x4000000000000000L)) {
return ((Boolean)PatchProxy.accessDispatch(v0, this, v12, false, "0231e3e90aba1d77b6009d4f4e808ce1")).booleanValue();
}
Logger.logD("/v5/sign onError");
IDFPManager.this.ensureLocalID();
return 1;
}
@Override // com.meituan.android.common.dfingerprint.network.IResponseParser
public boolean onResponse(Response arg23, long arg24, int arg26) {
String v2_1;
long interval;
String dfpid;
ResponseBody body;
Object[] v11 = new Object[]{arg23, new Long(arg24), ((int)arg26)};
ChangeQuickRedirect v14 = com.meituan.android.common.dfingerprint.interfaces.IDFPManager.1.changeQuickRedirect;
if(PatchProxy.isSupport(v11, this, v14, false, "cfa6814ee923204fe513080ced241785", 0x4000000000000000L)) {
return ((Boolean)PatchProxy.accessDispatch(v11, this, v14, false, "cfa6814ee923204fe513080ced241785")).booleanValue();
}
Logger.logD("/v5/sign onResponse $response");
if(arg23 == null) {
return 0;
}
if(arg23.code() != 200) {
MTGlibInterface.raptorAPI("v5_/v5/sign", arg23.code(), arg26, 0, System.currentTimeMillis() - arg24);
return 0;
}
try {
body = arg23.body();
if(body == null) {
IDFPManager.this.idCallback.onFailed(-3, "request body is invalid");
return 0;
}
String v3 = new String(body.bytes());
MTGlibInterface.raptorAPI("v5_/v5/sign", arg23.code(), arg26, v3.length(), System.currentTimeMillis() - arg24);
Logger.logD("RaptorMonitorService >> ${RaptorUtil.API_reportdfpidsync}");
Logger.logD("RaptorMonitorService result>> ${result}");
if(v3.isEmpty()) {
IDFPManager.this.idCallback.onFailed(-3, "request body is invalid");
MTGlibInterface.raptorAPI("v5_/v5/sign", 9401, arg26, 0, System.currentTimeMillis() - arg24);
return 0;
}
Logger.logD("/v5/sign response.body() >> $result");
DFPResponse body_json = (DFPResponse)new Gson().fromJson(v3, DFPResponse.class);
if(body_json == null) {
goto label_145;
}
if(body_json.code == 0xFFFFFF80) {
goto label_145;
}
int v3_1 = body_json.code;
if(v3_1 != 0) {
IDFPManager.this.idCallback.onFailed(v3_1, body_json.message);
MTGlibInterface.raptorAPI("v5_/v5/sign", 9402, arg26, 0, System.currentTimeMillis() - arg24);
return 0;
}
dfpid = body_json.data.dataDfp;
interval = body_json.data.dataInterval;
v2_1 = body_json.message;
}
catch(Exception unused_ex) {
IDFPManager.this.ensureLocalID();
MTGlibInterface.raptorAPI("v5_/v5/sign", 9405, arg26, 0, System.currentTimeMillis() - arg24);
return 0;
}
try {
Logger.logD("/v5/sign response, dataDecrypt > $dataDecrypt");
}
catch(Exception unused_ex) {
}
try { // 如果等空读取本地的
if(dfpid == "") { // 如果等空读取本地的
IDFPManager.this.ensureLocalID();
}
else {
Logger.logD("/v5/sign 返回新的 local_dfp_id,需要保存它");
long currtime = System.currentTimeMillis();
if(DFPConfigs.isDfpidFirst) {
MTGlibInterface.raptorFakeAPI("v5_dfpid_duration", 200, System.currentTimeMillis() - MTGuard.sFirstLaunchTime);
DFPConfigs.isDfpidFirst = false;
}
IDFPManager.this.doPersistence(dfpid, interval, currtime); // 保存dfpid
IDFPManager.this.idCallback.onSuccess(dfpid, interval * ((long)IDFPManager.ONE_HOUR) + currtime, v2_1);
}
body.close();
return 1;
label_145:
IDFPManager.this.idCallback.onFailed(-4, "body parse failed");
}
catch(Exception unused_ex) {
IDFPManager.this.ensureLocalID();
MTGlibInterface.raptorAPI("v5_/v5/sign", 9405, arg26, 0, System.currentTimeMillis() - arg24);
}
return 0;
}
}).build();
try {
ReqeustBody v2 = new ReqeustBody(arg12, v1, null);
Gson v12 = new GsonBuilder().disableHtmlEscaping().create();
if(v12 != null) {
String v12_1 = v12.toJson(v2);
Logger.logD("postDFPID body > $body");
return v0_2.reportDFPIDSync(v12_1, ContentType.application_json); // 网络请求
}
}
catch(Exception unused_ex) {
}
return false;
}
1. dfpid请求体分析
0x001. 请求体调用Native层方法NBridge.main(41, new Object[0])在Native层计算得到循环获取设备信息:
.text:C8A8C684 09 98 LDR R0, [SP,#0x24]
.text:C8A8C686 61 F0 CD FF BL getmContext_sub_CC9EF624 ; 获取上下文件
.text:C8A8C68A 07 90 STR R0, [SP,#0x1C]
.text:C8A8C68C 00 F0 14 FE BL init_DecString_sub_C84582B8
.text:C8A8C690 06 90 STR R0, [SP,#0x18]
.text:C8A8C692 2B A8 ADD R0, SP, #0xAC
.text:C8A8C694 05 90 STR R0, [SP,#0x14]
.text:C8A8C696 09 99 LDR R1, [SP,#0x24]
.text:C8A8C698 07 9A LDR R2, [SP,#0x1C]
.text:C8A8C69A 2B 00 MOVS R3, R5
.text:C8A8C69C 26 F0 7A FC BL GetDeviceInfo_dispatch_loop_sub_C89F8F94 ; 获取设备信息1
.text:C8A8C6A0 06 98 LDR R0, [SP,#0x18]
.text:C8A8C6A2 29 00 MOVS R1, R5
.text:C8A8C6A4 05 9A LDR R2, [SP,#0x14]
.text:C8A8C6A6 23 F0 8D FF BL jmp_checkField_sub_C89F65C4 ; 判断获取的内容是否为特殊字符mtg_unsupport,mtg_block,setup_empty
.text:C8A8C6AA 2B 98 LDR R0, [SP,#0xAC]
.text:C8A8C6AC 04 99 LDR R1, [SP,#0x10]
.text:C8A8C6AE 40 18 ADDS R0, R0, R1
.text:C8A8C6B0 27 A9 ADD R1, SP, #0x9C
.text:C8A8C6B2 77 F0 49 F8 BL free_sub_B2943748
.text:C8A8C6B6 07 99 LDR R1, [SP,#0x1C]
.text:C8A8C6B8 00 29 CMP R1, #0
.text:C8A8C6BA 00 D1 BNE loc_C8A8C6BE
.text:C8A8C6BC 4C E7 B loc_C8A8C558
0x002. 在下面地方下好断点跳到获取设备信息的地方,可以绕过代码流程混淆,快速定位到想要获取设备信息的方法:
.text:C8AB5134 80 00 LSLS R0, R0, #2 ; 跳到真实执行方法
.text:C8AB5136 02 A1 ADR R1, loc_C8AB5140
.text:C8AB5138 08 58 LDR R0, [R1,R0] ; 取方法表偏移
.text:C8AB513A 08 18 ADDS R0, R1, R0
.text:C8AB513C 87 46 MOV PC, R0
0x003. 获取完设备信息后组合成json,主要获取硬件类ID、imei、mac,系统属性、CPU、内存、陀螺仪传感器等:
{
"m20": "3",
"m22": "0",
"m24": "-1",
"m25": "0",
"m26": "0",
"m27": "DAD703FB1B789AFCFA0CAD4778CF9C8D0146219F941D41B66617A73F",
"m28": "0",
"m29": "28.5",
"m30": "1",
"m31": "0",
"m32": "0",
"m33": "1",
"m34": "",
"m35": "0",
"m36": "0",
"m37": "0",
"m38": "1",
"m39": "Google",
"m40": "",
"m41": "",
"m42": "1",
"m43": "23132356608",
"m44": "1230796800000",
"m45": "1",
"m46": "",
"m47": "android",
"m48": "0",
"m49": "nonetwork",
"m50": "user",
"m51": "1",
"m52": "google",
"m53": "unknown",
"m54": "adb",
"m55": "{\"data\":[36.107063],\"name\":\"TMD4903LightSensor\",\"vendor\":\"AMS\"}",
"m56": "google/sailfish/sailfish:9/PQ2A.190305.002/5240760:user/release-keys",
"m57": "[{\"ssid\":\"2F16C2\",\"bssid\":\"cc:ee:07:2f:16:c2\"},{\"ssid\":\"2F16C2\",\"bssid\":\"cc:ee:07:2f:16:c2\"},{\"ssid\":\"JinRong\",\"bssid\":\"cc:e9:e4:84:cc:76\"}]",
"m58": "unknown",
"m59": "0",
"m60": "2283765760",
"m61": "[1,BMI160accelerometer,1,Bosch,156,2500,0,0,4,BMI160gyroscope,1,Bosch,17,2500,0,0,2,AK09915magnetometer,1,AKM,1300,20000,0,0,6,BMP285pressure,1,Bosch,1100,100000,0,0,65536,BMP285temperature,1,Bosch,85,40000,0,0,8,TMD4903ProximitySensor,1,AMS,5,200000,0,1,5,TMD4903LightSensor,1,AMS,43000,200000,0,10,3,Orientation,1,Google,360,5000,0,1,18,BMI160Stepdetector,1,Bosch,1,0,0,1,17,Significantmotion,1,Google,1,-1,0,1,9,Gravity,1,Google,1000,5000,0,1,10,LinearAcceleration,1,Google,1000,5000,0,1,11,RotationVector,1,Google,1000,5000,0,1,20,GeomagneticRotationVector,1,Google,1000,5000,0,1,15,GameRotationVector,1,Google,1000,5000,0,1,25,PickupGesture,1,Google,1,-1,0,1,22,TiltDetector,1,Google,1,0,0,1,19,BMI160Stepcounter,1,Bosch,1,0,0,1,14,AK09915magnetometer(uncalibrated),1,AKM,1300,20000,0,0,16,BMI160gyroscope(uncalibrated),1,Bosch,17,2500,0,0,65537,SensorsSync,1,Google,1,0,0,1,65538,DoubleTwist,1,Google,1,0,0,1,65539,DoubleTap,1,Google,1,0,0,1,27,DeviceOrientation,1,Google,3,0,0,1,65540,DoubleTouch,1,Google,1,-1,0,1,35,BMI160accelerometer(uncalibrated),1,Bosch,156,2500,0,0,32,DynamicSensorManager,1,Google,1,1000,0,1]",
"m62": "1",
"m63": "0",
"m64": "1",
"m65": "1",
"m66": "Bosch",
"m67": "unknown",
"m68": "",
"m69": "352531086839980",
"m70": "sailfish",
"m71": "Gravity",
"m72": "1",
"m73": "com.qihoo.appstore-bin.mt.plus-cn.tongdun.sdkdemo-com.arcsoft.arcfacedemo-com.baidu.idl.face.demo-com.bjgas.shop-com.duapps.gif.emoji.gifmaker-com.mv.livebodyexample-com.sankuai.meituan-com.songheng.wubiime",
"m74": "FA7740302912",
"m75": "unknown",
"m76": "QualcommRIL1.0",
"m77": "BMI160accelerometer",
"m78": "com.android.chrome-com.android.settings-com.android.vending-com.google.android.GoogleCamera-com.google.android.apps.docs-com.google.android.apps.maps-com.google.android.apps.messaging-com.google.android.apps.photos-com.google.android.calendar-com.google.android.contacts",
"m79": "midi,adb",
"m80": "",
"m81": "8996-130181-1811270246",
"m82": "32",
"m83": "PQ2A.190305.002",
"m84": "midi,adb",
"m85": "",
"m86": "PQ2A.190305.002",
"m87": "lac:40980,cid:3909155,rssi:22|lac:-1,cid:-1,rssi:20",
"m88": "cn",
"m89": "release-keys",
"m90": "1",
"m91": "unknown",
"m92": "",
"m93": "{\"hashInfo\":[],\"number\":0}",
"m94": "sailfish",
"m95": "1",
"m96": "8996-012001-1812132253",
"m97": "",
"m98": "Google",
"m99": "",
"m100": "0",
"m101": "CN",
"m102": "1",
"m103": "26109874176",
"m104": "1593600",
"m105": "420",
"m106": "0",
"m107": "ac:37:43:df:02:7e",
"m108": "android-build",
"m111": "37cb81453cec878d",
"m112": "unknown",
"m116": "wlan0",
"m117": "1631706064788",
"m122": "AA==\n",
"m123": "",
"m125": "",
"m126": "Dalvik/2.1.0(Linux;U;Android9;PixelBuild/PQ2A.190305.002)",
"m127": "0.0000000000|0.0000000000",
"m128": "unknown",
"m129": "",
"m130": "",
"m131": "23132299264",
"m132": "26109874176",
"m133": "",
"m134": "bus",
"m135": "0.000000",
"m136": "",
"m137": "3.18.122-g665c9a1",
"m138": "[2,95]",
"m139": "4",
"m140": "arm64-v8a,armeabi-v7a,armeabi",
"m141": "0",
"m142": "0.16470589",
"m143": "0",
"m144": "11.12.204",
"m145": "mtguard",
"m146": "1",
"m147": "sailfish",
"m148": "1631706140783",
"m149": "1631706064",
"m150": "1631754658276",
"m151": "unknown",
"m152": "5.1.7",
"m153": "",
"m154": "com.sankuai.meituan",
"m155": "1629207179980",
"m156": "",
"m157": "3948302336",
"m158": "sailfish",
"m159": "abfarm722",
"m160": "9",
"m161": "0",
"m162": "unknown",
"m163": "0",
"m164": "zh",
"m165": "[GMT+08:00,Asia/Shanghai]",
"m166": "Pixel",
"m167": "1080*1794",
"m253": "",
"m254": "",
"m255": "0",
"m256": "",
"m293": "DAD7A2870A2DAAA2F67190B216A34A886A9E219F941D662641A653D9",
"m241": "",
"m242": "",
"m245": "{\"libc.so:\":\"E5592D3E966419A89DEF46F6BE029015\",\"libandroid.so:\":\"\",\"libandroid_runtime.so:\":\"2F4ADAB748DE1F97EACAC55B9584E504\",\"libandroid_servers.so:\":\"75AF8941A0B6C9A841C05442FE32CCFC\",\"framework.jar:\":\"\",\"services.jar:\":\"\",\"core.jar:\":\"\"}",
"m246": "ae:37:43:df:02:7e",
"m247": "35253108683998",
"m289": "352531086839980",
"m290": "352531086839980",
"m294": "{\"1\":\"\",\"2\":\"1|2|3\",\"3\":\"\",\"4\":\"\",\"5\":\"\",\"6\":\"\",\"7\":\"2\",\"8\":\"\",\"9\":\"\",\"10\":\"\",\"11\":\"\",\"12\":\"32\",\"13\":\"\",\"14\":\"\",\"15\":\"\",\"33\":{\"0\":2,\"1\":\"\",\"2\":\"\",\"3\":\"\",\"4\":\"2|22\",\"5\":\"\",\"6\":\"\",\"7\":\"\",\"8\":\"\",\"9\":\"\",\"10\":\"\",\"11\":\"\",\"12\":\"\",\"13\":\"\",\"14\":\"2\",\"15\":\"\"}}",
"m304": "-1",
"m305": "1080*1920",
"m217": "1631706064788185",
"m243": "-1",
"m244": "{\"DCIM\":\"00045F6737E705C00001C3B7F33CF3000005C810802CB9C0000083D1C295CA000005C810802CB9C0000083D1C295CA00\",\"Android\":\"00045F6737F648000002A40F89B18AC00005C5CB1C563D000000EE4ABA3499C00005C5CB1C563D000000EE4ABA3499C0\",\"misc\":\"0005BA6437AAF540000037EFB50958800005BDC662F5BF40000263501EE0BE000005BDC662F5BF40000263501EE0BE00\",\"settings\":\"00045F67360E000000005AF31103944000045F67360E000000005AF31103944000045F67360E000000005AF311039440\",\"saver\":\"0005BA6437AAF54000005F590941430000045F67377C360000014D7BCD19158000045F67377C360000014D7BCD191580\",\"mtp\":\"0005BA6437AAF5400000CC7CB757DE0000045F67360E00000001EB208F56774000045F67360E00000001EB208F567740\",\"calendar\":\"0005BA6437AAF54000008CD291CAAE4000045F6738AD630000019F5706658BC000045F6738AD630000019F5706658BC0\",\"media\":\"0005BA6437AAF5400000B7440023B8000000225E8BD0FF0000037B4E60CF5D000000225E8BD0FF0000037E567AF07C40\",\"misc_ce\":\"0005BA6437AAF540000062612371A48000045F6737D7C38000010AC9B10045C000057E646876D18000027F601A1B3540\",\"rollback\":\"\",\"system\":\"0005BA6437AAF54000005C50EF10E1800005CC17296EE1C0000373A4714044800005CC17296EE1C0000373A471404480\",\"data\":\"0005BA6437AAF5400000687157C325400005CC0732B344C000001BE686FAA0400005CC0732B344C000001BE686FAA040\",\"install_sessions\":\"0005BA6437AAF54000005F59094143000000225E8BD0FF00000329739E3E68C00000225E8BD0FF00000329739E3E68C0\",\"webview\":\"0005BA6437AAF54000008CD291CAAE4000045F6737C88140000104B976B8E40000045F6737C88140000107C190DA0340\"}",
"m248": "",
"m307": "{\"m34\":5,\"m40\":5,\"m41\":5,\"m46\":5,\"m58\":2,\"m67\":6,\"m68\":5,\"m75\":6,\"m80\":5,\"m85\":5,\"m91\":2,\"m92\":5,\"m97\":5,\"m99\":5,\"m112\":3,\"m123\":5,\"m125\":5,\"m128\":6,\"m129\":5,\"m130\":5,\"m133\":5,\"m136\":5,\"m151\":2,\"m153\":5,\"m156\":5,\"m162\":6,\"m253\":5,\"m254\":7,\"m256\":7,\"m241\":7,\"m242\":5,\"m248\":5}"
}
0x004. 加密设备数据,解密PIC数据获取AES KEY, 解密后数据:
{"a1":0,"a10":400,"a2":"com.sankuai.meituan","a11":"c1ee9178c95d9ec75f0f076a374df94a032d54c8576298d4f75e653de3705449","a3":"0a16ecd60eb56a6a3349f66cdcf7f7bf5190e5a42d6280d8dc0ee3be228398ec","a4":1100030200,"k0":{"k1":"meituan1sankuai0","k2":"meituan0sankuai1","k3":"$MXMYBS@HelloPay","k4":"Maoyan010iauknaS","k5":"34281a9dw2i701d4","k6":"X%rj@KiuU+|xY}?f"},"a5":"11.3.200","a0":"pw/LhTdeoTTyaxPHcHMy+/ssGNS1ihNkrJ+uBI74FIfd90KlTil1m0i7FF/n0bhY","a6":"/HntC9XIfdUyII/UiVfx020EQPpHz2XZY3qzM2aiNmM0i0pB1yeSO689TY9SBB3s","a7":"QsHnU6kFjTYR8Z6tHEvkGMO2Hrt+NRnVQhmxg6EtVBzuzQcBpma3AdhTWNMpesFT","c0":{"c1":true,"c2":false},"a9":"SDEzWXi5LHL/cuMCZ1zYyv+0hIViqWWf+ShbUYILWf4=","a8":1603800117167}
0x005. 解析json得到 aes key:meituan1sankuai0AES加密设备json数据(IV 0102030405060708):
.text:C8AA94EE 06 98 LDR R0, [SP,#0x120+byte_count] ; byte_count
.text:C8AA94F0 E0 F7 FA EB BLX malloc ; 存放加密后数据
.text:C8AA94F4 00 26 MOVS R6, #0
.text:C8AA94F6 00 28 CMP R0, #0
.text:C8AA94F8 1C D0 BEQ loc_C8AA9534
.text:C8AA94FA 4A 99 LDR R1, [SP,#0x120+arg_0]
.text:C8AA94FC 03 91 STR R1, [SP,#0x120+var_114]
.text:C8AA94FE 07 AE ADD R6, SP, #0x120+var_104
.text:C8AA9500 F4 21 MOVS R1, #0xF4
.text:C8AA9502 02 90 STR R0, [SP,#0x120+var_118]
.text:C8AA9504 30 00 MOVS R0, R6
.text:C8AA9506 E0 F7 08 EC BLX __aeabi_memclr4
.text:C8AA950A 80 21 MOVS R1, #0x80
.text:C8AA950C 20 00 MOVS R0, R4
.text:C8AA950E 32 00 MOVS R2, R6
.text:C8AA9510 56 F0 30 FF BL AES_set_Encrypt_key_sub_CB601374 ; R0:key,R1:长度,R2:返回值
.text:C8AA9514 06 9A LDR R2, [SP,#0x120+byte_count]
.text:C8AA9516 01 20 MOVS R0, #1
.text:C8AA9518 69 46 MOV R1, SP
.text:C8AA951A 04 9B LDR R3, [SP,#0x120+var_110]
.text:C8AA951C 0B 60 STR R3, [R1,#0x120+var_120]
.text:C8AA951E 48 60 STR R0, [R1,#0x120+var_11C]
.text:C8AA9520 05 98 LDR R0, [SP,#0x120+p]
.text:C8AA9522 02 9C LDR R4, [SP,#0x120+var_118]
.text:C8AA9524 21 00 MOVS R1, R4
.text:C8AA9526 33 00 MOVS R3, R6
.text:C8AA9528 57 F0 7A FD BL AES_cbc_Encrypt_sub_CB602020 ; R0:原始数据,R1:返回,R2:大小,R3:key
.text:C8AA952C 06 98 LDR R0, [SP,#0x120+byte_count]
.text:C8AA952E 03 99 LDR R1, [SP,#0x120+var_114]
.text:C8AA9530 08 60 STR R0, [R1]
.text:C8AA9532 26 00 MOVS R6, R4
.text:C8AA9534
.text:C8AA9534 loc_C8AA9534 ; CODE XREF: Aes_sub_CB5AA4B8+40↑j
.text:C8AA9534 05 98 LDR R0, [SP,#0x120+p] ; p
.text:C8AA9536 E0 F7 DE EB BLX free
0x006. 加密后数据(部分):
C6A47000 6C 96 CF 82 B2 88 06 39 8D 37 E9 1C D3 D7 DF A1 l.ς ...9.7......
C6A47010 A1 D7 C5 C7 A2 1F 21 47 F4 8D F8 E3 59 55 68 87 ...Ǣ .!G....YUh.
C6A47020 13 D2 C7 A5 AD 47 51 04 64 B2 86 3A 86 AA 47 36 .....GQ.d..:..G6
C6A47030 8A 26 F7 03 A0 42 3F 4E B7 43 53 F5 E8 DE 9A 48 .&....?N.CS....H
C6A47040 FF 7D CC D3 30 91 1C 59 34 6C 3C D5 A4 45 AD 8A .}..0..Y4l<դ E..
C6A47050 69 06 49 EA 1B B5 95 7F 40 3F AF BE DB 18 CB CD i.I.....@?......
C6A47060 85 A9 05 0E 02 43 1C 10 2C 50 53 9F A0 A1 6D 14 .....C..,PS...m.
C6A47070 DF F9 23 99 64 3C E4 D8 7C 56 58 C0 35 E6 81 34 ..#.d<...VX.....
C6A47080 9B 9C 6D A3 92 5B 36 50 6E 85 79 6E 2A 6C EB BF ..m..[6Pn.yn*l..
C6A47090 59 F5 77 F3 C3 F8 3D 47 04 D4 55 FB C1 D6 8D 3A Y.....=G.......:
C6A470A0 0F 4D EF 9E A2 C0 DF 93 58 B5 E1 79 22 EE 6A 65 .M ...X.......
C6A470B0 A4 A8 47 7F 68 BA C1 C7 19 96 8A 9E 29 90 48 07 ..G.h.......).H.
0x007. base64加密(部分):
bJbPgrKIBjmNN+kc09ffoaHXxceiHyFH9I3441lVaIcT0selrUdRBGSyhjqGqkc2iib3A6BCP063Q1P16N6aSP99zNMwkRxZNGw81aRFrYppBknqG7WVf0A/r77bGMvNhakFDgJDHBAsUFOfoKFtFN/5I5lkPOTYfFZYwDXmgTSbnG2jkls2UG6FeW4qbOu/WfV388P4PUcE1FX7wdaNOg9N756iwN+TWLXheSLuamWkqEd/aLrBxxmWip4pkEgHlLK14AbB68tlUvIauN50i/KZVCun9lA13FmhY9t4JiZYMuQUiluXGtFLoVLUb3ybe9Uy156k8NFn8sZkCzx5I1nUFKEx2Mgb6Q+SDXY1r4TCh6jYCYd/Dfr+n1ccN+Z7M8oceexb3KD+yapCYKvhj2sm5/WptX+ncnTTalrLG8U53YZAJtwQ2NTZ/yuVJWNpnEjRE3EI
0x008. 返回java层组合请求体,计算请求头签名发送给服务器获取dfpid 请求体格式:
{"data":"Native加密的设备数据","dfpVersion":"5.1.7","mtgVersion":"5.1.7","os":"Android","time":"2021-09-01 11:35:35"}
0x009. 计算的请求头签名:
{"a0":"2.0","a1":"9b69f861-e054-4bc4-9daf-d36ae205ed3e","a3":2,"a4":1631778284,"a5":"A18ywLdCS48BnwSLKup0wrjB+dsq4S6V+9BZPtgOWyf76KKpdYv8xejvBBC8HE6C4uRAl79/X7icd48pdktGG8B0+yAbMGtUl5Ri2kQc4/RgxjDiN64MjMvus7Aok+9LqzRZW1W9Qj2yJoMyK7h57/+amTSLDqyUzbat6zAgCAdeZ/vbKk+34+NVNwoz7fMLqvRlGbTVLZddTFIQvzbs1rNC3eV7mH9ORw==","a6":0,"a7":"lpArUzLcl+lgZ9YXlGR9nPVqJMM2UvrBYyFRM2UsDIidftxLwpEOzzcZ7NPmHxahYSpXrJr/eHv4y2FmjsLwnykKopieCU4Prh4FskqVsRg=","a8":"DAD796C46B5A6525F4B89DF661A97C7A218A219FC24B93F689DEBD92","a9":"97a62b63j1IexpGhrGBYdWqnstTXCpGUZncRa5MAcc5LtAO65uXQ/gPQuhqUcACAU5Cstbgs/wxZr8oFrMNqpSDo+Lt3QT7CenBY9BUnVn6bSHYNAaPhQ3WxYc1fpRi3+Lfpqz6/6CtwzNM113yKUoIgwMQZ2TTkRJ5S7JI0PztFc8u2I5ngz2thHx3rIXDjNXhmxoo7xH9rULUa65Y1zdPRx2xVNGDUJDFX78jvL39wIkvvnqBMK54GyQ8F8Vd/+lyPg1Wi3GoVUyFKrfw5RRDTElNyby2CvgQVKFRwHYbJu8OS3TjT6sW4uqmNxZQl4Zg4DBg/C6vlXAZISTCiCzC5yQ/xfqrQ5hNmKmsfHiVMduB7XYh9INAqceiTRlPV/ccY/JeGPRTbo52FoIHEponCLaToMU08uJVYC+hvT21OB/Wae2dr1l0vF4zDP+109YHgf7HbHg40TJW+UfIJdkAR0XHDINEqZIPmgE7jgon2B9KMXSyrWTg3OvOVA2USc7lBX9/8s1AXyI6MYgb7JwddM/cajZJle9ipMzJTmSZbJPw8o3bHGlt2pTtXzJb7mLgOxS1cwoc2kUTQYkRz5irPM1bhY4dT33d0tOr6C8IjROMgQMuIsVxKYCt88qo8ESk/nZEpVcWvBlsM+HWSwjHKtOJ8iPl3EqwSQiWRjVN6bOQyQIsPNVTfkZHSBqKnJ4dXcjXMTqcxGgxEzfD5sLfzXDz71A==","a10":"{}","x0":1,"a2":"0f4513356e64a6d70d962a764b1d68b8"}
0x010. 发送给服务器后成功返回dfpid:
{"code":0,"data":{"serverTimestamp":0,"clientIp":"218.xx.xx.xx","interval":24,"dfp":"8ecde1544fbe09ba3ec851e72fdd28c0803df1f83c5c0862c8ad571c"},"message":"ok"}
以上就是完整的dfpid设备指纹生成过程,xid生成也是类似的,也是在Native层获取设备信息加密返回到java层组合请求体,计算请求头签名,发送给服务器计算ID返回ID的过程,我就不再重复分析了。
七、设备指纹攻击
1. 设备指纹原理
0x001. 设备指纹是用来标识手机设备的唯一ID,能够通过这个ID关联到手机相关的全部数据,因此设备指纹是风控中最核心的数据之一,所以它需要具备以下几个条件时ID不变:设备重置、设备更新、设备刷机。要同时具备这样的条件,必须从多个维度采集不同的信息来生成ID,这些信息可以大致分为:软件ID、软件静态特征、硬件静态特征和硬件动态特征。采集完信息后如何基于这些信息计算出一个稳定的设备指纹ID,还是有比较大挑战,再加上目前国家对公民隐私保护严格,用户敏感信息不能采集,很多唯一性比较好的数据就失效,要做一稳定性高的ID就难上加难了。
2. 设备指纹变与不变
0x002. 既然设备指纹ID是根据手机设备的数据生成的,哪么我们的攻击思路就是修改设备信息,同一台手机不断变化设备信息让生成设备指纹的服务返回新的ID就算攻击成功了,因为它无法识别手机的唯一性。
实战修改设备字段生成新的dfpid
测试过程就是在内存中将采集的某设备字段改掉就可以生成新的设备ID(该字段是软件相关的ID,比较敏感就不说了,总共没有多少字段,想玩的朋友可以自己调试测试)八、黑产工具特征检测
1. 解密黑产工具特征
0x001. 获取密钥,解密PIC数据获取key(a9)
.text:C8571594 20 00 MOVS R0, R4
.text:C8571596 32 00 MOVS R2, R6
.text:C8571598 57 F0 7A F8 BL AES_set_decrypt_key_sub_CB601690 ; R0:key,R1:大小,R2:初始AES_KEY返回结构
.text:C857159C 00 20 MOVS R0, #0
.text:C857159E 69 46 MOV R1, SP
.text:C85715A0 06 9A LDR R2, [SP,#0x128+var_110]
.text:C85715A2 0A 60 STR R2, [R1,#0x128+var_128]
.text:C85715A4 48 60 STR R0, [R1,#0x128+var_124]
.text:C85715A6 08 98 LDR R0, [SP,#0x128+var_108]
.text:C85715A8 04 9E LDR R6, [SP,#0x128+var_118]
.text:C85715AA 31 00 MOVS R1, R6
.text:C85715AC 07 9C LDR R4, [SP,#0x128+var_10C]
.text:C85715AE 22 00 MOVS R2, R4
.text:C85715B0 03 9B LDR R3, [SP,#0x128+var_11C]
.text:C85715B2 57 F0 35 FD BL AES_cbc_Encrypt_sub_CB602020
.text:C85715B6 30 00 MOVS R0, R6
0x002. 解密后特征
{
"0": 2,
"1": "",
"2": ["/sys/devices/virtual/misc/qemu_pipe", "/sys/module/vboxsf", "/system/droid4x", "/system/bin/droid4x-vbox-sf", "/system/lib/egl/libEGL_tiDetectanVM.so", "/system/bin/ttVM-vbox-sf", "/system/lib/libnox.so", "/system/bin/nox-vbox-sf", "/system/bin/androVM-vbox-sf", "/ueventd.vbox86.rc", "/sys/class/misc/qemu_pipe", "/sys/qemu_trace", "/dev/com.bluestacks.superuser.daemon", "/system/framework/libqemu_wl.txt", "/system/lib/libc_malloc_debug_qemu.so-arm", "/data/downloads/qemu_list.txt", "/system/bin/yiwan-prop", "/system/bin/yiwan-sf", "/system/bin/qemu_props", "/system/bin/androVM-prop", "/system/bin/microvirt-prop", "/system/lib/libdroid4x.so", "/system/bin/windroyed", "/system/bin/microvirtd", "/system/bin/nox-prop", "/system/bin/ttVM-prop", "/dev/qemu_pipe", "/vendor/bin/qemu-props", "/system/bin/droid4x-prop", "/data/.bluestacks.prop", "/system/app/com.mumu.launcher", "/system/lib/vboxguest.ko", "/system/lib/vboxsf.ko", "/sys/class/misc/vboxguest", "/sys/class/misc/vboxuser"],
"3": ["de.robv.android.xposed.installer", "com.saurik.substrate", "com.soft.apk008v", "com.soft.apk008Tool", "com.mockgps.outside.ui", "com.tim.apps.mockgps", "com.huichongzi.locationmocke", "com.lxzs"],
"4": ["XposedBridge.jar", "frida", "substrate", "libriru_edxp.so", "libsandhook.edxp.so", "libwhale.edxp.so", "libxposed_art.so", "edxp.jar", "fasthook", "libfakeloc_initzygote.so", "qssq666", "com.lxzs", "sandhook", "libsubstrate.so", "libiohook.so", "libepic.so", "libepic64.so", "libexp824.so", "libexp82464.so", "libexposed.so", "cydia", "/data/local/tmp"],
"5": "",
"6": ["de.robv.android.xposed.XposedBridge", "de.robv.android.xposed.XposedHelpers"],
"7": ["/system/lib/lic", "/system/lib/ccc", "/system/lib/.aa"],
"8": ["de.robv.android.xposed.XposedBridge", "xposed", "com.lxzs"],
"9": ["dexguard_DGResourcesSuperClass.dex"],
"10": ["VirtualBox"],
"11": ["com.gsxz.location", "net.anylocation", "com.huichongzi.locationmocker", "top.a1024bytes.mockloc.ca.pro", "com.deniu.daniu"],
"12": ["fridaserver", "magisk", "xposed"],
"13": "",
"14": ["charles", "fiddler"],
"15": ["com.netease.nemu_vinput.nemu"]
}
0x003. 解析json检测特征
//直接调用SVC指令,检测特征是否存在系统中。
.text:C8571444 faccessat_sub_C8BE5444
.text:C8571444
.text:C8571444 F0 B5 PUSH {R4-R7,LR}
.text:C8571446 03 AF ADD R7, SP, #0xC
.text:C8571448 0B 00 MOVS R3, R1
.text:C857144A 04 00 MOVS R4, R0
.text:C857144C 63 20 MOVS R0, #0x63 ; 'c'
.text:C857144E C5 43 MVNS R5, R0
.text:C8571450 A7 20 MOVS R0, #0xA7
.text:C8571452 46 00 LSLS R6, R0, #1
.text:C8571454 28 46 MOV R0, R5
.text:C8571456 21 46 MOV R1, R4
.text:C8571458 1A 46 MOV R2, R3
.text:C857145A 37 46 MOV R7, R6
.text:C857145C 00 DF SVC 0
.text:C857145E 03 46 MOV R3, R0
.text:C8571460 18 00 MOVS R0, R3
.text:C8571462 F0 BD POP {R4-R7,PC}
九、总结
1. 安全点
0x001. 代码混淆,代码块间跳转动态计算获取,单步调试容易跑飞、流程混淆无法F5,字符串加密。采集设备信息都在Native层反射来获取,
2. 不足点
0x001. 指纹稳定性比较差,在华为的机型上基本不行,防hook只是简单做了前几个字节判断,检测黑产工具的特征写死的。
原文下载
友情提示:本文只为技术分享交流,请勿非法用途.产生一切法律问题与本人无关.
unidbgWebServer项目地址(unidbg封装app加密服务不依赖移动端) Git公开仓库地址 欢迎 start or fork 或贡献代码.
在浏览的同时希望给予作者打赏,来支持作者的服务器维护费用.一分也是爱~