关于ios:移动App入侵与逆向破解技术-iOS篇

48次阅读

共计 13556 个字符,预计需要花费 34 分钟才能阅读完成。

转载于 2016/07/25,搬迁到思否。

如果您有急躁看完这篇文章,您将懂得如何着手进行 app 的剖析、追踪、注入等实用的破解技术,另外,通过“入侵”,将帮忙您了解如何躲避常见的安全漏洞,文章纲要:

  • 简略介绍 ios 二进制文件构造与入侵的原理
  • 介绍入侵罕用的工具和办法,包含 pc 端和手机端
  • 解说黑客技术中的动态剖析和动静分析法
  • 通过一个简略的实例,来介绍如何综合使用砸壳、寻找注入点、lldb 近程调试、追踪、反汇编技术来进行黑客实战
  • 解说越狱破解补丁和不需越狱的破解补丁制作方法和差异

黑客的素养

  • 敏锐的嗅觉 有时候通过一个函数名,一个类名,就能大抵的判断出它的作用,这就是嗅觉;功力已臻化境时,甚至能够应用第六感判断出一些注入点
  • 面对失败的勇气 破解有时候很耗时,和程序开发正好相同,它耗时不是耗在写代码上,而是耗在寻找注入点和逆向工程上,有可能你花了 3 天工夫去找程序的漏洞,然而最终的破解代码可能就 2 行,不到一分钟就搞定了;然而你也须要做好面对失败的筹备,如果路选错了,有可能你这 3 天齐全是在节约脑细胞
  • 洪荒之力 洪荒之力-即入侵过程中须要借助的各种工具,工欲善其事,必先利其器,工具都是前人智慧的结晶,能用工具解决的,绝不要手动去搞

iOS 黑客关键字

iOS 的入侵离不开越狱开发,所有的破解、入侵都是建设在越狱的根底上的,如果没有拿到零碎级权限,所有的想法都是空谈了,当然,市面上存在免越狱的破解补丁,然而它的开发过程,也是基于越狱环境的

tweak

在 iOS 的黑客界,要做破解或越狱开发,就必须理解 tweak,它是各种破解补丁的统称,在 google 上,如果你想搜寻一些越狱开发材料或者开源的破解补丁代码,它是最好的关键字。

iOS 的 tweak 大抵分为两种:

  • 第一种是在 cydia 上公布的,须要越狱能力装置,大部分是 deb 格局的安装包,iOS 在越狱后,会默认装置一个名叫 mobilesubstrate 的动静库,它的作用是提供一个零碎级的入侵管道,所有的 tweak 都能够依赖它来进行开发,目前支流的开发工具有 theos 和 iOSOpenDev,前者是采纳 makefile 的一个编译框架,后者提供了一套 xcode 我的项目模版,能够间接应用 xcode 开发可调试,然而这个我的项目曾经进行更新了,对高版本的 xcode 反对不好,大家酌情抉择(本文中的例子全副采纳 theos)
  • 第二种是间接打包成 ipa 安装包,并应用本人的开发证书或者企业证书签名,不需越狱也能够装置,可间接放到本人的网站上,可实现在线装置;对于没有越狱的手机,因为权限的限度,咱们是没有方法写零碎级的 tweak 的,例如 springboard 的补丁是没法运行的,这种 tweak 大多是针对某个 app,把指标 app 进行批改注入解决,再从新签名和公布,有点相似于 windows 软件的 xxx 破解版、xxx 免注册版

没有越狱的机器因为零碎中没有 mobilesubstrate 这个库,咱们有二个抉择,第一个是间接把这个库打包进 ipa 当中,应用它的 api 实现注入,第二个是间接批改汇编代码;第一个实用于较为简单的破解行为,而且越狱 tweak 代码能够复用,第二种实用于破解一些 if…else…之类的条件语句

Mobilesubstrate

上面的图展现的就是 oc 届驰名的 method swizzling 技术,他就是 iOS 的注入原理,相似于 windows 的钩子,所以咱们注入也称为 hook

