SkillAgentSearch skills...

MMPlugin

微信自动抢红包、防消息撤回、修改运动步数、朋友圈小视频转发等功能(无需越狱),附微信重签名教程

Install / Use

/learn @gaoshilei/MMPlugin
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

2020.1.14更新无需越狱安装

前言

此文为逆向微信二进制文件,实现朋友圈小视频转发的教程,从最开始的汇编代码入手到最后重签名安装等操作,手把手教你玩转微信!学会之后再去逆向微信其他功能易如反掌。
本篇文章由于篇幅太长分成了两篇,上篇讲解的是逆向工作,也就是怎么找到相关的函数和方法实现,下篇讲解的是怎么在非越狱机重签名安装和越狱机tweak安装的详细过程。
正文的第二部分还提供了微信自动抢红包、修改微信步数的代码,这些都可以照葫芦画瓢按照本文的套路一步步逆向找到,这里就不再赘述。
在实践之前,需要准备好一部越狱的手机,然后将下文列出的所有工具安装好。IDA跟Reveal都是破解版,IDA的正版要2000多刀,对于这么牛逼的逆向工具确实物有所值,不过不是专门研究逆向的公司也没必要用正版的,下个Windows的破解版就好,Mac上暂时没找到。Mac上可以用hopper代替IDA,也是一款很牛逼的逆向工具。废话不多说,正式开始吧!

正文

一、获取朋友圈的小视频

注意:本文逆向的微信的二进制文件为6.3.28版本,如果是不同的微信版本,二进制文件中的基地址也不相同

本文涉及到的工具

  1. cycript
  2. LLDB与debugserver(Xcode自带)
  3. OpenSSH
  4. IDA
  5. Reveal
  6. theos
  7. CydiaSubstrate
  8. iOSOpenDev
  9. ideviceinstaller
  10. tcprelay(本地端口映射,USB连接SSH,不映射可通过WiFi连接)
  11. dumpdecrypted
  12. class-dump
  13. iOS App Signer
  14. 编译好的yololib

逆向环境为MacOS + iPhone5S 9.1越狱机
先用dumpdecrypted给微信砸壳(不会的请我写的看这篇教程),获得一个WeChat.decrypted文件,先把这个文件扔到IDA中分析(60MB左右的二进制文件,IDA差不多40分钟才能分析完),用class-dump导出所有头文件

LeonLei-MBP:~ gaoshilei$ class-dump -S -s -H /Users/gaoshilei/Desktop/reverse/binary_for_class-dump/WeChat.decrypted -o /Users/gaoshilei/Desktop/reverse/binary_for_class-dump/class-Header/WeChat

我滴个亲娘!一共有8000个头文件,微信果然工程量浩大!稳定一下情绪,理一理思路继续搞。要取得小视频的下载链接,找到播放视频的View,顺藤摸瓜就能找到小视频的URL。用Reveal查看小视频的播放窗口 Reveal
可以看出来WCContentItemViewTemplateNewSigh这个对象是小视频的播放窗口,它的subView有WCSightView,SightView、SightPlayerView,这几个类就是我们的切入点。 保存视频到favorite的时候是长按视频弹出选项的,那么在WCContentItemViewTemplateNewSight这个类里面可能有手势相关的方法,去刚才导出的头文件中找线索。

- (void)onLongTouch;
- (void)onLongPressedWCSight:(id)arg1;
- (void)onLongPressedWCSightFullScreenWindow:(id)arg1;

这几个方法跟长按手势相关,再去IDA中找到这些函数,逐个查看。onLongPressedWCSight和onLongPressedWCSightFullScreenWindow都比较简单,onLongTouch比较长,而且发现了内部调用了方法Favorites_Add,因为长按视频的时候出来一个选项就是Favorites,并且我看到这个函数调用

