-
-
[原创]某车联网APPx梆加固 浅浅分析
-
2022-8-10 18:05
61117
-
0x1 分析前准备
目标App:比亚迪汽车 6.1.0
工具:Cydia、Frida、Objection、Storm Sniffer(抓包)
0x2 抓包
首先打开Storm Sniffer,该AppStore可下载。(使用fiddler也可以)
目标App开启了SSLPinning,导致无法抓包。
通过objection绕过SSLPinning
1 2 | objection - g 比亚迪汽车 explore
ios sslpinning disable - - quiet
|
接下来可以看到抓包内容了
软件提示:账号密码错误
1 2 3 4 5 6 7 8 | https: / / dilinkappserver.byd.com / app / auth / login
User - Agent: bi ya di qi che / 6.0 . 1 (iPhone; iOS 14.0 ; Scale / 3.00 )
Content - Type : application / json
Host: dilinkappserver.byd.com
{ "request" : "FESWLgT0LjY\/GjPQmt4xYvDWajog909VYoUcLQ8TE7E\/F4U9GwHtbmfY9uZbmqPnGW2ys0NRnezIjTETA64wpvfP3aZV+caLdK8fsLovfxoacBp5hIkvlS4hTEYkl8XfIfashQDMOdYmm8W89ZBwpFF+Ipd9hFy7NGHDom4SgXQ5uE7Io8jFnoGiz5CiQ9B3K0NbCSOkSbbwJi14iFi15sy3car\/W3xMNUZuo7\/vNE7Dz\/eHwxroJ7L+DK\/6yXbNLRHMHRtXJykfnD31ShNTEqzkF+Fp2Z6jUuFFpn4B7SB4uJYWe5cJ9g3gDIOEifHEhhD3LCQfOEKppgisduO8el4rEGFaKPx1bzOAIk0W1qPXk0LbVCFPQYFpypUB8Rrn2hBBsA8cepRBBtH73jeRcvrRMBc0gK+YRw4uq8yd44bNoEpSt1L5YOJBelSxmp9WOhkGOjt5cPCHij1ptaO9gp1d7XAg4+MhpzXoluB8aPi8A28stX04l+HdU6lNU0pUGYtFVRbTvYV4KjseXQ5wlRavwFMgv3c61WUMznyLmtI8zdheCVdr3vGG1nNvGI7cqMHdw8jvdYFCe9jr3eu1nG2uHakh7PHDMyEDpEh7WSJvVod+0sleiS+vhv5xnNhXUOtBtjCUcLSZToY6YJky9O4E8WDOGg2j5kvCaHrY\/bgSGd87O7sCkmrjeYEJj5BSV95tlI2Ky1GlTRvG4jLQ800QuXAJyXQJpf9uO5lbmV2yPJ7OcKbRoaRu7rhMj4yok9dPEY5bIJeMFptv+bBTKgRh18R5ZecUdpyx8PrVY7FvTEihzH9z+ACGIMNgw7MZIVRPBqLh\/zXK1JfY3pPblvLVhmbeWQ6ETTC2eEWDmAcBovF+Mpj\/M2ybwRdFGLATHZJUQCobYS+02Jxfd0\/ODHpOQ7c2RJwZh6aijIEeh3Ohj1weh\/ZNAK7189yi3n810Bne0ld\/Vo11Jk7hSSQ9z1vCZijCzbDb4Yuw+jsnM\/CPS0OBMMQqIsuz9TPJ\/89SP103sVv01AOXWUM0OB97POJpQ8Bnfjusf8x7CKURlyj4hl6NHksSAGeOmPv96B\/X\/xEARr3Lq7K0RnVFjqFJUsXVVJavggfrhexl7xgvU7MqOPZ24ZiMmOTKTKP+WVsykcraeoP9+yuYkhdMLPEBelpnkoHOuHvpqojhOcJvN8pu\/tRclZO6KGuRD8I7M3J2+mMo8ZTNQUB7oYVR\/UfIKJ5+aIybJklZ1HTb5nV\/D1tDgWRN5JDvndJ78cEi6s8Hi9gsZjglN1JNaQ3vShP7RuLSYdRqDO7e27cSkibTH4YW6PsHPHhqX2g4ev8WTEbRIAsiVJTOuJqNaPaoX3oDMviBz5aZ0iu6XwRwbojibWBCOABktvzVNgngxxeyPmyJlVQ5H5ehn\/iNNZC4RRz0FqhetTfWdQWXnRqicq+tiujO478mQQVKTDKvhi6y0uL2g2SuR81QJ0YmhlCFxqFWX2ACpro\/4HM5J0EdJvboVwrR70CEBa6pqwsvCSCQCltwM+EDH+OYxt34oL1ngY7+fsm1oZcyEvn3\/snVZcd97klBzdl5oCyj3ANtoDIQua35u2ENXbPc8CqIIlcbPVsmF5U1ESRs5khYlDjBH6qvpZBoA4a36pgMZVu8XKpk7c+bOIB0WrZcMSaIF+r2x0Jg8ZKjrZ\/AwhoRDHAtEIQNDLNkPDvjoEcoI0CF3\/p\/AVyjko9aqtatyNZE7i0MQ4SUdamyogd428NFygGgq5JtoSe3XXL\/3hWxlbTGqESnPXKjh7jTG5FQxy6grBp7lVN2DSW2yNkvVOrtVaRjIbTzJd7\/oiUE29Yx1l\/1tPpJTq0CDSa2sTGgYHyPkppcoA3OXLiEGuQC0lKuvuahyAh956uueAi7DvMUWzPemfszzr6Bd35RucQE5tFjzQ19QIIDGhxLHMfweQHO2jEUuTddqRbnO3ZVyM8jZpcNBwMKbuqjk" }
{ "response" : "Fel63A3fJsBnqDNoqrf3sNRYntlgl2bMzWrA56aEQZRggnMBao9z1ds1G/TqV2TMwrRu1wovdv5AwWkDlpdqO0A==" }
|
0x3 砸壳
使用 frida-ios-dump进行砸壳dump出ipa文件,找到包内二进制文件,拖入IDA中分析。
0x4 加密点
4.1 思路: Frida hook -[NSURLRequest initWithURL:] 打印其调用堆栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | try {
var className = "NSURLRequest" ;
var funcName = "- initWithURL:" ;
var hook = eval ( 'ObjC.classes.' + className + '["' + funcName + '"]' );
Interceptor.attach(hook.implementation, {
onEnter: function(args) {
console.log(colors.green, "NSURLRequest with URL: " ,colors.resetColor + ObjC. Object (args[ 2 ]));
console.log( "\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE)
. map (DebugSymbol.fromAddress).join( "\n" ));
},
});
} catch (error) {
console.log(colors.red, "[!] Exception: " ,colors.resetColor + error.message);
}
|
输出如下:
1 2 3 4 5 6 7 8 9 10 | [iPhone::比亚迪汽车 ] - > NSURLRequest with URL: https: / / dilinkappserver.byd.com / app / auth / login
Backtrace:
0x1057d943c / private / var / containers / Bundle / Application / 48133A5D - 90E1 - 494C - 8472 - 79C2B5DE912B / 比亚迪汽车.app / 比亚迪汽车! - [AFHTTPRequestSerializer requestWithMethod:URLString:parameters:error:]
0x1057d106c / private / var / containers / Bundle / Application / 48133A5D - 90E1 - 494C - 8472 - 79C2B5DE912B / 比亚迪汽车.app / 比亚迪汽车! - [AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure:]
0x1057d0780 / private / var / containers / Bundle / Application / 48133A5D - 90E1 - 494C - 8472 - 79C2B5DE912B / 比亚迪汽车.app / 比亚迪汽车! - [AFHTTPSessionManager POST:parameters:headers:progress:success:failure:]
0x1049e1e24 / private / var / containers / Bundle / Application / 48133A5D - 90E1 - 494C - 8472 - 79C2B5DE912B / 比亚迪汽车.app / 比亚迪汽车! + [AFNRequestUtls postRequestWithInfo:successBlock:failedBlock:]
0x104b4d270 / private / var / containers / Bundle / Application / 48133A5D - 90E1 - 494C - 8472 - 79C2B5DE912B / 比亚迪汽车.app / 比亚迪汽车! + [BYDHttpsRequestUtils httpsPostRequestWithRequestRequestInfo:successBlock:failedBlock:]
0x1048f48fc / private / var / containers / Bundle / Application / 48133A5D - 90E1 - 494C - 8472 - 79C2B5DE912B / 比亚迪汽车.app / 比亚迪汽车! - [BYDUserModel doLoginSuccess:failed:]
0x104a4c4f8 / private / var / containers / Bundle / Application / 48133A5D - 90E1 - 494C - 8472 - 79C2B5DE912B / 比亚迪汽车.app / 比亚迪汽车! - [BYDLoginVC doLogin]
...
|
根据AFHTTPRequestSerializer可以判断出该App使用了 AFNetwoking库
继续hook -[AFHTTPRequestSerializer requestWithMethod:URLString:parameters:error:] 获取parameters参数,内容为加密后参数。
可以判断出加密点在+ [BYDHttpsRequestUtils httpsPostRequestWithRequestRequestInfo:successBlock:failedBlock:] 方法内。
4.2 ida 查看+ [BYDHttpsRequestUtils httpsPostRequestWithRequestRequestInfo:successBlock:failedBlock:]
这里使用Hopper反编译出现了一些问题(菜鸡 这里不知道Hopper如何更改 函数范围,有大佬知道可以留言一些么)
看一眼CFG图。(一种植物)!控制流混淆,稳住,问题不大,先看伪代码试试。
这里创建了网络请求 requestInfo实例,找一下设置参数 的函数调用。
这里找到了,+[BYDDataManager entryRequestInfo:]这个方法返回加密内容,传入的v6是明文消息字典的aes加密,密钥为$key+$value拼接sha1(先挖个坑,这里讲起来太复杂),再跟进一下康康。
wd**d,离谱了。再继续看看伪代码:
看到request字符串了,上面有个BangSafeSDK可以确定是梆梆企业的加密了,再继续深入看看+[BangSafeSDK checkcode:dataStyle:],结果utf8 编码、获取当前时间,最终调用了sub_1023BE0D4。
这里本来想看看sub_1023BE0D4的CFG,IDA直接给报错了,节点太多。
怎么办呢? 盲猜一手控制流混淆(已经习惯了),上trace!干他!
Frida Stalker trace一下调用地址,感谢misskings大佬。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | / / / <reference path = "frida-gum.d.ts" / >
/ / + [BYDHttpsRequestUtils httpsPostRequestWithRequestRequestInfo:successBlock:failedBlock:]
var target = ObjC.classes[ 'BYDHttpsRequestUtils' ][ '+ httpsPostRequestWithRequestRequestInfo:successBlock:failedBlock:' ]
console.log(target.implementation)
var m = Process.getModuleByAddress(target.implementation)
var vm = m.base.add( 0x23BE0D4 ) / / 注意ida加载二进制文件的基地址
var baseAddr = m.base
console.log(vm);
Interceptor.attach(vm, {
onEnter: function (args) {
console.log( "enter" )
this.tid = Process.getCurrentThreadId()
console.log(this.tid);
Stalker.follow(this.tid, {
events: {
/ / 暂时不需要这些 events
call: false,
ret: false,
exec : false,
block: false,
compile : false
},
transform: function (iterator) {
var instruction = iterator. next ();
const startAddress = instruction.address;
/ / 从ida里面 找到 sub_1023BE0D4 函数的地址范围,alt + p
var is = startAddress.compare(baseAddr.add( 0x23CBB6C ))< 0 && startAddress.compare(baseAddr.add( 0x23BE0D4 ))> = 0 ;
do{
if ( is ){
console.log(instruction.address.sub(baseAddr).add( 0x100000000 ) + ":" + instruction);
}
iterator.keep();
} while ((instruction = iterator. next ()) ! = = null);
}
})
},
onLeave: function (ret) {
Stalker.unfollow(this.tid)
}
})
|
trace 的指令如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 0x1023be0e4 :stp x20, x19, [sp,
0x1023be0e8 :stp x29, x30, [sp,
0x1023be0ec :add x29, sp,
0x1023be0f0 :sub sp, sp,
0x1023be0f4 :sub x9, x29,
0x1023be0f8 :adrp x8,
0x1023be0fc :ldr x8, [x8,
0x1023be100 :ldr x8, [x8]
0x1023be104 : str x8, [x9,
0x1023be108 :mov w8,
0x1023be10c : cmp x0,
0x1023be110 : str w8, [sp,
0x1023be114 :mov w8,
0x1023be118 :mov w9,
0x1023be11c :csel w8, w9, w8, eq
0x1023be120 :stp w8, w2, [sp,
0x1023be124 : cmp w2,
0x1023be128 :mov w8,
0x1023be12c :csel w8, w9, w8, eq
0x1023be130 : str w8, [sp,
0x1023be134 :mov w8,
0x1023be138 :mov w9,
0x1023be13c :csel w8, w9, w8, eq
......
|
配合ida python脚本,去除无用分支:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import sark
import idc
import sys
def patch_code(addr,code):
for i in range ( len (code)):
idc.patch_byte(addr + i,code[i])
def nop(addr):
nop_code = [ 0x1f , 0x20 , 0x03 , 0xd5 ]
patch_code(addr,nop_code)
def main():
logfilename = "./log.txt"
start = 0x1023BE0D4
end = 0x1023CBB6C
addrs = []
with open (logfilename, "r" ) as logfile:
lines = logfile.readlines()
for line in lines:
addrs.append( int (line.replace( "\n" ,"").split( ':' )[ 0 ], 16 ))
for addr in addrs:
line = sark.line.Line(addr)
line.color = 0x00ffff
funcLines = sark.lines(start,end)
for line in funcLines:
if line. type = = "code" :
if line.color! = 0x00ffff :
nop(line.ea)
if __name__ = = "__main__" :
main()
|
再次查看CFG图:
不会,遂放弃。
毁灭吧!!! 挖坑了,其实还是控制流混淆,先分析到这里吧。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2022-8-24 14:25
被FANGG3编辑
,原因: