【iOS逆向】某交友App的x-sign算法分析

【【iOS逆向】某交友App的x-sign算法分析】阅读此文档的过程中遇到任何问题,请关注公众号【移动端Android和iOS开发技术分享】或加QQ群【812546729】1.目标某交友软件的x-sign算法分析。2.操作环境mac系统frida-ios-dump:砸壳Charles:抓包已越狱iOS设备:脱壳及frida调试IDA Pro:静态分析3.流程寻找切入点在账号密码登录页,点击登录,通过Charles抓包获取到关键词为x-sign,这也就是我们的切入点:
【iOS逆向】某交友App的x-sign算法分析
文章图片

分析过程使用frida-ios-dump的砸壳命令dump.py com.wemomo.momoappdemo1 砸壳获取到ipa文件,再使用IDA Pro编译ipa文件,然后搜索搜索字符串x-sign,结果如下:
【iOS逆向】某交友App的x-sign算法分析
文章图片

查找该字符串的交叉引用,发现只有一处方法有使用:
【iOS逆向】某交友App的x-sign算法分析
文章图片

使用frida-trace的frida-trace -UF -m "-[TBSDKRequest setHTTPRequestHeader]"命令跟踪该函数,发现点击登录按钮,该方法并没有调用,说明该x-sign并非抓包获取到的x-sign参数。既然x-sign在header里。那我们再使用frida-trace -UF -m "-[NSMutableURLRequest setValue:forHTTPHeaderField:]"命令尝试跟踪设置header的函数,js代码如下:{onEnter(log, args, state) {log('--------------- start ---------------')log(-[NSMutableURLRequest setValue:${new ObjC.Object(args[2])} forHTTPHeaderField:${new ObjC.Object(args[3])}]); log('NSMutableURLRequest setValue:forHTTPHeaderField:]\n' +Thread.backtrace(this.context, Backtracer.ACCURATE) .map(DebugSymbol.fromAddress).join('\n') + '\n'); log('--------------- end ---------------')},onLeave(log, retval, state) {}}点击登录后,获取到关键信息如下:witchan@witchandeMacBook-Air ~ % frida-trace -UF -m "-[NSMutableURLRequest setValue:forHTTPHeaderField:]"Instrumenting...-[NSMutableURLRequest setValue:forHTTPHeaderField:]: Loaded handler at "/Users/witchan/__handlers__/NSMutableURLRequest/setValue_forHTTPHeaderField_.js"Started tracing 1 function. Press Ctrl+C to stop./ TID 0x303 /5679 ms--------------- start ---------------5679 ms-[NSMutableURLRequest setValue:TpBMMTGM5Lcu+FOochRUPZgo8Pg= forHTTPHeaderField:X-SIGN]5679 ms NSMutableURLRequest setValue:forHTTPHeaderField:]0x101893dcc MomoChat!-[NSMutableURLRequest(CustomHeader) injectParaToHeader:]0x105cdebcc MomoChat!-[MDRequestSerializer requestWithMethod:URLString:parameters:error:]0x1033ceb80 MomoChat!-[AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure:]0x1033ce294 MomoChat!-[AFHTTPSessionManager POST:parameters:headers:progress:success:failure:]0x105cdc138 MomoChat!-[MDHTTPSessionManager requestWithApiParam:success:failure:]0x105cbd4b4 MomoChat!+[MDApiBase postRequestWithApiParam:]0x104e99904 MomoChat!-[MDLoginService accountLoginWithAccount:params:completion:]0x104e80fd0 MomoChat!-[MDAccountLoginManager requestAccountLoginWithAccount:params:completion:]0x104eb2958 MomoChat!-[MDRegLoginAccountViewController didClickCompleteButton:]0x216999300 UIKitCore!-[UIApplication sendAction:to:from:forEvent:]0x216442424 UIKitCore!-[UIControl sendAction:to:forEvent:]0x216442744 UIKitCore!-[UIControl _sendActionsForEvents:withEvent:]0x2164417b0 UIKitCore!-[UIControl touchesEnded:withEvent:]0x2165bb2d0 UIKitCore!_UIGestureEnvironmentUpdate0x2165b93a8 UIKitCore!-[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:]0x2165b9188 UIKitCore!-[UIGestureEnvironment _updateForEvent:window:]5679 ms--------------- end ---------------根据调用堆栈可知设置x-sign的函数在[NSMutableURLRequest injectParaToHeader:],继续trace该函数frida-trace -UF -m "-[NSMutableURLRequest injectParaToHeader:]",js代码如下:{ onEnter(log, args, state) {log(-[NSMutableURLRequest injectParaToHeader:]); var obj = new ObjC.Object(args[2]) var ivar = obj.$ivars for (var key in ivar) { log("k:" + key + " v:" + ivar[key]); } }, onLeave(log, retval, state) { }}得到日志如下: 2016 ms -[NSMutableURLRequest injectParaToHeader:] 2016 ms k:isa v:MDApiParam 2016 ms k:_compressed v:true 2016 ms k:_loggedIn v:true 2016 ms k:_licienceKey v:63c92d0c 2016 ms k:_paraDic v:{\nBc4grei+NtA8CMpMOGw="; G90EcFCPigXsWIIvM++Z4Uzf033xcRe1544/byyAWPRDZJJn0TCpp/UgevDQVJ"code_version" = 2; "map_id" = 782054678088; \nbkMIYHkZkBGwC3Ix4q5ksZrxiRD/Xq3v2EGGb7Asv5mByy7ZQ6pG1TYZ"; 9bcNyVCkUsYGBlUTMc/8ZoFy6ClL} 2016 ms k:_backupDic v:{"_idfa_" = "21D2A6AF-58D5-4E0A-ABBA-FC5972DAE0BD"; "_net_" = wifi; "_uid_" = 3d6777a2d9e59e5da0cf8b6b75e0f1fb; account = 13333333333; bindSource = "bind_source_new_login"; ct = "1661094132.711969"; lat = 0; lng = 0; password = e3ceb5881a0a1fdaad01296d7554868d; rqid = e3f4be75; uid = 3d6777a2d9e59e5da0cf8b6b75e0f1fb; } 2016 ms k:_tokenString v:null 2016 ms k:_currentLV v:1 2016 ms k:_decodeFailedCount v:0 2016 ms k:_signString v:QV+H6sFy/QHCfrFndOKn/IhfnIg= 2016 ms k:_isThirdRequest v:false 2016 ms k:_delegate v:null 2016 ms k:_successSelector v:0x0 2016 ms k:_failSelector v:0x0 2016 ms k:_errorSelector v:0x0 2016 ms k:_identifier v:null 2016 ms k:_headers v:null 2016 ms k:_cookie v:null 2016 ms k:_userInfo v:null 2016 ms k:_timeout v:15 2016 ms k:_requestType v:3 2016 ms k:_urlString v:https://api.immomo.com/api/v2... 2016 ms k:_urlHost v:api.immomo.com 2016 ms k:_uploadData v:null 2016 ms k:_otherPara v:null 2016 ms k:_state v:0 2016 ms k:_successCallbackBlock v:[object Object] 2016 ms k:_failCallbackBlock v:[object Object] 2016 ms k:_errorCallbackBlock v:[object Object] 2069 ms -[NSMutableURLRequest injectParaToHeader:] 2069 ms k:isa v:MDApiParam 2069 ms k:_compressed v:false 2069 ms k:_loggedIn v:true 2069 ms k:_licienceKey v:null 2069 ms k:_paraDic v:{"_idfa_" = "21D2A6AF-58D5-4E0A-ABBA-FC5972DAE0BD"; "_net_" = wifi; "_uid_" = 3d6777a2d9e59e5da0cf8b6b75e0f1fb; "click_sign" = "click_account_login_button"; type = "login_register_click"; } 2069 ms k:_backupDic v:null 2069 ms k:_tokenString v:null 2069 ms k:_currentLV v:0 2069 ms k:_decodeFailedCount v:0 2069 ms k:_signString v:null 2069 ms k:_isThirdRequest v:false 2069 ms k:_delegate v:null 2069 ms k:_successSelector v:0x0 2069 ms k:_failSelector v:0x0 2069 ms k:_errorSelector v:0x0 2069 ms k:_identifier v:null 2069 ms k:_headers v:null 2069 ms k:_cookie v:null 2069 ms k:_userInfo v:null 2069 ms k:_timeout v:15 2069 ms k:_requestType v:1 2069 ms k:_urlString v:https://api.immomo.com/v1/log... 2069 ms k:_urlHost v:api.immomo.com 2069 ms k:_uploadData v:null 2069 ms k:_otherPara v:null 2069 ms k:_state v:0 2069 ms k:_successCallbackBlock v:null 2069 ms k:_failCallbackBlock v:null 2069 ms k:_errorCallbackBlock v:null根据请求头的x-sign值发现,x-sign参数在MDApiParam类的_signString属性里,那我们跟踪MDApiParam类的setSignString:方法,frida-trace -UF -m "-[MDApiParam setSignString:]",结果跟踪失败。那就说明该方法在MDApiParam的父类,那我们调整trace命令为frida-trace -UF -m "-[* setSignString:]",js代码如下:{onEnter(log, args, state) { log(-[MDApiBaseParam setSignString:${new ObjC.Object(args[2])}]); log('MDApiBaseParam setSignString:]\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'); log('--------------- end ---------------')},onLeave(log, retval, state) {}}跟踪日志如下:2838 ms -[MDApiBaseParam setSignString:3XEvF8ZcUY1v7bknbQYWKsrajvQ=]2838 ms MDApiBaseParam setSignString:]0x1018a6f3c MomoChat!+[MDPrivateKeyGenerator handleRegisterPara:withGenerator:operatorItem:userAgentData:]0x105cc6ec0 MomoChat!-[MDAPIOperatorLayer statusOfSendingRequestPara:]0x105cde7f0 MomoChat!-[MDRequestSerializer requestWithMethod:URLString:parameters:error:]0x1033ceb80 MomoChat!-[AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure:]0x1033ce294 MomoChat!-[AFHTTPSessionManager POST:parameters:headers:progress:success:failure:]0x105cdc138 MomoChat!-[MDHTTPSessionManager requestWithApiParam:success:failure:]0x105cbd4b4 MomoChat!+[MDApiBase postRequestWithApiParam:]0x104e99904 MomoChat!-[MDLoginService accountLoginWithAccount:params:completion:]0x104e80fd0 MomoChat!-[MDAccountLoginManager requestAccountLoginWithAccount:params:completion:]0x104eb2958 MomoChat!-[MDRegLoginAccountViewController didClickCompleteButton:]0x216999300 UIKitCore!-[UIApplication sendAction:to:from:forEvent:]0x216442424 UIKitCore!-[UIControl sendAction:to:forEvent:]0x216442744 UIKitCore!-[UIControl _sendActionsForEvents:withEvent:]0x2164417b0 UIKitCore!-[UIControl touchesEnded:withEvent:]0x2165bb2d0 UIKitCore!_UIGestureEnvironmentUpdate0x2165b93a8 UIKitCore!-[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:]?2838 ms --------------- end ---------------根据调用堆栈,在IDA Pro查看[MDPrivateKeyGenerator handleRegisterPara:withGenerator:operatorItem:userAgentData:]函数,该函数有使用ollvm混淆,不过,通过关键词搜索,发现目标函数:
【iOS逆向】某交友App的x-sign算法分析
文章图片

