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中的代码了。

相关推荐
幽夜落雨4 分钟前
ios老版本应用安装方法
ios
gxhlh6 小时前
局域网中 Windows 与 Mac 互相远程连接的最佳方案
windows·macos
宏基骑士6 小时前
mac 电脑上安装adb命令
macos·adb
胖虎18 小时前
实现 iOS 自定义高斯模糊文字效果的 UILabel(文末有Demo)
ios·高斯模糊文字·模糊文字
水银嘻嘻13 小时前
【Mac】Python相关知识经验
开发语言·python·macos
梦魇梦狸º1 天前
mac 配置 python 环境变量
chrome·python·macos
丁总学Java1 天前
macOS如何进入 Application Support 目录(cd: string not in pwd: Application)
macos
qdprobot1 天前
Mixly米思齐1.0 2.0 3.0 软件windows版本MAC苹果电脑系统安装使用常见问题与解决
windows·macos
麦克Mapp1 天前
不用安装双系统,如何在mac上玩windows游戏呢?
macos
符小易1 天前
Mac苹果电脑 怎么用word文档和Excel表格?
macos·word·excel