Mobilesubstrate 为了不便 tweak 开发,提供了三个重要的模块:

  • MobileHooker 就是用来做下面所说的这件事的,它定义一系列的宏和函数,底层调用 objc-runtime 和 fishhook 来替换零碎或者指标利用的函数
  • MobileLoader 用来在目标程序启动时依据规定把指定目录的第三方的动静库加载进去,第三方的动静库也就是咱们写的破解程序,他的原理上面会简略解说一下
  • Safe mode 相似于 windows 的平安模式,比方咱们写的一些零碎级的 hook 代码产生 crash 时,mobilesubstrate 会主动进入平安模式,平安模式下,会禁用所有的第三方动静库

app 注入原理

下面讲到了 mobileloader,他是怎么做到把第三方的 lib 注入进目标程序的呢?这个咱们要从二进制文件的构造说起,从上面的图来看,Mach- O 文件的数据主体可分为三大部分,别离是头部(Header)、加载命令(Load commands)、和最终的数据(Data)。mobileloader 会在目标程序启动时,会依据指定的规定查看指定目录是否存在第三方库,如果有,则会通过批改二进制的 loadCommands,来把本人注入进所有的 app 当中,而后加载第三方库。

为了让大家看的更分明,上面我用 machoview 来关上一个实在的二进制文件给大家看看,能够看出,二进制当中所有援用到的动静库都放在 Load commands 段当中,所以,通过给这个段减少记录,就能够注入咱们本人写的动静库了

那么问题来了,在这里插入咱们本人的动静库有什么用?咱们本人写的代码没有执行的入口,咱们一样没发干坏事,嗯,祝贺你问到点子上了,咱们还须要一个 ”main” 函数来执行咱们本人的代码,这个 ”main” 函数在 oc 外面称为构造函数,只有在函数前申明“attribute((constructor)) static”即可,有了它咱们就能够施展想象力,进行偷天换日干点好事了:

#import <CaptainHook/CaptainHook.h>

CHDeclareClass(AnAppClass);
CHMethod(1, void, AnAppClass, say, id, arg1)
{
    NSString* tmp=@"Hello, iOS!";
    CHSuper(1, AnAppClass, say, tmp);
}
__attribute__((constructor)) static void entry()
{NSLog(@"Hello, Ice And Fire!");
    CHLoadLateClass(AnAppClass);
    CHClassHook(1, AnAppClass,say);
}

到这里为止,咱们曾经晓得了怎么在目标程序注入本人的代码,那么咱们怎么晓得须要 hook 哪些办法?怎么找到关键点进行理论的破解呢?上面讲一下常见的 app 入侵分析方法

iOS 逆向分析方法

逆向剖析最罕用的有三种办法:

  1. 网络分析 通过剖析和篡改接口数据,能够无效的破解通过接口数据来管制客户端行为的 app,罕用的抓包工具备 Tcpdump, WireShark, Charles 等,windows 平台有 fidller
  2. 动态剖析 通过砸壳、反汇编、classdump 头文件等技术来剖析 app 行为,通过这种形式能够无效的剖析出 app 实用的一些第三方库,甚至剖析出 app 的架构等内容,罕用的工具有 dumpdecrypted(砸壳)、hopper disassembler(反汇编)、class_dump(导头文件)
  3. 动态分析 有静就有动,万物都是相生相克的,动态分析指的是通过剖析 app 的运行时数据,来定位注入点或者获取要害数据,罕用的工具有 cycript(运行时控制台)、lldb+debugserver(近程断点调试)、logify(追踪)

demo: 微信抢红包插件

下面讲了很多原理性的货色,置信大家曾经看的不耐烦了,上面咱们一起动点真格的,咱们从头开始,一步一步的做一个微信的主动抢红包插件,当然,网上可能曾经有相干的开源代码了,然而我这里要讲的是,这些代码是怎么得进去的,我么重点讲一讲剖析过程

工欲善其事,必先利其器

一台越狱的手机,并装有以下软件

  • cycript
  • dumpdecrypted
  • debug server
  • openssh

一台苹果电脑,并装有以下软件

  • class_dump
  • Theos
  • Hopper Disassembler v3
  • xcode
  • insert_dylib
  • pp 助手

寻找注入点

砸壳

首先咱们要做的就是把微信的壳砸掉,砸壳其实是为了把它的头文件 classdump 进去,因为从 appstore 下载的 app 二进制都是通过加密的,间接进行 classdump 操作是啥也看不出来的

  • 用 pp 助手把 dumpdecrypted.dylib 文件 copy 到微信的 documents 目录
  • ssh 到手机的终端,cd 到 documents 目录中,执行上面的命令进行砸壳操作
