前言
我们继续之前的29-项目实战(1),接着破解分析拆红包的相关逻辑。
一、IDA初使用
IDA是windows平台上的反编译插件,如果在mac电脑上使用,首先得装个虚拟机,虚拟机上安装windows操作系统,现成的软件有Parallels Desktop,可自行百度搜索安装。安装完成后,打开微信的Mach-O二进制文件👇🏻


⚠️注意:恢复符号表,这个时间段会很长(可能
3h以上),我们等待就行。

二、静态分析拆红包
在静态分析之前,我们应该知道,Wechat的二进制文件是去符号的,即很多OC的方法被干掉了,因此需要恢复,这样对IDA反编译也有很大的帮助,此时我们可以使用Monkey来做恢复符号这项工作。
2.1 Monkey恢复符号演示
其实很简单,就是修改Monkey的配置项👇🏻



恢复符号后的app包,再把里面的Mach-O文件丢给IDA进行反编译。
2.2 开始静态分析
目前,我们定位到拆红包的方法是OnOpenRedEnvelopes,这是一个实例方法,而且这个实例是个view(WCRedEnvelopesReceiveHomeView),那么触发它就必须有个前提 👉🏻 模拟构造一个WCRedEnvelopesReceiveHomeView对象,很显然,这么做会很难。
我们只有想另外一条途径 👇🏻
OnOpenRedEnvelopes内部的逻辑是什么?
我们只要能弄清楚拆红包的内部做的事情,然后将这个逻辑写到CheckMessageStatus:Msg方法中,不就等于自动拆红包了么。那么接下来的重点 👉🏻 反汇编OnOpenRedEnvelopes内部的逻辑。
- 打开反汇编完成后的ida文件,搜索
OnOpenRedEnvelopes👇🏻

-
WARedEnvelopesReceiveHomeView头文件👇🏻

-
WCRedEnvelopesReceiveHomeView头文件👇🏻

可见,WARedEnvelopesReceiveHomeView和WCRedEnvelopesReceiveHomeView大部分的属性和方法都一样,WA这个应该是旧版本的红包View类,里面的属性没有WC的多。
- 分析汇编代码👇🏻



以上,其实分析下来,流程不怎么难,即获取一个字典m_dicBaseInfo,获取key分别是isSender和hbType的value,再拿到m_delegate对象,调用其WCRedEnvelopesReceiveHomeViewOpenRedEnvelope方法。
三、动态调试拆红包
接下来,我们通过logos语法,hookWCRedEnvelopesReceiveHomeView中的上面的关键信息,打印看看具体有什么。
- 成员变量
m_dicBaseInfo和m_delegate👇🏻

- 编写logos代码👇🏻
⚠️注意:针对成员变量的获取方式 👉🏻
MSHookIvar
首先要声明一下类
@interface WCRedEnvelopesReceiveHomeView
{
id m_delegate;// 具体delegate不需要指明
NSDictionary *m_dicBaseInfo;
}
@end
然后hook拆红包方法,我们在拆的时机点,打印信息
%hook WCRedEnvelopesReceiveHomeView
- (void)OnOpenRedEnvelopes {
// BaseInfo
NSDictionary *dict = MSHookIvar<NSDictionary *>(self, "m_dicBaseInfo");
NSArray *keys = [dict allKeys];
for (int i = 0; i < keys.count; i++) {
NSLog(@"%@ : %@", keys[i], [dict objectForKey:keys[i]]);
}
// delegate
id delegate = MSHookIvar<id>(self, "m_delegate");
NSLog(@"delegateClass:%@", [delegate class]);
%orig;
}
%end
- 编译安装,接收一个红包消息,点击
拆开,查看控制台输出👇🏻

上图可见,m_dicBaseInfo中的信息就是红包相关的信息,m_delegate的类就是WCRedEnvelopesReceiveControlLogic,那么拆红包最终就是调用WCRedEnvelopesReceiveControlLogic类的方法WCRedEnvelopesReceiveHomeViewOpenRedEnvelope。
四、静态分析delegate
接下来,我们静态分析下WCRedEnvelopesReceiveControlLogic的WCRedEnvelopesReceiveHomeViewOpenRedEnvelope方法👇🏻

我们去WCRedEnvelopesReceiveControlLogic.h头文件中看看👇🏻

果然有带参数的方法,且参数类型是id类型👇🏻
- (void)WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes:(id)arg1;
那么,我们可以理解它的执行流程 的伪代码就是👇🏻
- (void)WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes {
[self WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes:0];
}
接着继续分析带参数的WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes👇🏻


接着我们看看m_data是什么👇🏻