发现生成sign的函数为MDPrivateKeyGenerator类的signStringForEncryptedData:userAgentData:withTDKey:方法。frida-trace -UF -m "[MDPrivateKeyGenerator signStringForEncryptedData:userAgentData:withTDKey:]" -m "[MDPrivateEncryptor encryptData:withPassword:error:]" -m "[NSJSONSerialization dataWithJSONObject:options:error:]"该方法,对应js代码如下:[MDPrivateKeyGenerator signStringForEncryptedData:userAgentData:withTDKey:]{onEnter(log, args, state) { var obj = new ObjC.Object(args[2]); var ua = new ObjC.Object(args[3]); log(+[MDPrivateKeyGenerator signStringForEncryptedData:${obj} userAgentData:${ua.bytes().readUtf8String(ua.length())} withTDKey:${new ObjC.Object(args[4])}]); log('MDPrivateKeyGenerator signStringForEncryptedData from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'); },onLeave(log, retval, state) { log(+[MDPrivateKeyGenerator signStringForEncryptedData:userAgentData:withTDKey:]=${new ObjC.Object(retval)}=); }}[MDPrivateEncryptor encryptData:withPassword:error:]{onEnter(log, args, state) { var obj = new ObjC.Object(args[2]); log(+[MDPrivateEncryptor encryptData:${obj} withPassword:${args[3]} error:${args[4]}]); },onLeave(log, retval, state) { var obj = new ObjC.Object(retval); log(+[MDPrivateEncryptor encryptData:withPassword:error:]=${obj}=); }}[NSJSONSerialization dataWithJSONObject:options:error:]{onEnter(log, args, state) { log(+[NSJSONSerialization dataWithJSONObject:${new ObjC.Object(args[2])} options:${args[3]} error:${args[4]}]); },onLeave(log, retval, state) { var obj = new ObjC.Object(retval); log(+[NSJSONSerialization dataWithJSONObject:options:error:]=${obj}=); }}关键日志如下:+[NSJSONSerialization dataWithJSONObject:{ "_idfa_" = "21D2A6AF-58D5-4E0A-ABBA-FC5972DAE0BD"; "_net_" = wifi; "_uid_" = 3d6777a2d9e59e5da0cf8b6b75e0f1fb; account = 13333333333; bindSource = "bind_source_new_login"; ct = "1661097991.706133"; lat = 0; lng = 0; password = e3ceb5881a0a1fdaad01296d7554868d; rqid = b0a993ba; uid = 3d6777a2d9e59e5da0cf8b6b75e0f1fb; } options:0x0 error:0x0]+[NSJSONSerialization dataWithJSONObject:options:error:]=<7b227569 64223a22 33643637 37376132 64396535 39653564 61306366 38623662 37356530 66316662 222c225f 6e65745f 223a2277 69666922 2c226374 223a2231 36363130 39373939 312e3730 36313333 222c225f 69646661 5f223a22 32314432 41364146 2d353844 352d3445 30412d41 4242412d 46433539 37324441 45304244 222c226c 6174223a 2230222c 22706173 73776f72 64223a22 65336365 62353838 31613061 31666461 61643031 32393664 37353534 38363864 222c2262 696e6453 6f757263 65223a22 62696e64 5f736f75 7263655f 6e65775f 6c6f6769 6e222c22 72716964 223a2262 30613939 33626122 2c226163 636f756e 74223a22 31333333 33333333 33333322 2c226c6e 67223a22 30222c22 5f756964 5f223a22 33643637 37376132 64396535 39653564 61306366 38623662 37356530 66316662 227d>=+[MDPrivateEncryptor encryptData:<7b227569 64223a22 33643637 37376132 64396535 39653564 61306366 38623662 37356530 66316662 222c225f 6e65745f 223a2277 69666922 2c226374 223a2231 36363130 39373939 312e3730 36313333 222c225f 69646661 5f223a22 32314432 41364146 2d353844 352d3445 30412d41 4242412d 46433539 37324441 45304244 222c226c 6174223a 2230222c 22706173 73776f72 64223a22 65336365 62353838 31613061 31666461 61643031 32393664 37353534 38363864 222c2262 696e6453 6f757263 65223a22 62696e64 5f736f75 7263655f 6e65775f 6c6f6769 6e222c22 72716964 223a2262 30613939 33626122 2c226163 636f756e 74223a22 31333333 33333333 33333322 2c226c6e 67223a22 30222c22 5f756964 5f223a22 33643637 37376132 64396535 39653564 61306366 38623662 37356530 66316662 227d> withPassword:0x282806bc0 error:0x0]+[MDPrivateEncryptor encryptData:withPassword:error:]=<020350f1 d8c4006a 2daffbca efd85d33 0b76f031 c23d38f6 7c8a1ef9 ed054baa d07aeba0 fb780f76 6822ac1b a68c9254 3cc58d5e 8707e40b 8f68ff0c fbcdea46 db6cc822 1c1e7e84 332805d5 88edcb1a 182a1db7 4c0e4568 75ee7859 b5f4af82 67ec6662 03e41725 740412e2 655d04a9 fc9321fe 5220ed14 076d2a2d 8d840686 0107810f 886cd438 eec7b0ce 4f244ecc acafb5ad 285bec58 e714962d 9e4e5fba 75ac82cd cf23c69e 862f0833 9e337628 c3b79aa3 2571ff8f 4b3f44c9 52357277 5beb8dce f1e9cc9a 6e763b6e eb2ae747 d00d571b 3d668e09 f37dec21 3aaf6bd6 b8714b98 b1b1513c ef5f080c fc07b17b a0cc5991 ac9e58d7 b1c14edb 084b1c0e 05ac1bb8 15b5efcb a64f1f86 035a1e84 b326a8bc 355093d6 dd8a12d8 96bbe3e0 9a252878 18cfc115 78507b3c 20baedf4 495c969b 4e433364 ceddf0a3 f759aab0 4402cfe9 4aa934>=+[MDPrivateKeyGenerator signStringForEncryptedData:<020350f1 d8c4006a 2daffbca efd85d33 0b76f031 c23d38f6 7c8a1ef9 ed054baa d07aeba0 fb780f76 6822ac1b a68c9254 3cc58d5e 8707e40b 8f68ff0c fbcdea46 db6cc822 1c1e7e84 332805d5 88edcb1a 182a1db7 4c0e4568 75ee7859 b5f4af82 67ec6662 03e41725 740412e2 655d04a9 fc9321fe 5220ed14 076d2a2d 8d840686 0107810f 886cd438 eec7b0ce 4f244ecc acafb5ad 285bec58 e714962d 9e4e5fba 75ac82cd cf23c69e 862f0833 9e337628 c3b79aa3 2571ff8f 4b3f44c9 52357277 5beb8dce f1e9cc9a 6e763b6e eb2ae747 d00d571b 3d668e09 f37dec21 3aaf6bd6 b8714b98 b1b1513c ef5f080c fc07b17b a0cc5991 ac9e58d7 b1c14edb 084b1c0e 05ac1bb8 15b5efcb a64f1f86 035a1e84 b326a8bc 355093d6 dd8a12d8 96bbe3e0 9a252878 18cfc115 78507b3c 20baedf4 495c969b 4e433364 ceddf0a3 f759aab0 4402cfe9 4aa934> userAgentData:MomoChat/9.2.6 ios/4268 (iPhone 6; iOS 12.5.5; zh_CN; iPhone7,2; S1) withTDKey:LZekgG6VHCbwKhzTeSHYx+BbJJOUJsggLZekgG6VHCbwKhzT]MDPrivateKeyGenerator signStringForEncryptedData from:0x1018a6f1c MomoChat!+[MDPrivateKeyGenerator handleRegisterPara:withGenerator:operatorItem:userAgentData:]0x105cc6ec0 MomoChat!-[MDAPIOperatorLayer statusOfSendingRequestPara:]0x105cde7f0 MomoChat!-[MDRequestSerializer requestWithMethod:URLString:parameters:error:]0x1033ceb80 MomoChat!-[AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure:]0x1033ce294 MomoChat!-[AFHTTPSessionManager POST:parameters:headers:progress:success:failure:]0x105cdc138 MomoChat!-[MDHTTPSessionManager requestWithApiParam:success:failure:]0x105cbd4b4 MomoChat!+[MDApiBase postRequestWithApiParam:]0x104e99904 MomoChat!-[MDLoginService accountLoginWithAccount:params:completion:]0x104e80fd0 MomoChat!-[MDAccountLoginManager requestAccountLoginWithAccount:params:completion:]0x104eb2958 MomoChat!-[MDRegLoginAccountViewController didClickCompleteButton:]0x216999300 UIKitCore!-[UIApplication sendAction:to:from:forEvent:]0x216442424 UIKitCore!-[UIControl sendAction:to:forEvent:]0x216442744 UIKitCore!-[UIControl _sendActionsForEvents:withEvent:]0x2164417b0 UIKitCore!-[UIControl touchesEnded:withEvent:]0x2165bb2d0 UIKitCore!_UIGestureEnvironmentUpdate0x2165b93a8 UIKitCore!-[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:]+[MDPrivateKeyGenerator signStringForEncryptedData:userAgentData:withTDKey:]=LbQ1kIg2MGf+5uXtUR4MguFYTIE==经过整理得出:签名函数[MDPrivateKeyGenerator signStringForEncryptedData:userAgentData:withTDKey:]的入参分别为:EncryptedData:调用[MDPrivateEncryptor encryptData:withPassword:error:]生成,入参为:{ "_idfa_" = "21D2A6AF-58D5-4E0A-ABBA-FC5972DAE0BD"; "_net_" = wifi; "_uid_" = 3d6777a2d9e59e5da0cf8b6b75e0f1fb; account = 13333333333; bindSource = "bind_source_new_login"; ct = "1661097991.706133"; lat = 0; lng = 0; password = e3ceb5881a0a1fdaad01296d7554868d; rqid = b0a993ba; uid = 3d6777a2d9e59e5da0cf8b6b75e0f1fb; }userAgentData:MomoChat/9.2.6 ios/4268 (iPhone 6; iOS 12.5.5; zh_CN; iPhone7,2; S1)也就是请求头的user-agent字段TDKey:LZekgG6VHCbwKhzTeSHYx+BbJJOUJsggLZekgG6VHCbwKhzT函数[MDPrivateKeyGenerator signStringForEncryptedData:userAgentData:withTDKey:]被混淆过了,抠出关键代码如下:id __cdecl +MDPrivateKeyGenerator signStringForEncryptedData:userAgentData:withTDKey:{ NSMutableData data = [[NSMutableData alloc] initWithData:ua]; [data appendData:inData]; return [MDPrivateKeyGenerator signDataForData: data withKey: key]; }[MDPrivateKeyGenerator signDataForData:withKey:]仍然被混淆,继续抠出关键代码如下: case 1048019035: objc_retainAutorelease(data1); data_byte = objc_msgSend(data1, bytes, v26); v38 = (__int64 )v33; v22 = (__int64 )v33; ((_DWORD )v33 + 4) = 0; v22 = 0LL; v22[1] = 0LL; objc_retainAutorelease(key2); key_c = objc_msgSend(key2, UTF8String, v26); outData = https://www.it610.com/article/(__int64 )v33; dataLength = (unsigned __int64)objc_msgSend(data1, length1, v26); v40 = (unsigned int)sub_101137F5C(data_byte, key_c, outData, dataLength) == 0; v6 = 1136488291; break; }继续进入sub_101137F5C函数:__int64 __fastcall sub_101137F5C(char a1, _QWORD a2, void a3, signed int length){ size_t v4; // x22 size_t v5; // x23 signed int v6; // w9 char v7; // x24 char v8; // x24 signed int v9; // w8 BOOL v11; // [xsp+4h] [xbp-7Ch] char inData; // [xsp+8h] [xbp-78h] _QWORD key; // [xsp+10h] [xbp-70h] void outData; // [xsp+18h] [xbp-68h] signed int v15; // [xsp+24h] [xbp-5Ch] bool v16; // [xsp+2Bh] [xbp-55h] unsigned int v17; // [xsp+2Ch] [xbp-54h] inData = https://www.it610.com/article/a1; v11 = length < 1 || a1 == 0LL || a2 == 0LL || a3 == 0LL; v4 = length; v5 = length + 8; v6 = -982936543; key = a2; outData = a3; do { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { v9 = v6; if ( v6 <= -213277501 ) break; if ( v6> 1153753992 ) { if ( v6 > 1967097480 ) { if ( v6 == 1967097481 ) { v7 = (char )malloc(v5); memcpy(v7, inData, v4); (_QWORD )&v7[v4] = key; sub_101137BEC((__int64)v7, (__int64)outData, v5); free(v7); goto LABEL_8; } if ( v6 == 1993019028 )LABEL_6: v6 = -1283420476; } else if ( v6 == 1153753993 ) { v6 = -1085362011; } else if ( v6 == 1602184948 ) {LABEL_8: v6 = -2054010553; } } else if ( v6 > 932805686 ) { if ( v6 == 932805687 ) { v6 = -776523138; v16 = v11; } else if ( v6 == 1133444574 ) { v15 = 0; v6 = -816491233; } } else { v6 = 1153753993; if ( v9 != -213277500 ) { v6 = v9; if ( v9 == 589407864 ) v6 = 1153753993; } } } if ( v6 <= -1072802235 ) break; if ( v6 > -816491234 ) { if ( v6 == -816491233 ) { v17 = v15; goto LABEL_6; } if ( v6 == -776523138 ) { if ( v16 ) v6 = -213277500; else v6 = 1602184948; } } else { v6 = 932805687; if ( v9 != -1072802234 ) { v6 = v9; if ( v9 == -982936543 ) v6 = 932805687; } } } if ( v6 <= -1283420477 ) break; if ( v6 == -1283420476 ) { v6 = -2014741442; } else if ( v6 == -1085362011 ) { v15 = -970; v6 = -816491233; } } if ( v6 != -2054010553 ) break; v8 = (char )malloc(v5); memcpy(v8, inData, v4); (_QWORD )&v8[v4] = key; sub_101137BEC((__int64)v8, (__int64)outData, v5); free(v8); v6 = 1133444574; } } while ( v6 != -2014741442 ); return v17; }发现该函数最终调用了sub_101137BEC函数,继续点进去:__int64 __fastcall sub_101137BEC(__int64 inData, __int64 outData, signed int length){ signed int v3; // w20 signed int v4; // w9 signed int v5; // w8 __int64 v7; // [xsp+0h] [xbp-70h] __int64 v8; // [xsp+8h] [xbp-68h] void v9; // [xsp+10h] [xbp-60h] bool v10; // [xsp+19h] [xbp-57h] bool v11; // [xsp+1Ah] [xbp-56h] bool v12; // [xsp+1Bh] [xbp-55h] unsigned int v13; // [xsp+1Ch] [xbp-54h] v7 = length; v10 = inData =https://www.it610.com/article/= 0; v4 = -1578351266; v8 = inData; v9 = (void )outData; v11 = length < 1; while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { v5 = v4; if ( v4 > -472472763 ) break; if ( v4 > -1578351267 ) { if ( v4 > -1093978826 ) { v4 = -1307992632; if ( v5 != -1093978825 ) { v4 = v5; if ( v5 == -954022793 ) { v13 = v3; v4 = 682513349; } } } else if ( v4 == -1578351266 ) { if ( v10 || v11 ) v4 = -1093978825; else v4 = 1410854159; } else if ( v4 == -1307992632 ) { v4 = -472472762; } } else if ( v4 > -1972614761 ) { v4 = 566635925; if ( v5 != -1972614760 ) { v4 = v5; if ( v5 == -1711298395 ) { if ( v12 ) v4 = 841496535; else v4 = -1093978825; } } } else { v4 = 682513349; if ( v5 != -2077253293 ) { v4 = v5; if ( v5 == -1988385219 ) { v3 = 0; v4 = -954022793; } } } } if ( v4 > 589005999 ) break; if ( v4 > -69020687 ) { if ( v4 == -69020686 ) { sub_101C0BC50(v8, v7, v9); v4 = 589006000; } else if ( v4 == 566635925 ) { v4 = -1988385219; } } else if ( v4 == -472472762 ) { v3 = -978; v4 = -954022793; } else if ( v4 == -318483307 ) { v4 = -1307992632; } } if ( v4 > 841496534 ) break; if ( v4 == 589006000 ) { v12 = sub_101C0BC50(v8, v7, v9) != 0LL; v4 = -1711298395; } else if ( v4 == 682513349 ) { v4 = 1752038933; } } v4 = 566635925; if ( v5 != 841496535 ) { v4 = 589006000; if ( v5 != 1410854159 ) { v4 = v5; if ( v5 == 1752038933 ) break; } } } return v13; }发现该函数最终调用了sub_101C0BC50函数,再点进去:_DWORD __fastcall sub_101C0BC50(char inData, __int64 length, void outData){ __int64 length2; // x20 char inData2; // x21 _DWORD outData2; // x19 __int64 v7; // [xsp+0h] [xbp-90h] length2 = length; inData2 = inData; if ( outData ) outData2 = outData; else outData2 = &unk_10AC6B920; if ( !(unsigned int)sub_101C0BC08(&v7) ) return 0LL; sub_101C0AA00(&v7, inData2, length2); sub_101C0BB24(outData2, (unsigned int )&v7); sub_101C06228((__int64)&v7, 96LL); return outData2; }使用frida脚本打印sub_101C0BC50参数:js代码:var addr = 0x1C0BC50var baseAddr = Module.findBaseAddress('MomoChat')!; Interceptor.attach(baseAddr.add(addr), { onEnter: function(args) { console.log(addr.toString(16), "=begin tatget Addr===================================================================="); console.log(args[0].readCString()); console.log(args[1]); }, onLeave: function(retval) { var ret = ObjC.classes.NSData.dataWithBytes_length_(retval, 20); console.log("ret:", ret) console.log(addr.toString(16), "=end tatget Addr===================================================================="); }}); 日志如下:1c0bc50 =begin tatget Addr====================================================================???Ls?a' ??SRf?{?^??N$?6?????.?-?0x31ret: 1c0bc50 =end tatget Addr====================================================================1c0bc50 =begin tatget Addr====================================================================?%{0x4ret: 1c0bc50 =end tatget Addr====================================================================1c0bc50 =begin tatget Addr===================================================================={"uid":"3d6777a2d9e59e5da0cf8b6b75e0f1fb","_net_":"wifi","ct":"1661534490.693195","_idfa_":"21D2A6AF-58D5-4E0A-ABBA-FC5972DAE0BD","lat":"0","password":"e3ceb5881a0a1fdaad01296d7554868d","bindSource":"bind_source_new_login","rqid":"de7161c2","account":"13333333333","lng":"0","_uid_":"3d6777a2d9e59e5da0cf8b6b75e0f1fb"}0x13eret: <305af756 afbb064b a1786925 657d15f9 2c45ae27>1c0bc50 =end tatget Addr====================================================================1c0bc50 =begin tatget Addr====================================================================0Z?V0x4ret: 1c0bc50 =end tatget Addr====================================================================1c0bc50 =begin tatget Addr====================================================================MomoChat/9.2.6 ios/4268 (iPhone 6; iOS 12.5.5; zh_CN; iPhone7,2; S1)0Z?V0x193ret: <7ab2461f 1b9fc68d 79469c19 2bb653a9 2ef706a6>1c0bc50 =end tatget Addr====================================================================1c0bc50 =begin tatget Addr====================================================================}??0x4ret: <97d96923 4d342ba2 d7767838 838707fd 6dc19ebb>1c0bc50 =end tatget Addr====================================================================<7ab2461f 1b9fc68d 79469c19 2bb653a9 2ef706a6>该数据转换成base64后,正是x-sign。
【iOS逆向】某交友App的x-sign算法分析
文章图片

