逆向练手——说一说捅MXX的过程
本帖最后由 Defender 于 2019-6-10 10:26 编辑这是一个在so层对签名加密的不错的例子,想练练手的小伙伴可以在帖子最后下载apk
抓包数据:首先当然是抓包:使用工具fd
提交的数据:POST https://mapi.mafengwo.cn/rest/app/user/login/ HTTP/1.1User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; a1601 Build/LMY49I) mfwappcode/com.mfw.roadbook mfwappver/8.1.6 mfwversioncode/535 mfwsdk/20140507 channel/GROWTH-WAP-LC-3 mfwjssdk/1.1 mfwappjsapi/1.5Connection: closeX-HTTP-METHOD-OVERRIDE: PUTContent-Type: application/x-www-form-urlencoded; charset=UTF-8Content-Length: 665Host: mapi.mafengwo.cnAccept-Encoding: gzipCookie: __openudid=00:81:ec:a6:4f:7d; PHPSESSID=03rtbvl8c0nuck1uv7q9tlhkp7; mfw_uuid=5cf66bb5-5d2c-f5b1-702c-4a77de7fb626; oad_n=a%3A3%3A%7Bs%3A3%3A%22oid%22%3Bi%3A1029%3Bs%3A2%3A%22dm%22%3Bs%3A16%3A%22mapi.mafengwo.cn%22%3Bs%3A2%3A%22ft%22%3Bs%3A19%3A%222019-06-04+21%3A01%3A41%22%3B%7D; mafengwo=deleted
device_type=android&after_style=default&open_udid=00%3A81%3Aec%3Aa6%3A4f%3A7d&put_style=default&oauth_signature=P%2FqDQjTg6xlFNx%2FwyPleESdbcGA%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1559653353&time_offset=480&sys_ver=5.1.1&screen_width=540&mfwsdk_ver=20140507&screen_scale=1.5&app_code=com.mfw.roadbook&x_auth_mode=client_auth&x_auth_password=a2345678&app_ver=8.1.6&app_version_code=535&x_auth_username=15233445566&screen_height=960&oauth_consumer_key=5&oauth_version=1.0&oauth_nonce=f5080046-7ece-4ae8-80ea-2cfb30e3b24d&hardware_model=a1601&device_id=00%3A81%3Aec%3Aa6%3A4f%3A7d&brand=oppo&channel_id=GROWTH-WAP-LC-3&o_lat=39.916295&o_lng=116.410344&
分析数据包发现:open_udid和device_id都是mac,o_lat和o_lng是经纬度,由以往经验可知,nonce正常情况下都是随机生成数,所以数据包里面大部分数据都可以视为固定的,只有oauth_signture加密需要进行进一步分析。从oauth_signature_method可知加密oauth_signture的算法是Hmac-SHA1。
所以我们只需着重分析oauth_signture使用jadx反编译apk,查找oauth_signture关键字。分析排除其他选择后,发现这个可能性比较大:
一步步跟进函数调用,最后发现是一个so加密。这样就需要在IDA里面动态调试获取方法的参数了。
于是我们又进入了IDA分析so的步骤:从代码中可以看到,加载的是mfw这个名字的so库。将apk从压缩包里拖出来分析。首先从暴露出来的函数中查找xAuthencode()小技巧,直接在Exports栏中ctrl+F搜索java,就可以很快的找到需要的目标。这是因为在标准JNI格式中,被调用的方法都是以 Java开头,加上包名类名方法名的格式。如:Java_com_mfw_tnative_AuthorizeHelper_xAuthencode
第一个就是我们要找的函数调用。双击后进入IDA View-A查看arm汇编代码。
F5切换到伪C代码比较号分析。整理伪C代码,比如将第一个_JNIEnv *a1变量修改名字为更符合阅读习惯的env,对照java层的方法调用来对应修改参数名字。以方便阅读代码。整理好参数名称后,代码中的对应调用都会自动修改过来,这样就比较容易看到参数的传递情况。
伪C代码即使整理了之后本身仍然看起来杂乱无章,还夹杂着JNI,让人不知从何读起,这里有个技巧,可以从后面看起,因为一般前面是各种参数传递,而一个函数最终的return都是在后面的。从后面查看,寻找熟悉的文字,如密钥key,添加加密数据update,加密doFinal等。就容易比较快的找到要动态调试下断点的位置。比如这段代码就符合这个阅读方式:
前面数据包分析的时候已知最终的加密数据是Base64格式,上面代码很容易看到Base64编码的位置,Final是加密库里的最后加密的方法,既然要加密,就要有数据,所以就看到了update,而HmacSHA1消息摘要算法是需要key的,所以往前找,看到了Setkey。这样,加密所需的key生成位置,最终明文,加密后的密文生成位置都找到了,如果对常见的公开加密算法比较熟悉,知道所使用的加密方式的特点,就能比较快速的找到了关键点。至于前面参数如何分割,重组成加密明文的过程,并不是我们关心的,只要看到最后的需要加密的明文,不就知道需要哪些数据来构成了么?
下面进行动态调试,查看这些参数的构成:老办法,重新打开一个IDA,这样就有一个IDA做静态分析对比,一个IDA动态调试使用。按部就班,打开设备的android-server,做好端口转发,开启app,IDA附加app进程,做好动态调试所需的准备工作。在Modules栏中找到需要调试的so文件,在找到加密函数,进入。快速在加密函数的伪C代码处定位key的位置,然后切换回汇编代码模式下在key,update,base64三处下好断点。IDA的附加进程总是比较容易挂,可能要多试几次。当在key的位置断下后,查看R1寄存器。为什么是R1寄存器呢?可以参考伪C代码,第一个参数不是我们想要的,第二个才是需要的数据,第三个是key的长度。所以查看R1寄存器。
得到加密的key如下:asfsaADDJF55b262d99cff7cac7459e8&
放行就会断在第二个断点update的位置:
同理查看R1得到了加载进去的加密前的最终明文:
PUT&https%3A%2F%2Fmapi.mafengwo.cn%2Frest%2Fapp%2Fuser%2Flogin%2F&after_style%3Ddefault%26app_code%3Dcom.mfw.roadbook%26app_ver%3D8.1.6%26app_version_code%3D535%26brand%3DAndroid%26channel_id%3DGROWTH-WAP-LC-3%26device_id%3Dbc%253Af5%253Aac%253Af9%253Ab6%253A99%26device_type%3Dandroid%26hardware_model%3DAOSP%2520on%2520HammerHead%26mfwsdk_ver%3D20140507%26o_lat%3D30.526591%26o_lng%3D114.330431%26oauth_consumer_key%3D5%26oauth_nonce%3D1a1b5f49-b341-431f-8281-a5da4a5758ad%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1559750039%26oauth_version%3D1.0%26open_udid%3Dbc%253Af5%253Aac%253Af9%253Ab6%253A99%26put_style%3Ddefault%26screen_height%3D1776%26screen_scale%3D3.0%26screen_width%3D1080%26sys_ver%3D4.4.4%26time_offset%3D480%26x_auth_mode%3Dclient_auth%26x_auth_password%3Da2345678%26x_auth_username%3D15233445566
继续放行,就会断在加密完成最终进行base64编码的位置,但是这时候编码并未完成,所以要继续放行一步,这样编码才会完成,才能得到最终的编码数据。
最终的加密结果:c81oj5WJcUJEMfpghpGdKIQoV00=
加密所需的key,明文我们都拿到了,是时候验证一下结果是否正确。
验证结果证实了我们的猜想和操作没有问题。
接下来看看加密的明文一大串到底是什么东西?从一堆堆的%可以看出应该是对原字符串进行了URL编码,经过URL解码后,可以得到清晰的数据组成:PUT&https://mapi.mafengwo.cn/rest/app/user/login/&after_style=default&app_code=com.mfw.roadbook&app_ver=8.1.6&app_version_code=535&brand=Android&channel_id=GROWTH-WAP-LC-3&device_id=bc:f5:ac:f9:b6:99&device_type=android&hardware_model=AOSP on HammerHead&mfwsdk_ver=20140507&o_lat=30.526591&o_lng=114.330431&oauth_consumer_key=5&oauth_nonce=1a1b5f49-b341-431f-8281-a5da4a5758ad&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1559750039&oauth_version=1.0&open_udid=bc:f5:ac:f9:b6:99&put_style=default&screen_height=1776&screen_scale=3.0&screen_width=1080&sys_ver=4.4.4&time_offset=480&x_auth_mode=client_auth&x_auth_password=a2345678&x_auth_username=15233445566
仔细分析这个数据的组成,可以发现,元素基本上都来源于我们抓的的数据包那些相对固定的部分,然后加上了登录账号和密码。
案例apk:X蜂窝链接:https://pan.baidu.com/s/1YKuUEd5UFExEX1rrjnEsEw 提取码:05n4
赞,想知道楼主最后一张图用到的工具叫什么? MrYu 发表于 2019-6-6 03:02
为什么我的fiddler抓这个蜂窝的https都抓不出正常数据的能教一下怎么配置的吗 百度这些的https我可以抓 ...
手机上安装fiddler的证书了吗? 为什么我的fiddler抓这个蜂窝的https都抓不出正常数据的能教一下怎么配置的吗 百度这些的https我可以抓到呀 谢谢您的分享! 感谢分享 感谢分享,操作过程可以录一个小视频不,感觉对so逆向过程还是有点迷迷糊糊 准备跟着你的操作练一遍,练手 MrYu 发表于 2019-6-6 03:02
为什么我的fiddler抓这个蜂窝的https都抓不出正常数据的能教一下怎么配置的吗 百度这些的https我可以抓 ...
安装证书呀 还是有点迷糊!