ADRP            X8, #selRef_sightVideoPath@PAGE
LDR             X1, [X8,#selRef_sightVideoPath@PAGEOFF]

这里拿到了小视频的地址,可以推测这个函数跟收藏有关,下面打断点测试。

(lldb) im li -o -f
[  0] 0x000000000003c000 /var/mobile/Containers/Bundle/Application/2F1D52EC-C57E-4F95-B715-EF04351232E8/WeChat.app/WeChat(0x000000010003c000)

可以看到WeChat的ASLR为0x3c000,在IDA查找到这三个函数的基地址,分别下断点

(lldb) br s -a 0x1020D3A10+0x3c000
Breakpoint 1: where = WeChat`___lldb_unnamed_symbol110094$$WeChat + 28, address = 0x000000010210fa10
(lldb) br s -a 0x1020D3370+0x3c000
Breakpoint 2: where = WeChat`___lldb_unnamed_symbol110091$$WeChat + 8, address = 0x000000010210f370
(lldb) br s -a 0x1020D33E4+0x3c000
Breakpoint 3: where = WeChat`___lldb_unnamed_symbol110092$$WeChat + 12, address = 0x000000010210f3e4

回到微信里面长按小视频,看断点触发情况

Process 3721 stopped
* thread #1: tid = 0x658fc, 0x000000010210f370 WeChat`___lldb_unnamed_symbol110091$$WeChat + 8, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
    frame #0: 0x000000010210f370 WeChat`___lldb_unnamed_symbol110091$$WeChat + 8
WeChat`___lldb_unnamed_symbol110091$$WeChat:
->  0x10210f370 <+8>:  add    x29, sp, #16              ; =16 
    0x10210f374 <+12>: mov    x19, x0
    0x10210f378 <+16>: adrp   x8, 4968
    0x10210f37c <+20>: ldr    x0, [x8, #744]
(lldb) c
Process 3721 resuming
Process 3721 stopped
* thread #1: tid = 0x658fc, 0x000000010210fa10 WeChat`___lldb_unnamed_symbol110094$$WeChat + 28, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x000000010210fa10 WeChat`___lldb_unnamed_symbol110094$$WeChat + 28
WeChat`___lldb_unnamed_symbol110094$$WeChat:
->  0x10210fa10 <+28>: add    x29, sp, #96              ; =96 
    0x10210fa14 <+32>: sub    sp, sp, #96               ; =96 
    0x10210fa18 <+36>: mov    x19, x0
    0x10210fa1c <+40>: adrp   x8, 4863
……

发现断点2先被触发,接着触发断点1,后面断点2和1又各触发了1次,断点3一直很安静。可以排除onLongPressedWCSightFullScreenWindow与收藏小视频的联系。小视频的踪影就要在剩下的两个方法中寻找了。通过V找到C,顺藤摸瓜找到M屡试不爽!用cycript注入WeChat,拿到播放小视频的view所在的Controller。

cy# [#0x138c18030 nextResponder]
#"<WCTimeLineCellView: 0x138c34620; frame = (0 0; 319 249); tag = 1048577; layer = <CALayer: 0x138362ba0>>"
cy# [#0x138c34620 nextResponder]
#"<UITableViewCellContentView: 0x138223c70; frame = (0 0; 320 256); gestureRecognizers = <NSArray: 0x1384ec480>; layer = <CALayer: 0x138081dc0>>"
cy# [#0x138223c70 nextResponder]
#"<MMTableViewCell: 0x138c9f930; baseClass = UITableViewCell; frame = (0 307; 320 256); autoresize = W; layer = <CALayer: 0x1382dcd10>>"
cy# [#0x138c9f930 nextResponder]
#"<UITableViewWrapperView: 0x137b57800; frame = (0 0; 320 504); gestureRecognizers = <NSArray: 0x1383db660>; layer = <CALayer: 0x138af20c0>; contentOffset: {0, 0}; contentSize: {320, 504}>"
cy# [#0x137b57800 nextResponder]
#"<MMTableView: 0x137b8ae00; baseClass = UITableView; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x138adb590>; layer = <CALayer: 0x138956890>; contentOffset: {0, 99.5}; contentSize: {320, 3193}>"
cy# [#0x137b8ae00 nextResponder]
#"<UIView: 0x138ade5c0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x138ac9990>>"
cy# [#0x138ade5c0 nextResponder]
#"<WCTimeLineViewController: 0x1379eb000>"

通过响应者链条找到 WCContentItemViewTemplateNewSight所属的Controller为WCTimeLineViewController。在这个类的头文件中并没有发现有价值的线索,不过我们注意到小视频所在的view是属于MMTableVIewCell的(见上图Reveal分析图),这是每一个iOS最熟悉的TableView,cell的数据是通过UITableViewDataSource的代理方法- tableView:cellForRowAtIndexPath:赋值的,通过这个方法肯定能知道到M的影子。在IDA中找到[WCTimeLineViewController tableView:cellForRowAtIndexPath:],定位到基地址0x10128B6B0位置:

__text:000000010128B6B0     ADRP     X8, #selRef_genNormalCell_indexPath_@PAGE

这里的函数是WCTimeLineViewController中生成cell的方法,除了这个方法在这个类中还有另外三个生成cell的方法:

- (void)genABTestTipCell:(id)arg1 indexPath:(id)arg2;
- (void)genRedHeartCell:(id)arg1 indexPath:(id)arg2;
- (void)genUploadFailCell:(id)arg1 indexPath:(id)arg2;

通过字面意思可以猜测出normal这个应该是生成小视频cell的方法。继续在IDA中寻找线索

__text:0000000101287CC8     ADRP     X8, #selRef_getTimelineDataItemOfIndex_@PAGE

genNormalCell:IndexPath:方法中发现上面这个方法,可以大胆猜想这个方法是获取TimeLine(朋友圈)数据的方法,那小视频的数据肯定也是通过这个方法获取的,并且IDA可以看到这个方法中调用一个叫做selRef_getTimelineDataItemOfIndex_的方法,获取DataItem貌似就是cell的数据源啊!接下来用LLDB下断点验证猜想。 通过IDA可以找到这个方法对应的基地址为:0x101287CE4,先打印正在运行WeChat的ASLR偏移

LeonLei-MBP:~ gaoshilei$ lldb
(lldb) process connect connect://localhost:1234
(lldb) im li -o -f 
[0] 0x0000000000050000 /var/mobile/Containers/Bundle/Application/2DCE8F30-9B6B-4652-901C-37EB1FF2A40D/WeChat.app/WeChat(0x0000000100050000)

所以我们下断点的位置是0x50000+0x101287CE4

(lldb) br s -a 0x50000+0x101287CE4
Breakpoint 1: where = WeChat`___lldb_unnamed_symbol63721$$WeChat + 252, address = 0x00000001012d7ce4

打印x0的值

(lldb) po $x0
Class name: WCDataItem, addr: 0x15f5f03b0
tid: 12393001887435993280
username: wxid_z8twcz4o18fg12
createtime: 1477360950
commentUsers: (
)
contentObj: <WCContentItem: 0x15f57d000>

得到一个WCDataItem的对象,这里x0的值就是selRef_getTimelineDataItemOfIndex_执行完的返回值,然后把x0的值改掉

(lldb) register write $x0 0
(lldb) c

此时会发现我们要刷新的那条小视频内容全部为空
小视频内容为空
到这里已经找到了小视频的源数据获取方法,问题是我们怎么拿到这个WCDataItem呢?继续看IDA分析函数的调用情况:

WCTimeLineViewController - (void)genNormalCell:(id) indexPath:(id)

__text:0000000101287BCC                 STP             X28, X27, [SP,#var_60]!
__text:0000000101287BD0                 STP             X26, X25, [SP,#0x60+var_50]
__text:0000000101287BD4                 STP             X24, X23, [SP,#0x60+var_40]
__text:0000000101287BD8                 STP             X22, X21, [SP,#0x60+var_30]
__text:0000000101287BDC                 STP             X20, X19, [SP,#0x60+var_20]
__text:0000000101287BE0                 STP             X29, X30, [SP,#0x60+var_10]
__text:0000000101287BE4                 ADD             X29, SP, #0x60+var_10
__text:0000000101287BE8                 SUB             SP, SP, #0x80
__text:0000000101287BEC                 MOV             X19, X3
__text:0000000101287BF0                 MOV             X22, X0
__text:0000000101287BF4                 MOV             W25, #0x100000
__text:0000000101287BF8                 MOVK            W25, #1
__text:0000000101287BFC                 MOV             X0, X2
__text:0000000101287C00                 BL              _objc_retain
__text:0000000101287C04                 MOV             X28, X0
__text:0000000101287C08                 MOV             X0, X19
__text:0000000101287C0C                 BL              _objc_retain
__text:0000000101287C10                 MOV             X20, X0
__text:0000000101287C14                 STR             X20, [SP,#0xE0+var_98]
__text:0000000101287C18                 ADRP            X8, #selRef_row@PAGE
__text:0000000101287C1C                 LDR             X1, [X8,#selRef_row@PAGEOFF]
__text:0000000101287C20                 BL              _objc_msgSend
__text:0000000101287C24                 MOV             X26, X0
__text:0000000101287C28                 ADRP            X8, #selRef_section@PAGE
__text:0000000101287C2C                 LDR             X19, [X8,#selRef_section@PAGEOFF]
__text:0000000101287C30                 MOV             X0, X20
__text:0000000101287C34                 MOV             X1, X19
__text:0000000101287C38                 BL              _objc_msgSend
__text:0000000101287C3C                 STR             X0, [SP,#0xE0+var_A8]
__text:0000000101287C40                 MOV             X0, X20
__text:0000000101287C44                 MOV             X1, X19
__text:0000000101287C48                 BL              _objc_msgSend
__text:0000000101287C4C                 MOV          
View on GitHub
GitHub Stars244
CategoryDevelopment
Updated20d ago
Forks60

Languages

Objective-C

Security Score

100/100

Audited on Mar 7, 2026

No findings