前言
在 微信抢红包(一) 中我们已经修改了WeChat 的 设置界面了, 那接下来就要实现其功能了。
分析逻辑
我们想要实现其自动抢红包的功能应该从哪里入手呢?
-
首先,我们是不是应该想从聊天的界面入手,找到接收到红包的方法呢??
-
然后对这个方法进行修改呢??
进入 Cycript 调试环境
image.pngUIApp.keyWindow.recursiveDescription.toString()
"function CallbackObject() {\n [native code]\n}"
失败
cy# [[UIApp keyWindow] recursiveDescription].toString()
看到会有很多内容,通过时间 3:38 找到 时间 label 的响应者链,这个聊天界面是谁管理的?
image.png'\u4e0b\u53483:38' unicode转中文 即为 '下午3:38'
image.png也可以用 FLEX 查看,或 Xcode LLDB 调试。
- 查看视图的层次结构
根视图的层次结构
[[UIApp keyWindow].rootViewController _printHierarchy].toString()
如下:
`<MainTabBarViewController 0x107987200>, state: appeared, view: <UILayoutContainerView 0x106f4aea0>
| <MMUINavigationController 0x107808400>, state: appeared, view: <UILayoutContainerView 0x106f68830>
| | <NewMainFrameViewController 0x107807a00>, state: disappeared, view: <MMUIHookView 0x106bea830> not in the window
| | <BaseMsgContentViewController 0x107548000>, state: appeared, view: <UIView 0x113a23710>
| <MMUINavigationController 0x10728f600>, state: disappeared, view: <UILayoutContainerView 0x106ba0050> not in the window
| | <ContactsViewController 0x107306600>, state: disappeared, view: (view not loaded)
| <MMUINavigationController 0x1071b4000>, state: disappeared, view: <UILayoutContainerView 0x106b5a710> not in the window
| | <FindFriendEntryViewController 0x1072eba00>, state: disappeared, view: (view not loaded)
| <MMUINavigationController 0x107a1e400>, state: disappeared, view: <UILayoutContainerView 0x106f99850> not in the window
| | <MoreViewController 0x107a1d600>, state: disappeared, view: (view not loaded)`
接下来主要就是处理 BaseMsgContentViewController 这个类了。
通过 Class-dump 导出的 headers 搜索查看,你会发现:
image.png这有几百个方法,瞬间要疯了!
Thoes->logify 工具
接下来介绍一个处理头文件的工具 Thoes->logify,生成 .xm 文件,Hook 传入类的所有方法。
快捷方式 原身logify 使用
使用前先配置好环境变量,方便在任何地方使用。
image.png根据头文件的路径,输出 HookBaseMsgVC.xm 文件
logify.pl /路径/BaseMsgContentViewController.h > ./HookBaseMsgVC.xm
接着添加至工程中,编译 生成 .mm 资源文件,添加至动态库中,编译,你会发现 N 个错误,因为这里面使用的变量,方法关联了很多个类,找不到定义固然报错,手动处理起来相当麻烦。
另辟蹊径
从上导出了类的所有Hook方法代码,但是依旧很麻烦,解决方法:
-
把 WeChat 的 Headers 全部添加至工程中,这个过程需要一段在时间,这种方法也比较粗暴,笨拙。
-
在项目中的 Config 配置中,修改 Plist 文件添加 BaseMsgContentViewController,即会Hook 这个累的所有方法。
ENABLE 字段值 改为 YES,默认为 NO , CLASS_LIST 添加要 Hook 的类的名称即可,用 Xcode 调试即可看到与添加类相关的方法调用日志。
搜索 Message 跟消息相关的,你会发现这几个方法:
- (void)addMessageNode:(id)arg1 layout:(_Bool)arg2 addMoreMsg:(_Bool)arg3;
- 再次修改 Config 的 plist 文件,因为它可以 Hook 制定类的指定方法。
添加addMessageNode:layout:addMoreMsg:
- 进入聊天界面时,调用的,有多少条消息就调用多少次
- (void)addMessageNode:(id)arg1 layout:(_Bool)arg2 addMoreMsg:(_Bool)arg3;
接下来就 Hook 这个方法:
#pragma mark -- 逻辑分析
//微信应该有一个专门管理消息的对象
// 即时通讯中的多播代理,就是发现消息以后找到合适的代理对象,代理对象是一个数组,将这个消息发送给对应的对象。
// 顺藤摸瓜:看这个函数到底是谁调用的?看函数调用栈
%hook BaseMsgContentViewController
//进入聊天界面时,调用的,有多少条消息就调用多少次
- (void)addMessageNode:(id)arg1 layout:(_Bool)arg2 addMoreMsg:(_Bool)arg3
{
%orig;
// %log;
}
但是你会发现方法名称什么都没有了,查看函数调用栈 是逆向中经常要用到的也是必要的。
因为符号表没有了,接下来就要恢复符号表。
image.png恢复符号表
下载 restore-symbol项目,用xcode 编译一下(试了编译和运行没成功),或者用终端
make restore-symbol
生成 restore-symbol 的 Mach-o 可执行文件。
接下来就用这个 对原始项目中的 Mach-o 文件进行恢复。
要想恢复这个符号表, Mach-o 文件 必须是单一架构的,不能是通用架构的。
查看架构
lipo -info WeChat
拆分 arm64 架构的
image.pnglipo WeChat -thin arm64 -output WeChat_Arm64
恢复 Mach-o 文件
image.png/restore-symbol WeChat_Arm64 -o WeChat2
将恢复好的 Mach-o 文件拷贝至原始项目的APP 包中替换掉原来的 Mach-o 文件。
重新运行,调试,可以看到函数的调用栈了,如下:
image.png当接收到新消息时的调用栈信息:
image.png image.png继续分析找到红包消息
通过上面符号表的恢复可以看到调用的函数,接下来 Hook 这几个函数:
%hook BaseMsgContentLogicController
- (void)DidAddMsg:(id)arg1
{
%orig;
}
- (void)OnAddMsg:(id)arg1 MsgWrap:(id)arg2
{
%orig;
}
%end
%hook CMessageMgr
- (void)MainThreadNotifyToExt:(id)arg1
{
%orig;
}
%end
通过调试可以发现只要收到消息都会调用 CMessageMgr—> MainThreadNotifyToExt 这个方法,但并不能判定这个就是接受消息的方法。
所以接下来 hook CMessageMgr,查看调用的方法:
image.pngonNewSyncAddMessage 这个方法看着挺像的,Hook 一下试试;
image.png发送的消息依次为:系统表情、添加的表情、图片、文字。
可以看到,进入聊天界面时是不会调用的,只有在收到新消息时才会调用,无论在后台还是前台,这样基本上就满足了我们的要求了。
通过分析找到红包消息的 type 为 49
if(type == 49) {
抢红包的逻辑
}
部分 type 值,其它的可以探索一下:
Type 值 | 消息类型 |
---|---|
1 | 系统表情或文字 |
3 | 图片 |
34 | 语音消息 |
47 | 添加的表情 |
49 | 红包消息/文件 |
通过界面动态分析定位到抢红包的方法
打开抢红包的界面,进入 Xcode 调试,查看:
image.pngCycript 调试
这种方法有的时候,不太好用,那还可以用 Cycript 进行调试,找到抢红包触发的方法:
[[UIApp keyWindow] recursiveDescription].toString()
- 搜索 名称,中文的话转为 Unicode 码再进行搜索(修改前加#)。
http://www.bejson.com/convert/unicode_chinese/
image.png尝试修改一下,确定找的对不对
0x1399df400.text=@"Superman"
- 找到它的响应者
image.png0x1399df400.nextResponder
- 查看一下他的子视图
0x1399bfcc0.subviews 可能失败。
image.png[#0x1399bfcc0 subviews]
- 上面可以看到有两个 Button,找到红包 按钮的 Target.
image.png0x1167a25e0.allTargets
可以看到是这个类 WCRedEnvelopesReceiveHomeView,接着进入 Headers 搜索。
image.png就这么多方法,可以看一下
- 调用抢红包的方法 ** OnOpenRedEnvelopes**
image.png[#0x1167a25e0 OnOpenRedEnvelopes]
调用成功,OK,不过可能会调用失败。
思考一下
至此手动调用抢红包已经成功,是不是已经完事了呢?
这个过程是复杂的,需要进入聊天界面,点开红包页面,才能调到这个方法,是不是太笨了,太绕了,这样和我们自己抢有何区别呢???
跟我们的需求差十万八千里呢!!!我们要的自动抢红包,而不需要这么麻烦的步骤。
接下来就要换一种思路了
静态分析 OnOpenRedEvelopes
通过 IDA 静态分析 WCRedEnvelopesReceiveHomeView 的 OnOpenRedEvelopes 方法:
汇编代码如下:
text:0000000100440BE8
__text:0000000100440BEC
__text:0000000100440BEC ; =============== S U B R O U T I N E =======================================
__text:0000000100440BEC
__text:0000000100440BEC ; Attributes: bp-based frame
__text:0000000100440BEC
__text:0000000100440BEC ; void __cdecl -[WARedEnvelopesReceiveHomeView OnOpenRedEnvelopes](WARedEnvelopesReceiveHomeView *self, SEL)
__text:0000000100440BEC __WARedEnvelopesReceiveHomeView_OnOpenRedEnvelopes_
__text:0000000100440BEC SUB SP, SP, #0x70
__text:0000000100440BF0 STP X24, X23, [SP,#0x30]
__text:0000000100440BF4 STP X22, X21, [SP,#0x40]
__text:0000000100440BF8 STP X20, X19, [SP,#0x50]
__text:0000000100440BFC STP X29, X30, [SP,#0x60]
__text:0000000100440C00 ADD X29, SP, #0x60
__text:0000000100440C04 MOV X19, X0
__text:0000000100440C08 ADRP X8, #_OBJC_IVAR_$_WARedEnvelopesReceiveHomeView.m_dicBaseInfo@PAGE
__text:0000000100440C0C LDRSW X24, [X8,#_OBJC_IVAR_$_WARedEnvelopesReceiveHomeView.m_dicBaseInfo@PAGEOFF] ; NSDictionary *m_dicBaseInfo;
__text:0000000100440C10 LDR X0, [X19,X24]
__text:0000000100440C14 ADRP X8, #selRef_objectForKey_@PAGE
__text:0000000100440C18 LDR X20, [X8,#selRef_objectForKey_@PAGEOFF]
__text:0000000100440C1C ADRP X2, #cfstr_Issender_1@PAGE
__text:0000000100440C20 ADD X2, X2, #cfstr_Issender_1@PAGEOFF ; "isSender"
__text:0000000100440C24 MOV X1, X20
__text:0000000100440C28 BL _objc_msgSend
__text:0000000100440C2C MOV X29, X29
__text:0000000100440C30 BL _objc_retainAutoreleasedReturnValue
__text:0000000100440C34 MOV X21, X0
__text:0000000100440C38 ADRP X8, #selRef_intValue@PAGE
__text:0000000100440C3C LDR X22, [X8,#selRef_intValue@PAGEOFF]
__text:0000000100440C40 MOV X1, X22
__text:0000000100440C44 BL _objc_msgSend
__text:0000000100440C48 MOV X23, X0
__text:0000000100440C4C MOV X0, X21
__text:0000000100440C50 BL _objc_release
__text:0000000100440C54 LDR X0, [X19,X24]
__text:0000000100440C58 ADRP X2, #cfstr_Hbtype_1@PAGE
__text:0000000100440C5C ADD X2, X2, #cfstr_Hbtype_1@PAGEOFF ; "hbType"
__text:0000000100440C60 MOV X1, X20
__text:0000000100440C64 BL _objc_msgSend
__text:0000000100440C68 MOV X29, X29
__text:0000000100440C6C BL _objc_retainAutoreleasedReturnValue
__text:0000000100440C70 MOV X20, X0
__text:0000000100440C74 MOV X1, X22
__text:0000000100440C78 BL _objc_msgSend
__text:0000000100440C7C MOV X21, X0
__text:0000000100440C80 MOV X0, X20
__text:0000000100440C84 BL _objc_release
__text:0000000100440C88 ADRP X8, #classRef_NSString@PAGE
__text:0000000100440C8C LDR X0, [X8,#classRef_NSString@PAGEOFF]
__text:0000000100440C90 ADD W8, W21, #1
__text:0000000100440C94 CMP W23, #0
__text:0000000100440C98 MOV W9, #1
__text:0000000100440C9C CINC W9, W9, LE
__text:0000000100440CA0 ADRP X10, #selRef_stringWithFormat_@PAGE
__text:0000000100440CA4 LDR X1, [X10,#selRef_stringWithFormat_@PAGEOFF]
__text:0000000100440CA8 ADRP X10, #stru_10390DD08@PAGE
__text:0000000100440CAC ADD X10, X10, #stru_10390DD08@PAGEOFF
__text:0000000100440CB0 MOV W11, #2
__text:0000000100440CB4 STP X11, X10, [SP,#0x20]
__text:0000000100440CB8 STP X9, XZR, [SP,#0x10]
__text:0000000100440CBC MOV W9, #5
__text:0000000100440CC0 STP X9, X8, [SP]
__text:0000000100440CC4 ADRP X2, #cfstr_UUUUU_1@PAGE
__text:0000000100440CC8 ADD X2, X2, #cfstr_UUUUU_1@PAGEOFF ; "%u,%u,%u,%u,%u,%@"
__text:0000000100440CCC BL _objc_msgSend
__text:0000000100440CD0 MOV X29, X29
__text:0000000100440CD4 BL _objc_retainAutoreleasedReturnValue
__text:0000000100440CD8 MOV X20, X0
__text:0000000100440CDC MOV W0, #0x2DB5
__text:0000000100440CE0 MOV X1, X20
__text:0000000100440CE4 MOV W2, #0
__text:0000000100440CE8 MOV W3, #0
__text:0000000100440CEC BL sub_102E21B7C
__text:0000000100440CF0 ADRP X8, #_OBJC_IVAR_$_WARedEnvelopesReceiveHomeView.m_delegate@PAGE
__text:0000000100440CF4 LDRSW X8, [X8,#_OBJC_IVAR_$_WARedEnvelopesReceiveHomeView.m_delegate@PAGEOFF] ; WCRedEnvelopesReceiveHomeViewDelegate *m_delegate;
__text:0000000100440CF8 ADD X0, X19, X8
__text:0000000100440CFC BL _objc_loadWeakRetained
__text:0000000100440D00 MOV X19, X0
__text:0000000100440D04 ADRP X8, #selRef_WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes@PAGE
__text:0000000100440D08 LDR X1, [X8,#selRef_WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes@PAGEOFF]
__text:0000000100440D0C BL _objc_msgSend
__text:0000000100440D10 MOV X0, X19
__text:0000000100440D14 BL _objc_release
__text:0000000100440D18 MOV X0, X20
__text:0000000100440D1C LDP X29, X30, [SP,#0x60]
__text:0000000100440D20 LDP X20, X19, [SP,#0x50]
__text:0000000100440D24 LDP X22, X21, [SP,#0x40]
__text:0000000100440D28 LDP X24, X23, [SP,#0x30]
__text:0000000100440D2C ADD SP, SP, #0x70
__text:0000000100440D30 B _objc_release
__text:0000000100440D30 ; End of function -[WARedEnvelopesReceiveHomeView OnOpenRedEnvelopes]
__text:0000000100440D30
Hook OnOpenRedEvelopes 这个方法:
- (void)OnOpenRedEnvelopes
{
// self->m_dicBaseInfo;
// 1. 拿到成员变量 m_dicBaseInfo
NSDictionary *dict = MSHookIvar<NSDictionary *>(self, "m_dicBaseInfo");
// 打印字典
NSArray *allKeys = [dict allKeys];
for (int i = 0; i < allKeys.count; i++){
NSLog(@"Key:%@ ———— Value:%@",allKeys[i],[dict objectForKey:allKeys[i]]);
}
// 2. 获取 Delegate
id delegate = MSHookIvar<id>(self, "m_delegate");
NSLog(@"DelegateClass——%@",[delegate class]);
}
点击抢红包传入的参数:
image.png修改代码,调用抢红包方法:
// 获取代理调用方法
WeChatDelegate *delegate = MSHookIvar<WeChatDelegate *>(self, "m_delegate");
[delegate WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes];
抢红包调用成功,这就恢复了抢红包的代码。
调用成功接下来要继续寻找核心方法,这里只是调用前的参数、代理准备工作。
静态分析二
通过上面的分析,找到了这个关键的方法 WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes;这个方法又是代理 WCRedEnvelopesReceiveControlLogic 调用的方法。
继续用 IDA 分析搜索这个方法
WCRedEnvelopesReceiveControlLogic 头文件定义
@interface WCRedEnvelopesReceiveControlLogic : WCRedEnvelopesControlLogic <WCBaseControlLogicDeleagte, WCBaseControlMgrExt, WCRedEnvelopesReceiveHomeViewDelegate, WCRedEnvelopesRedEnvelopesDetailViewControllerDelegate, WCRedEnvelopesEnterpriseDetailViewControllerDelegate, WCRedEnvelopesSessionSelectViewControllerDelegate, WCRedEnvelopesMultiSelectContactsViewControllerDelegate>
{
int m_scene;
WCRedEnvelopesReceiveHomeView *introView;
}
......
- (void)WCRedEnvelopesRedEnvelopesDetailViewControllerContinueSendRedEnvelopes;
- (void)WCRedEnvelopesRedEnvelopesDetailViewControllerBack;
- (void)WCRedEnvelopesEnterpriseDetailViewControllerContinueSendRedEnvelopes;
- (void)WCRedEnvelopesEnterpriseDetailViewControllerBack;
- (void)WCRedEnvelopesReceiveHomeViewOpenList;
- (void)WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes;
- (void)WCRedEnvelopesReceiveHomeViewBack;
- (void)showReceivedAndOutOfDataRedEnvelopesIntroView;
- (void)queryRedEnvelopesDetailRequest:(id)arg1;
- (_Bool)isRedEnvelopesHasBeenReceivedAndOutOfDate:(id)arg1;
- (_Bool)isRedEnvelopesHasBeenReceivedAndNotOutOfDate:(id)arg1;
- (void)startLogic;
- (void)stopLoading;
- (id)initWithData:(id)arg1 Scene:(int)arg2;
WCRedEnvelopesReceiveControlLogic 父类 WCRedEnvelopesControlLogic 定义:
#import "WCBizControlLogic.h"
#import "WCRedEnvelopesLogicMgrExt-Protocol.h"
@class NSString, WCRedEnvelopesControlData;
@interface WCRedEnvelopesControlLogic : WCBizControlLogic <WCRedEnvelopesLogicMgrExt>
{
WCRedEnvelopesControlData *m_data;
}
- (void).cxx_destruct;
- (void)OnWCRedEnvBizBaseRequestCommonSystemError:(id)arg1 HBCmdType:(int)arg2;
- (void)OnWCRedEnvBizBaseRequestCommonError:(id)arg1 HBCmdType:(int)arg2;
- (void)OnWCRedEnvEnterpriseBaseRequestCommonSystemError:(id)arg1 HBCmdType:(int)arg2;
- (void)OnWCRedEnvEnterpriseBaseRequestCommonError:(id)arg1 HBCmdType:(int)arg2;
- (void)OnWCRedEnvelopesBaseRequestCommonSystemError:(id)arg1 HongbaoCmdType:(int)arg2;
- (void)OnWCRedEnvelopesBaseRequestCommonError:(id)arg1 HongbaoCmdType:(int)arg2;
- (_Bool)onNeedToControlCurrentPublicError;
- (_Bool)onError:(id)arg1;
- (void)onErrorAlertViewDismiss:(id)arg1;
- (void)onErrorAlertViewStopLogic:(id)arg1;
- (_Bool)OnCheckDismissCurrentViewControllerAndStopLogicAfterDismiss;
- (_Bool)OnCheckDismissCurrentViewControllerAndStopLogicBeforeDismiss;
- (void)stopLoading;
- (void)startWCPayLoading;
- (void)startLoading;
- (void)stopLogic;
- (void)pause;
- (void)resume;
- (void)dealloc;
- (id)initWithData:(id)arg1;
- (id)init;
// Remaining properties
@property(readonly, copy) NSString *debugDescription;
@property(readonly, copy) NSString *description;
@property(readonly) unsigned long long hash;
@property(readonly) Class superclass;
@end
可以看到 成员变量 WCRedEnvelopesControlData *m_data 比较关键的,WCRedEnvelopesControlData 的定义:
#import <objc/NSObject.h>
@class CContact, CMessageWrap, NSDictionary, NSMutableArray, NSMutableDictionary, NSString, WCPayRealnameGuideInfo, WCRedEnvelopesAtomicInfo, WCRedEnvelopesDetailInfo, WCRedEnvelopesHistoryInfo, WCRedEnvelopesOperationInfo, WCRedEnvelopesReceivedRedEnvelopesInfo, WCRedEnvelopesSendedRedEnvelopesInfo;
@interface WCRedEnvelopesControlData : NSObject
{
NSDictionary *m_dicPrepayRequestOrderInfo;
NSMutableArray *m_arrSelectedSendRedEnvelopesUserList;
CMessageWrap *m_oSelectedMessageWrap;
CContact *m_oSelectContact;
WCRedEnvelopesDetailInfo *m_oWCRedEnvelopesDetailInfo;
WCRedEnvelopesHistoryInfo *m_oWCRedEnvelopesHistoryInfo;
WCRedEnvelopesReceivedRedEnvelopesInfo *m_oSelectedWCRedEnvelopesReceivedRedEnvelopesInfo;
WCRedEnvelopesSendedRedEnvelopesInfo *m_oSelectedWCRedEnvelopesSendedRedEnvelopesInfo;
WCRedEnvelopesAtomicInfo *m_oWCRedEnvelopesAtomicInfo;
WCRedEnvelopesOperationInfo *m_oWCRedEnvelopesOpTail;
NSString *m_nsWCRedEnvelopesBrandMessageNativeUrl;
NSString *m_nsSendID;
NSString *m_nsOpenBundleId;
NSDictionary *m_dicOpenApiParam;
NSDictionary *m_structDicRedEnvelopesUserInfo;
NSDictionary *m_structDicPrepayOrderInfo;
NSDictionary *m_structDicRedEnvelopesBaseInfo;
NSMutableDictionary *m_structDicRedEnvelopesCompleteInfo;
NSDictionary *m_structDicAfterOpenRedEnvelopesInfo;
WCPayRealnameGuideInfo *realnameGuideInfo;
NSDictionary *m_structDicEnterpriseRedEnvelopesData;
}
@property(retain, nonatomic) NSDictionary *m_structDicEnterpriseRedEnvelopesData; // @synthesize m_structDicEnterpriseRedEnvelopesData;
@property(retain, nonatomic) WCPayRealnameGuideInfo *realnameGuideInfo; // @synthesize realnameGuideInfo;
@property(retain, nonatomic) NSDictionary *m_dicOpenApiParam; // @synthesize m_dicOpenApiParam;
@property(retain, nonatomic) NSString *m_nsSendID; // @synthesize m_nsSendID;
@property(retain, nonatomic) NSString *m_nsOpenBundleId; // @synthesize m_nsOpenBundleId;
@property(retain, nonatomic) NSString *m_nsWCRedEnvelopesBrandMessageNativeUrl; // @synthesize m_nsWCRedEnvelopesBrandMessageNativeUrl;
@property(retain, nonatomic) WCRedEnvelopesOperationInfo *m_oWCRedEnvelopesOpTail; // @synthesize m_oWCRedEnvelopesOpTail;
@property(retain, nonatomic) WCRedEnvelopesAtomicInfo *m_oWCRedEnvelopesAtomicInfo; // @synthesize m_oWCRedEnvelopesAtomicInfo;
@property(retain, nonatomic) WCRedEnvelopesSendedRedEnvelopesInfo *m_oSelectedWCRedEnvelopesSendedRedEnvelopesInfo; // @synthesize m_oSelectedWCRedEnvelopesSendedRedEnvelopesInfo;
@property(retain, nonatomic) WCRedEnvelopesReceivedRedEnvelopesInfo *m_oSelectedWCRedEnvelopesReceivedRedEnvelopesInfo; // @synthesize m_oSelectedWCRedEnvelopesReceivedRedEnvelopesInfo;
@property(retain, nonatomic) WCRedEnvelopesHistoryInfo *m_oWCRedEnvelopesHistoryInfo; // @synthesize m_oWCRedEnvelopesHistoryInfo;
@property(retain, nonatomic) WCRedEnvelopesDetailInfo *m_oWCRedEnvelopesDetailInfo; // @synthesize m_oWCRedEnvelopesDetailInfo;
@property(retain, nonatomic) NSMutableDictionary *m_structDicRedEnvelopesCompleteInfo; // @synthesize m_structDicRedEnvelopesCompleteInfo;
@property(retain, nonatomic) NSDictionary *m_structDicRedEnvelopesBaseInfo; // @synthesize m_structDicRedEnvelopesBaseInfo;
@property(retain, nonatomic) NSDictionary *m_structDicAfterOpenRedEnvelopesInfo; // @synthesize m_structDicAfterOpenRedEnvelopesInfo;
@property(retain, nonatomic) CMessageWrap *m_oSelectedMessageWrap; // @synthesize m_oSelectedMessageWrap;
@property(retain, nonatomic) NSDictionary *m_structDicRedEnvelopesUserInfo; // @synthesize m_structDicRedEnvelopesUserInfo;
@property(retain, nonatomic) NSDictionary *m_structDicPrepayOrderInfo; // @synthesize m_structDicPrepayOrderInfo;
@property(retain, nonatomic) NSMutableArray *m_arrSelectedSendRedEnvelopesUserList; // @synthesize m_arrSelectedSendRedEnvelopesUserList;
@property(retain, nonatomic) CContact *m_oSelectContact; // @synthesize m_oSelectContact;
@property(retain, nonatomic) NSDictionary *m_dicPrepayRequestOrderInfo; // @synthesize m_dicPrepayRequestOrderInfo;
- (void).cxx_destruct;
@end
其中对我们目前比较关键的则是 m_oSelectedMessageWrap ,从汇编代码中可以看出调用的 m_oSelectedMessageWrap Get 方法,返回 ** CMessageWrap** 类型。
接着编写 **WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes ** 这个方法的伪代码:
汇编分析:
// 汇编分析调用过程
//WCRedEnvelopesControlData *m_data = self.m_data;
//// 相当于调用 Get 方法
//CMessageWrap *mesWrap = [m_data m_oSelectedMessageWrap];
//// 相当于调用 Get 方法
//WCPayInfoItem *infoItem = [mesWrap m_oWCPayInfoItem];
////
//NSString *m_Url = [infoItem m_c2cNativeUrl];
手动实现 上面 抢红包前的准备过程
%hook WCRedEnvelopesReceiveControlLogic
- (void)WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes
{
id data = MSHookIvar<WCRedEnvelopesControlData *>(self, "m_data");
NSLog(@"DataClass----%@",[data class]);
id mesWrap = MSHookIvar<CMessageWrap *>(data, "m_oSelectedMessageWrap");
NSLog(@"MesWarpClass----%@",[mesWrap class]);
// 相当于调用 Get 方法
WCPayInfoItem *infoItem = [mesWrap m_oWCPayInfoItem];
//
NSString *m_Url = [infoItem m_c2cNativeUrl];
NSLog(@"返回的 URL--%@",m_Url);
// URL 处理 拼接参数,做真正抢红包的准备
}
结果如下:
image.png
网友评论