ios逆向某新闻 md5+aes

本期的案例比较简单,也许是ios逆向算法本来就比较简单的原因,所以前面我就多扯一些爬虫和逆向的东西。之前写的文章都是js逆向和android逆向的案例,这也是首篇ios的案例,所以会从入门开始讲起。

3大逆向对比

首先爬虫工程师大部分都是需要js逆向的,会安卓的人不多,ios的就更不用说了,js逆向中会安卓逆向的保守估计不超过40%,因为大部分人搞爬虫都是从js开始的,当然少部分会从安卓开始,而ios逆向和安卓逆向的比例不超过1:5,你去各大社区的论坛帖子数对比下就知道了,网上的ios协议分析也是少的可怜。学ios逆向有什么用处呢?对我们爬虫工程师来说就是可以增加一个技能,让你的简历脱颖而出,

很多招聘要求上都有写,会安卓逆向的优先,会ios逆向的优先。其次,ios的逆向及风控要比安卓逆向弱很多,如果安卓上业务过不去可以考虑ios,ios的很多app即使接口有加密也有很多不验证的(本篇会验证),并且不像安卓跑几次就封账号了。

ios难度与安卓对比

很多人说ios逆向比安卓简单,有以下几个原因

1 首先就是闭源,安卓开源导致的各种系统定制,各大安全厂商不得不对这些系统进行检测,对抗就是这样起来的。

2 iphone默认只允许用户从app store下载应用,并且上架到了app store的应用都被苹果加了一层壳,类似安卓的加固,安卓的叫脱壳,ios的叫砸壳,并且这个砸壳也是有成熟的方案的。对比下安卓的各大厂商的加固,虽然现在fart脱壳机可以脱很多整体加固和抽取加固,但是由于太过热门,现在也有很多厂商检测fart特征的,并且未来的第3代加固技术vmp加固你又该怎么办?

3 玩ios逆向的人少,对抗自然就少了,不过我这一篇文章也掀不起什么大风大浪。并且教程少,很多社区都没落了。

4 还有就是很多人以为设备的问题,ios逆向需要mac(其实win也够了,不开发插件的话),黑苹果也是够用的。还有就是iphone贵,现在的iphone6比pixel4便宜太多了,两三百就够了。

5 ios逆向处于调用系统加密库的时代,而安卓处于魔改算法,自写算法,白盒时代,前些天分析的x-zse-96就是一个魔改严重的AES。如果你用过安卓的算法助手就知道ios的加密类似于这个。

6 ios逆向的话我认为入门的话安卓要简单,因为有java层的加密给你体验,体验完事后你就得准备硬刚so了。整体来说还是ios要简单的。

正片开始

前提

肯定是需要一部iphone的,有预算的话最好不要选择太老的iphone,否则一些大型app你可能运行不起来,最好不要低于iphone6.电脑 win mac都可以

环境

需要能越狱的,并且在ios上安装好frida,同时配置好ssl kill switch2插件(类似安卓的justtrustme),这些教程都比较简单,网上都有资料,相信你都搞逆向了不会连这个配置都完不成吧!

抓包

app是从app store下载的,目标api是搜索接口

抓了两个包转python后对比一下

第一个关键词是淀粉肠,第二个关键词是可口可乐,文本对比后发现主要是sign和url中的不一样,没有看到搜索的关键词,正常人应该都会猜关键词在url中或者sign中,先看url中的5reA57KJ6IKg和淀粉肠有什么关系你觉得?应该会猜base 64吧,因为包在传输过程中有些数据字符或者空格直接传过去可能有问题,需要先base64一下。

所以关键就是这个sign了,这个sign看着也像是base64过的,长度是64并且长度固定,转成16进制是96位,也就是48字节,hash算法好像没有96位的,对称加密算法有可能,des分组长度8字节,aes分组长度16字节,这两个都有可能。

前面我们说过ios的很多都是调用的系统函数,aes和des都调用的是CCCrypt函数,CCCrypt还包括3des和rc4 rc2等等。所以可以先hook这个函数看看

|---|------------------------------------|
| 1 | frida-trace -UF -i CCCrypt |