结果sub_101C0BC50函数就是最终生成x-sign的地方,sub_101C0AA00函数对入参进行加工,sub_101C0BB24最终 生成x-sign参数。sub_101C0BB24函数的代码如下:signed __int64 __fastcall sub_101C0BB24(_DWORD a1, unsigned int inData){ unsigned int inData2; // x20 _DWORD outData; // x19 unsigned int v4; // x21 __int64 v5; // x8 signed __int64 v6; // x9 unsigned int v7; // w8 inData2 = inData; outData = https://www.it610.com/article/a1; v4 = inData + 7; v5 = inData[23]; ((_BYTE )inData + v5 + 28) = -128; v6 = v5 + 1; if ( (unsigned int)v5 >= 0x38 ) { bzero((char )v4 + v6, 63 - v5); sub_101C0AB08(inData2, v4, 1LL); v6 = 0LL; } bzero((char )v4 + v6, 56 - v6); v7 = bswap32(inData2[5]); inData2[21] = bswap32(inData2[6]); inData2[22] = v7; sub_101C0AB08(inData2, v4, 1LL); inData2[23] = 0; sub_101C06228((__int64)v4, 64LL); outData = https://www.it610.com/article/bswap32(*inData2); outData[1] = bswap32(inData2[1]); outData[2] = bswap32(inData2[2]); outData[3] = bswap32(inData2[3]); outData[4] = bswap32(inData2[4]); return 1LL; }这应该就是生成x-sign的最终函数,就先分析到这吧。End阅读此文档的过程中遇到任何问题,请关注公众号【移动端Android和iOS开发技术分享】或加QQ群【812546729】
【iOS逆向】某交友App的x-sign算法分析
文章图片

    推荐阅读