xxx$ cp /usr/lib/dumpdecrypted.dylib /path/to/app/document
xxx$ DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /path/to/WeChat

  • 最初砸壳实现后会在 documents 目录生成砸了壳后的二进制文件,用 pp 助手 copy 进去并 class-dump 他的头文件备用

执行完这几行命令后,会在微信的 documents 目录生成一个 WeChat.decrypted 文件,这就是砸壳后的二进制文件;当然了,这一步不是必须的,咱们能够间接从 91 或者 pp 助手下载一个曾经砸过壳的版本

动态分析-cycript

要想实现主动抢红包,咱们必须找到收到红包音讯的 handler 办法,怎么动手呢?咱们先从界面登程,进入微信的音讯首发窗口:

  • ssh 进手机的终端,输出 ps 命令,查找到微信的过程 id
ps aux | grep WeChat

  • 祭起神器 cycript,依据上一步找到的 pid 注入到微信的过程
cycript -p pidxxx

  • 在 cycript 的终端输出这一串办法,作用就是打印出以后界面的 view 层级,(cycript 还有很多妙用,大家能够上官网看文档,这里不具体介绍)
UIApp.keyWindow.recursiveDescription().toString()

最终的输入如下,内容太多,大家必定看不清楚,不过没关系,这个不是重点,这里只是展现一下打印的后果模式:

咱们能够随机的选取一个节点不要太靠树叶,也不要太靠树根,例如我选的是标红的局部,把这个节点的内存地址 copy 进去,这个内存地址,就代表了这个节点的 view 对象,ios 开发的老油条们都晓得,通过 view 的 nextResponder 办法,能够找出它所属的视图控制器 ViewController,所以我么在 cycript 的控制台中继续输出如下的命令:

看到没有,通过四个 nextResponder 办法调用,我么找到了以后聊天窗口的 ViewController 类名,他就是 BaseMsgContentViewController,当初咱们放大了指标范畴,上面咱们还须要持续放大范畴,要找到具体的音讯处理函数才行。

动态分析-Logify

要持续放大范畴,就得祭起神器 Logify 了,它是 theos 的一个模块,作用就是依据头文件主动生成 tweak,生成的 tweak 会在头文件的所有办法中注入 NSLog 来打印办法的入参和出参,非常适合追踪办法的调用和数据传递

当初咱们依据此前砸壳后 class_dump 进去的头文件,找到 BaseMsgContentViewController 在 pc 终端执行如下命令:

logify.pl /path/to/BaseMsgContentViewController.h > /out/to/Tweak.xm

输入的 tweak 文件大略是这个样子的:

这里带百分号的关键字,例如 %hook、%log、%orig 都是 mobilesubstrate 的 MobileHooker 模块提供的宏,其实也就是把 method swizzling 相干的办法封装成了各种宏标记,应用起来更简略,大家想要更深刻理解各种标记,能够 google 一下 logos 语言

theos 创立 tweak

下面咱们用 logify 生成了一个 tweak 代码,咱们要把它装置到手机上,首先须要应用 theos 进行编译,装置了 theos 之后,在 pc 终端输出 nic.pl:

首先抉择我的项目模版当然是 tweak 啦,而后是项目名称、作者,前面两个选项要留神:

  • 首先是 bundle filter,这个须要填你须要注入的指标 app 的 bundle id,MobileLoader 模块会依据它来寻找你的 tweak 的注入指标
  • 最初是 list id applications to terminate upon installation,这里指定当 tweak 装置胜利之后,须要 kill 的过程,咱们要 hook 微信,这里就填微信的二进制文件名就能够了,为什么要 kill?因为我么的插件是须要在 app 启动时加载进去的,如果不重启 app,插件是不会失效的

最初所有都实现后,在当前目录会生成下列文件:

把下面 logify 生成的 tweak 文件笼罩到当前目录,并用文本编辑器关上 makefile 文件,在文件的结尾减少你的 ios 设施的 ip 地址和 ssh 端口:

最初在 pc 终端进入我的项目目录,输出 make package install 命令:

期间会让你输出设施的 ssh 明码,越狱机器的默认 ssh 明码是 alpine,make 命令会生成 deb 安装包,放在 debs 目录,咱们如果想对外公布本人的插件,能够把生成的安装包上传到 cydia 即可

