书接上文:
一、反爬虫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层从服务器端获取.
0x009.获取到的dfpid
DAD796C46B5A6525F4B89DF661A97C7A218A219FC24B93F689DEBD92
0x010.获取xid (设备指纹)判断本地是否有存储,如果有优先读取本地,如果无反谢java层从服务器端获取,APP第一次运行进就用UUID与时间加密生成一个.
0x011.获取到的xid
Rs8NOy0BFS5JQxfdOoIxpMnKV3iqYWcblAjp0vpnWZyNzyF9rfsi3ekpm4ScaIZgeImizX/5AbS3e838Or4el4+PPPI2kD8XW+8vbvjDBSM=
0x012.组合json(每一个字段的解释,a0:版本,a1:appkey, a3:版本,a4:时间,a5:加密的设备环境,a6:固定数字,a7:xid,a8:dfpid,a9:初始化时加密的设备环境信息(前8字符中CRC:f4ec12ef)):
- 计算请求体签名值
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),解密流程与初始化时一样
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. 将异或后的值与请求体组合:
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. 解密PIC数据获取KEY(a9) 解析json获取a3:0a16ecd60eb56a6a3349f66cdcf7f7bf5190e5a42d6280d8dc0ee3be228398ec a3为AES KEY解密a9解密后数据
0x013. AES加密Body计算得到的MD5值
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"
}