执行后当前目录会生成一个_handlers_的文件夹,子文件夹里有CCCrypt.js文件,如果你用过ida中的tracenatives插件就应该知道这个。

修改一下CCCrypt.js文件,初始生成的只会打印些简单的东西,只有参数的地址或者长度,修改成打印出加密的类型,key及key的长度,是否有iv,以及input和input的长度,output和output的长度,这份代码可以固定住,后续如果hook这个函数直接用这份就行了,当然你也可以自己改进一下

|----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 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 | /* ``* Auto-generated by Frida. Please modify to match the signature of CCCrypt. ``* This stub is currently auto-generated from manpages when available. ``* ``* ``For full API reference, see: https://frida.re/docs/javascript-api/ ``*/ { ``/** ``* Called synchronously when about to call CCCrypt. ``* ``* ``@this {object} - Object allowing you to store state ``for use ``in onLeave. ``* ``@param {``function``} log - Call this ``function with a string to be presented to the user. ``* ``@param {array} args - ``Function arguments represented as an array of NativePointer objects. ``* ``For example use args[0].readUtf8String() ``if the first argument is a pointer to a C string encoded as UTF-8. ``* It is also possible to modify arguments by assigning a NativePointer object to an element of this array. ``* ``@param {object} state - Object allowing you to keep state across ``function calls. ``* Only one JavaScript ``function will execute at a time, so ``do not worry about race-conditions. ``* However, ``do not use this to store ``function arguments across onEnter/onLeave, but instead ``* use ``"this" which is an object ``for keeping state local to an invocation. ``*/ ``onEnter(log, args, state) { ```log(CCCrypt(op={args[0]}, alg={args[1]}, options={args[2]}, keyLength={args[4]}, iv={args[5]} dataIn={args[6]}, dataInLength={args[7]}, dataOut={args[8]}, dataOutAvailable={args[9]}, dataOutMoved={args[10]}));`` log('key',hexdump(args[3]));` ` // log('iv',hexdump(args[5])); log('input',hexdump(args[6]));` ` log('input len',args[7]); this.args8=args[8];` ` this.arg10=args[10]; },` ` /** * Called synchronously when about to return from CCCrypt. *` ` * See onEnter for` `details.` ` * @this {object} - Object allowing you to access state stored in` `onEnter.` ` @param` `{function} log - Call this function with a string to be presented to the user. * @param {NativePointer} retval - Return` `value represented as a NativePointer object.` ` * @param` `{object} state - Object allowing you to keep state across function calls. */` ` onLeave(log, retval, state) { log('output',hexdump(this.args8));` ` log('output len',hexdump(this.arg10)); ``} }` |

改完只会再执行一次命令,并且输出到一个文件夹中,控制台输出太多会把一些输出冲掉。

frida-trace -UF -i CCCrypt -o 1.txt

这个时候抓包也要开着,不然输出太多不好找哪个是你要的。

在这里插入图片描述

把抓包中的sign转成16进制去文件里搜索

有结果,输入是fd99ce95acda41c8647d9520a061dba6,key的utf-8形式是neteasenewsboard,注意,如果utf-8是不可见字符的就用16进制形式的。iv是0x0,说明没有使用到iv,arg1=0x0说明用的第一种加密模式也就是aes,options=0x3代表PKCS7Padding和ecb模式

拿到cyberchef中加密一下结果也可以对得上。

接下来就是考虑下输入fd99ce95acda41c8647d9520a061dba6是什么了,32位考虑md5或者hmac md5,这个时候两个你都可以试一下,CC_MD5或者CCHmac,后者很少碰到,优先hook md5,这里提一下是为了提醒读者考虑这种情况,如果没hook到不要上来就往魔改去想。

|----------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 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 51 52 53 54 | /* ``* Auto-generated by Frida. Please modify to match the signature of CC_MD5. ``* This stub is currently auto-generated from manpages when available. ``* ``* For full API reference, see: https://frida.re/docs/javascript-api/ ``*/ { ``/** ``* Called synchronously when about to call CC_MD5. ``* ``* @this {object} - Object allowing you to store state for use in onLeave. ``* @param {function} log - Call this function with a string to be presented to the user. ``* @param {array} args - Function arguments represented as an array of NativePointer objects. ``* For example use args[0].readUtf8String() if the first argument is a pointer to a C string encoded as UTF-8. ``* It is also possible to modify arguments by assigning a NativePointer object to an element of this array. ``* @param {object} state - Object allowing you to keep state across function calls. ``* Only one JavaScript function will execute at a time, so do not worry about race-conditions. ``* However, do not use this to store function arguments across onEnter/onLeave, but instead ``* use "this" which is an object for keeping state local to an invocation. ``*/ ``onEnter(log, args, state) { ``this``.args0 = args[0]; ``// 入参 ``this``.args2 = args[2]; ``// 返回值指针 ``}, ``/** ``* Called synchronously when about to return from CC_MD5. ``* ``* See onEnter for details. ``* ``* @this {object} - Object allowing you to access state stored in onEnter. ``* @param {function} log - Call this function with a string to be presented to the user. ``* @param {NativePointer} retval - Return value represented as a NativePointer object. ``* @param {object} state - Object allowing you to keep state across function calls. ``*/ ``onLeave(log, retval, state) { ``var ByteArray = Memory.readByteArray(``this``.args2, 16); ``var uint8Array = ``new Uint8Array(ByteArray); ``var str = ``""``; ``for``(``var i = 0; i < uint8Array.length; i++) { ``var hextemp = (uint8Array[i].toString(16)) ``if``(hextemp.length == 1){ ``hextemp = ``"0" + hextemp ``} ``str += hextemp; ``} ```log(CC_MD5_arg={```this```.args0.readUtf8String()}`); ```// 入参` ` ```log(`CC_MD5_result={str}); ```// 返回值 ``log(Thread.backtrace(``this``.context, Backtracer.ACCURATE) ``.map(DebugSymbol.fromAddress).join(``'\n'``) + ``'\n'``); ``} } |

同时也是开着抓包的。

入参是1E1CE0E2-4FDF-41A1-A9BE-74C5F425B4A61711255091 验证了是标准的md5,

入参由两部分组成1E1CE0E2-4FDF-41A1-A9BE-74C5F425B4A6和1711255091,前面部分是头部一个固定的值,后面的是时间戳。

这样的话sign就被我们成功逆向了,仅用frida hook就成功拿到结果了。ios中很多都是这样,当然大厂除外。

安卓中的应用后缀是apk,ios中的是ipa,安卓中的可以直接扔到jadx中反编译,ios的是砸壳后的mach-o文件是扔到ida中的,看的是c代码,并且这个mach-o文件是很大的,如果一个100mb的mach-o文件,ida分析都需要好几个小时,如果是安卓的so可能也就十几秒的事情。

砸壳的方式有很多种,静态砸壳,动态砸壳,最常用的就是frida-ios-dump

总结

本章案例是比较简单的入门案例,感兴趣的可以尝试复现一下,有iphone即可。

如果是标准的oc方法,ios逆向确实比安卓逆向要简单,涉及到自写或者魔改的就需要去看ida中的代码了。

相关推荐
weixin_497845543 分钟前
.NET MAUI开发的安卓、iOS软件和Java开发的安卓和Swift开发的iOS的区别
macos·objective-c·cocoa
草明6 分钟前
ios 开发配置蓝牙
macos·ios·cocoa
小杨互联网3 小时前
Fiddler 配置安卓和ios抓包和pc抓包
ios·fiddler·抓包·安卓抓包·fiddler抓包配置安卓·浏览器抓包
m0_748254667 小时前
iOS中使用WKWebView加载和显示PDF文档实战
ios·pdf·cocoa
十月ooOO14 小时前
Capacitor 打包后的 iOS app 无法访问 http 的内容,解决办法
http·ios·iphone
二流小码农18 小时前
鸿蒙开发:一个轻盈的上拉下拉刷新组件
android·ios·harmonyos
rgrgrwfe1 天前
工具篇:(一)MacOS 下使用 Navicat 管理 MySQL 数据库:详细图文教程与常见问题解决
数据库·mysql·macos
cv-player1 天前
Mac软件推荐
macos
m0_748254091 天前
vue前端获取电脑本机的mac和ip地址
前端·vue.js·macos