装置胜利后再次进入微信的聊天界面,并应用另外一个微信在群里发个一般音讯,连贯 xcode 关上越狱机器控制台,查看输入,会发现有相似上面的输入:

Jun  7 09:56:13 Administratorde-iPhone WeChat[85972] <Notice>: [1;36m[WxMsgPreview] [m[0;36mTweak.xm:308[m [0;30;46mDEBUG:[m -[<BaseMsgContentViewController: 0x15e0c9a00> addMessageNode:{m_uiMesLocalID=2, m_ui64MesSvrID=0, m_nsFromUsr=ccg*675~9, m_nsToUsr=1037957572@chatroom, m_uiStatus=1, type=1, msgSource="(null)"}  layout:1 addMoreMsg:0]

看进去了吧,音讯处理函数是 BaseMsgContentViewController 的 **addMessageNode:layout:addMoreMsg:** 办法,大家能够看出,办法的参数内容也打印进去了


动态分析-lldb

到目前为止,我么曾经把范畴放大到了具体的函数,看起来注入点曾经找到了,然而请大家思考一下,如果咱们在这个函数中注入抢红包逻辑,那咱们的 tweak 会不会有什么致命的缺点?

是的,因为 BaseMsgContentViewController 这个类是微信群聊天窗口对应的 controller,我么必须进入到群的聊天界面,这个类才会创立,如果不进入聊天窗口,咱们的插件就不失效了,而且,即便进入聊天窗口,也只是能自动枪以后群的红包而已,其余群就无能为力了,是不是有点 low?

所以为了使咱们的插件显得上流一些,我么还要持续追根溯源,寻找音讯的源头,这里就用到了 lldb 近程调试,应用 lldb 打断点的形式,通过调用栈,咱们能够就能够看到当音讯来到时,办法的调用程序,找到最先执行的音讯处理函数。

要在刚刚追踪到的 **addMessageNode:layout:addMoreMsg:** 办法中打断点,首先咱们得晓得它在运行时的内存地址,那么内存地址怎么来呢?有这么一个公式:

  • 内存地址=过程内存基地址+函数在二进制中的偏移量 

首先偏移量咱们能够通过反汇编工具 hooper 来查,在 pc 上用 hooper 关上微信的二进制文件(留神,关上时会让你抉择 armv7 或者 arm64,这须要依据你越狱手机的 cpu 类型来选,肯定要和你的手机统一),hooper 的界面十分简洁,左侧有个搜寻框,能够输出函数名,间接找到函数在二进制中的地位

通过左侧的搜寻框搜 addMessageNode 关键字,找到它的偏移量是 0x00000001017d7c6c:

找到了偏移量,还须要过程的基地址,这个地址须要连 lldb,所以上面讲一下如何连贯 lldb 进行近程调试,先 ssh 进越狱手机的终端,在终端输出如下命令(留神,你的手机必须连 xcode 调试过才会有这个命令):

debugserver *:19999 -a WeChat

而后在 pc 端新起一个终端窗口,输出如下命令来连贯手机端进行调试:

lldb  ->  process connect connect://deviceIP:19999

如果连贯胜利,会进入 lldb 的控制台,咱们在 lldb 的控制台输出如下命令来获取微信过程的基地址:

image list -o -f

执行这个命令会打印很多行数据,像上面图中这样,我么要找到微信的二进制文件所在的行,记录它的内存地址 0X00000000000E800:

到这里咱们两个地址都找到了,再通过 br 命令打断点:

br s -a '0X00000000000E800+0x00000001017d7c6c'

打好断点后持续向群外面发消息,咱们会发现过程被断掉了,这时输出 bt 指令,就能够看到以后的调用栈,就像下图这样:

剖析堆栈的时候,重点找出模块时 WeChat 的项,这些都是微信模块的办法调用,有了堆栈,咱们须要依据堆栈的内存地址找出它的具体函数名,思路还是先依据下面讲到的公式来计算出栈地址在二进制中的偏移量,而后用 hooper 找到偏移量对应的函数名

  • 函数在二进制中的偏移量=内存地址 – 过程内存基地址 

例如依据箭头所指的内存地址和刚刚失去的过程基地址,计算偏移量:

0x0000000101ad02f4 – 0x00000000000e8000 = 1019E82F4

而后在 hooper 中搜寻这个地址,失去后果如下:

最终把所有的栈都进行还原,得出调用栈是这个样子的:

-[CMessageMgr MainThreadNotifyToExt:]:
–>    
-[BaseMsgContentLogicController OnAddMsg:MsgWrap:]:
——>
-[RoomContentLogicController DidAddMsg:]
———->
-[BaseMsgContentLogicController DidAddMsg:]
—————->
-[BaseMsgContentViewController addMessageNode:layout:addMoreMsg:]:

CMessageMgr 这个类浮出水面了,是时候施展黑客的嗅觉了,依据办法名咱们能判断出 MainThreadNotifyToExt: 这个办法仅仅是用来发送告诉的,如果 hook 这个办法,咱们是拿不到音讯内容的

因为这里可能是一个异步调用,用断点的形式,可能曾经打印不进去栈信息了,所以还得应用 logify 来持续追踪 CMessageMgr 这个类,讲过的内容我就不反复了,间接失去最终的音讯处理函数:

-(void)AsyncOnAddMsg:(id)message MsgWrap:(CMessageWrap*)msgWrap 


实现“抢”的动作

上一节咱们曾经找到了 hook 的关键点,那么该如何去实现抢的动作?同样咱们须要联合动态分析和动态剖析,首先失去红包音讯体的数据特色,而后再剖析解决音讯的关键点

数据包剖析

首先咱们的代码须要分辨哪些才是红包音讯,办法很简略,用 logify 追踪 BaseMsgContentViewController,而后向微信群发一个红包,察看手机日志输入,咱们能够看出音讯的数据结构中有个 type 字段,值是 49,这个 type 应该就是标记音讯类型的,如果不确定,能够再发个图片或者文本之类的音讯,这个值是不同的:

Administratorde-iPhone WeChat[47410] <Notice>: [1;36m[WxMsgPreview] [m[0;36mTweak.xm:308[m [0;30;46mDEBUG:[m -[<BaseMsgContentViewController: 0x15e0c9a00> addMessageNode:{m_uiMesLocalID=16, m_ui64MesSvrID=1452438635530425509, m_nsFromUsr=1037957572@chatroom, m_nsToUsr=ccg*675~9, m_uiStatus=4, type=49, msgSource="<msgsource>
        <silence>0</silence>
        <membercount>3</membercount>
    </msgsource>
    "}  layout:1 addMoreMsg:0]

当初咱们能分辨音讯类型了,重点来了,怎么实现抢这个事呢,可能聪明人曾经猜到了,从 ui 动手,先找到微信自身的抢红包函数,咱们本人来给它结构参数并调用他不就行了?

把红包点开后,用 cycript 打印出以后 view 的档次,就像上面这个,一眼就能够看到重点,WCRedEnvelopesReceiveHomeView 就是开红包弹框的类名

晓得类名后,用 cycript 追踪它,点击开红包,在日志中找到了下图中的内容,从名字来看,这是一个事件处理函数,咱们当初要做的,就是把他还原成 oc 代码,真正实现抢红包性能

Administratorde-iPhone WeChat[91173] <Notice>: [1;36m[WxMsgPreview] [m[0;36mTweak.xm:8[m [0;30;46mDEBUG:[m -[<WCRedEnvelopesReceiveHomeView: 0x13cdda8c0> OnOpenRedEnvelopes]

动态分析法

怎么把他还原成 oc 代码,真正实现抢红包性能呢?还得借助一点点汇编技能,只是一点点而已,因为当初的反汇编工具曾经很弱小了,咱们不须要挨个去看寄存器了

在 pc 上用 hooper 关上微信的二进制文件,搜寻 OnOpenRedEnvelopes,查看汇编代码,留神在图片中最初一行调用了一个 WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes 函数


持续搜寻 WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes 这个办法,找到它的汇编代码

  • 首先他不晓得从哪里获取了一个 payinfoitem
  • 而后又获取了 payinfo 的 m_c2cNativeUrl 属性
  • 而后调用 substringfromindex 吧 navtiveurl 的前缀截断,并调用 bizutil 的一个办法把 url 参数转换成了一个字典

最终反解出的代码如下,是不是很简略?

NSString *nativeUrl = [[msgWrap m_oWCPayInfoItem] m_c2cNativeUrl];
nativeUrl = [nativeUrl substringFromIndex:[@"wxpay://c2cbizmessagehandler/hongbao/receivehongbao?" length]];
NSDictionary *nativeUrlDict = [%c(WCBizUtil) dictionaryWithDecodedComponets:nativeUrl separator:@"&"];


持续往下看, 在这里后面三行创立了一个 mutable dictionary:

  • 紧接着上面三个框框处都是调用了 setobject:forkey:向外面填货色,那填的货色是啥呢?
  • 其实这里曾经能够看的很分明了,第一个 key 是 msgtype,值是字符串 1,第二个 sendid,值是调用了一个 objectforkey 从另一个字典中取出来的,很显然,另一个字典就是下面从 url 解析失去的,前面的 channelid 也是同样的情理

最终失去的代码如下:

NSMutableDictionary *args = [[%c(NSMutableDictionary) alloc] init];
[args setObject:nativeUrlDict[@"msgtype"] forKey:@"msgType"];
[args setObject:nativeUrlDict[@"sendid"] forKey:@"sendId"];
[args setObject:nativeUrlDict[@"channelid"] forKey:@"channelId"];


持续往下看从箭头所指的几处,咱们能够看见,它的代码是这样的,共分为四步

  • 第一个箭头调用了 mmservicecenter 的 defaultcenter 办法来获取 mmservicecenter 实例
  • 第二个箭头调用了 CContactMgr 的 class 办法
  • 第三个箭头调用了第一步获取的 mmservicecenter 实例的 getservice 办法,而这个办法是把第二步失去的 class 作为参数
  • 第四个箭头很明确了吧,第三步失去了 CContactMgr 实例,这里就是调用 CContactMgr 实例的 getselfcontact 办法获取本人的账户材料

最终还原的到的代码如下:

CContactMgr *contactManager = [[%c(MMServiceCenter) defaultCenter] getService:[%c(CContactMgr) class]];
CContact *selfContact = [contactManager getSelfContact];


持续往下看,这里应用刚刚失去的 selfcontact 来获取 displayname 和 headimgurl,并把它们设置到刚刚的字典外面了,key 别离是 nickname 和 headimg

最终的代码:

[args setObject:[selfContact getContactDisplayName] forKey:@"nickName"];
[args setObject:[selfContact m_nsHeadImgUrl] forKey:@"headImg"];


接着看,接下来这两段就比拟蛋疼了,齐全是从内存地址外面取的值,我也不晓得他从哪里来,怎么办呢?有没有不懂汇编就能搞定它的捷径呢,答案是有!

  • 对于第一个,我能够通过它的 key 猜出来,还记得最开始的时候咱们取过 payinfo 的一个 nativeurl 属性吧,咱们权且把他传进去
  • 对于第二个,咱们能够猜想 sessionUserName 大略是会话名称,也就是群名称的意思,从哪里取这个值呢?咱们先把也设置成伪代码

最终的后果如下:

[args setObject:nativeUrl forKey:@"nativeUrl"];
[args setObject:xxx forKey:@"sessionUserName"];


持续往下看,接下来这一段还是用 mmservicecenter 来获取 WCRedLogicMgr 对象,而后调用 WCRedLogicMgr 的 open 办法来拆红包,能够设想 open 办法的参数就是下面咱们辛苦组装的字典

代码如下:

[[[%c(MMServiceCenter) defaultCenter] getService:[%c(WCRedEnvelopesLogicMgr) class]] OpenRedEnvelopesRequest:args];

领红包逻辑

到这里,咱们再总结一下咱们下面剖析的过程…

  • 失去 m_oWCPayInfoItem 属性
  • 解析 m_oWCPayInfoItem 的 m_c2cNativeUrl 属性
  • 失去 selfcontact
  • 组装相干参数
  • 调用 OpenRedEnvelopesRequest: 支付红包

最终的抢红包代码合并起来如下:

#import "WxMsgPreview.h"

%hook CMessageMgr

-(void)AsyncOnAddMsg:(id)message MsgWrap:(CMessageWrap*)msgWrap {
    %log;
    %orig;
    if(msgWrap.m_uiMessageType == 49){CContactMgr *contactManager = [[%c(MMServiceCenter) defaultCenter] getService:[%c(CContactMgr) class]];
        CContact *selfContact = [contactManager getSelfContact];

        if ([msgWrap.m_nsContent rangeOfString:@"wxpay://c2cbizmessagehandler/hongbao/receivehongbao"].location != NSNotFound) { // 红包

            NSString *nativeUrl = [[msgWrap m_oWCPayInfoItem] m_c2cNativeUrl];
            nativeUrl = [nativeUrl substringFromIndex:[@"wxpay://c2cbizmessagehandler/hongbao/receivehongbao?" length]];

            NSDictionary *nativeUrlDict = [%c(WCBizUtil) dictionaryWithDecodedComponets:nativeUrl separator:@"&"];

            NSMutableDictionary *args = [[%c(NSMutableDictionary) alloc] init];
            [args setObject:nativeUrlDict[@"msgtype"] forKey:@"msgType"];
            [args setObject:nativeUrlDict[@"sendid"] forKey:@"sendId"];
            [args setObject:nativeUrlDict[@"channelid"] forKey:@"channelId"];
            [args setObject:[selfContact getContactDisplayName] forKey:@"nickName"];
            [args setObject:[selfContact m_nsHeadImgUrl] forKey:@"headImg"];
            [args setObject:nativeUrl forKey:@"nativeUrl"];
            [args setObject:msgWrap.m_nsFromUsr forKey:@"sessionUserName"];

            [[[%c(MMServiceCenter) defaultCenter] getService:[%c(WCRedEnvelopesLogicMgr) class]] OpenRedEnvelopesRequest:args];
        }
    }
}

%end

方才说了,有两个疑难点没有解决:

  • 第一:咱们不晓得 payinfo 是哪里来的,
  • 第二:sessionusername 咱们也不晓得是哪里来的

这时候咱们能够从咱们注入点的参数动手,首先用 logify 打印出 addmsg 办法的参数信息,会发现,它的第二个参数刚好有一个 payinfo 的属性,这样第一个问题迎刃而解了

第二个咱们曾经猜测到它代表群名称,所以咱们从批改几次群名称,而后再察看 logify 打印出的参数值的变动,就能够确认出从哪里取了

通过一番折腾,得出了抢红包的外围代码,再联合下面章节所讲的 theos 制作 tweak 包的办法,打包并装置到手机,发个红包试试,是不是秒抢?


免越狱插件

查看依赖项

如果设施没有越狱,是没有 mobilesubstrate 等环境的,而且一些系统目录是没有读写权限的,这时我么只能从指标 app 的二进制文件动手,通过手动批改 load commands 来加载本人的 dylib,那么下面咱们的插件又是应用 theos 基于 mobilesubstrate 编译的,有没有方法确定咱们的 dylib 有没有依赖其余的库呢?

应用 osx 自带的 otool 工具即可,能够看出,咱们的 lib 是依赖于 substrate 库的,其余的都是零碎库,所以咱们从越狱设施中把 cydiasubstrate 文件 copy 进去重命名为 libsunstrate.dylib,和咱们的 dylib 一起放入 wechat.app 目录中

最初应用 install_name_tool 命令批改动静库的门路把它指向 app 二进制文件的同级目录

制作安装包

解决了依赖问题,而后要把咱们的库注入到二进制 weixin 的二进制文件,这一步应用开源的 insert_dylib 即可(@executable_path 是一个环境变量,指的是二进制文件所在的门路)

insert_dylib 命令格局:./insert_dylib 动静库门路 指标二进制文件

// 注入动静库
./insert_dylib [@executable_path](/user/name/executable_path)/wxmsgpreview.dylib WeChat
// 打包成 ipa
xcrun -sdk iphoneos PackageApplication -v WeChat.app -o ~/WeChat.ipa

最初应用用企业证书或者开发证书签名对 ipa 从新签名,就能够放到本人的渠道进行公布了!


结语

通过综合使用各种工具,进行动态和动态分析,咱们通过实战破解了微信的抢红包逻辑,明确了入侵罕用的工具,下面的抢红包代码还有很多改良之处,比方没有判断红包的发送者是不是本人、也没有判断红包外面的文字是不是抢错三倍,有趣味的童鞋能够尝试优化一下!

正文完
 0