m_data的类是WCRedEnvelopesControlData。那么上面的流程伪代码可以这么写👇🏻
- (void)WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes:(id)arg1 {
[self reportReveiveHomeViewEmoticon];
WCRedEnvelopesControlData *data = self.m_data;
[data m_oSelectedMessageWrap];
}
继续,看看WCRedEnvelopesControlData类的m_oSelectedMessageWrap方法👇🏻

m_oSelectedMessageWrap是一个属性,类是CMessageWrap。

接着看CMessageWrap👇🏻

m_oWCPayInfoItem也是一个属性,类是WCPayInfoItem,继续👇🏻

果然,m_c2cNativeUrl也是一个属性。
综上,完善上面的伪代码👇🏻
- (void)WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes:(id)arg1 {
[self reportReveiveHomeViewEmoticon];
WCRedEnvelopesControlData *data = self.m_data;
CMessageWrap *msgWrap = [data m_oSelectedMessageWrap];
WCPayInfoItem *payInfoItem = [msgWrap m_oWCPayInfoItem];
NSString *url = [payInfoItem m_c2cNativeUrl];
}
五、动态调试delegate
还是一样,根据上面的伪代码,接下来我们动态调试一下👇🏻
- 编写logos hook代码👇🏻
// 声明需要的类及属性
@interface WCPayInfoItem
@property(retain, nonatomic) NSString *m_c2cNativeUrl;
@end
@interface CMessageWrap
@property(retain, nonatomic) WCPayInfoItem *m_oWCPayInfoItem;
@end
@interface WCRedEnvelopesControlData
@property(retain, nonatomic) CMessageWrap *m_oSelectedMessageWrap;
@end
%hook WCRedEnvelopesReceiveControlLogic
- (void)WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes:(id)arg1 {
// 这个流程是UIView相关的,不是拆红包的重点,可以注释掉
// [self reportReveiveHomeViewEmoticon];
// 不能直接.m_data获取,可通过MSHookIvar这种方式获取
// WCRedEnvelopesControlData *data = self.m_data;
WCRedEnvelopesControlData *data = MSHookIvar<WCRedEnvelopesControlData *>(self, "m_data");
// 以下3句可以简化成1句
// CMessageWrap *msgWrap = [data m_oSelectedMessageWrap];
// WCPayInfoItem *payInfoItem = [msgWrap m_oWCPayInfoItem];
// NSString *url = [payInfoItem m_c2cNativeUrl];
NSString *url = data.m_oSelectedMessageWrap.m_oWCPayInfoItem.m_c2cNativeUrl;
NSLog(@"m_c2cNativeUrl:%@", url);
// 也不需要继续走原有的流程,这样就不会真正的“拆”红包了
// %orig;
}
%end
- 编译安装,接收红包消息,查看控制台信息👇🏻

m_c2cNativeUrl:wxpay://c2cbizmessagehandler/hongbao/receivehongbao?msgtype=1&channelid=1&sendid=1000039901202108267308122328105&sendusername=Aron1101&ver=6&sign=39c4f82a43ecd7ae7154169e7c69ff70c71e43a1ace7bb9b9b35486c18e99b302cece5fa7544a479021db71856a3936182bc6dc7cf1d86267cbfba952b67bd4673e4751447d5bb1c76b2a52c7e7e32a1
我们拿到了url,其中包含有签名信息sign。
- 我们继续往下静态分析
- (void)WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes:(id)arg1剩下的汇编代码流程👇🏻

-
cfstr_WxpayC2cbizmes
其实只需看WxpayC2cbizmes,我们可以直接鼠标点进去查看👇🏻


可见,cfstr_WxpayC2cbizmes其实是个简化字符串,即👇🏻
wxpay://c2cbizmessagehandler/hongbao/receivehongbao?
和前面控制台打印输出的url的前半部分一模一样,再回过头看汇编,就能明白cfstr_WxpayC2cbizmes那块处理做的事情👇🏻


至此,我们分析到截取wxpay://c2cbizmessagehandler/hongbao/receivehongbao?之后,得到的子串👇🏻
msgtype=1&channelid=1&sendid=1000039901202108267308122328105&sendusername=Aron1101&ver=6&sign=39c4f82a43ecd7ae7154169e7c69ff70c71e43a1ace7bb9b9b35486c18e99b302cece5fa7544a479021db71856a3936182bc6dc7cf1d86267cbfba952b67bd4673e4751447d5bb1c76b2a52c7e7e32a1
总结
本篇文章,使用IDA逆向软件,针对WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes,通过静态分析汇编代码,加上hook动态调试打印关键信息,一步步得到关键的字串。
我们先告一段落,后面文章将继续讲解WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes的重点 👉🏻 31-项目实战(3)还原红包方法。