书接上篇,我们来分析打开红包页面
一、分析打开红包页面
1.使用FLEXLoader,分析
找到WCRedEnvelopesReceiveHomeView,使用logify.pl给WCRedEnvelopesReceiveHomeView.h所有函数添加log,打开红包的时候,根据打印信息,定位到OnOpenRedEnvelopes。
二、静态分析汇编代码
1.Mac上用hooper打开微信的二进制文件,搜索WCRedEnvelopesReceiveHomeView OnOpenRedEnvelopes,查看汇编代码
然后根据汇编代码,找到WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes,然后在Xcode搜索,找到3个类都有这个方法,然后打断点,最后定位到WCRedEnvelopesReceiveControlLogic这个类
2.继续在hooper里搜索
WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes,查看汇编代码
根据汇编代码,在WCRedEnvelopesReceiveControlLogic.h里查找m_data这个属性,
@interface WCRedEnvelopesReceiveControlLogic :
WCRedEnvelopesControlLogic
如果没有,就查找它的父类
@interface WCRedEnvelopesControlLogic : WCBizControlLogic {
WCRedEnvelopesControlData *m_data;
}
根据上面的汇编代码,得到下面的代码
id data = MSHookIvar(self, "m_data");
CMessageWrap *msgWrap = [data m_oSelectedMessageWrap];
WCPayInfoItem
*payInfoItem = [msgWrap m_oWCPayInfoItem];
NSString *m_c2cNativeUrl = [payInfoItem m_c2cNativeUrl];
NSLog(@"m_c2cNativeUrl: %@", m_c2cNativeUrl);
NSInteger length = [@"wxpay://c2cbizmessagehandler/hongbao/receivehongbao?" length];
NSString *subStr = [m_c2cNativeUrl substringFromIndex:length];
得到代码
NSDictionary *dic = [%c(WCBizUtil) dictionaryWithDecodedComponets:subStr separator:@"&"];
NSMutableDictionary *myDictionary = [NSMutableDictionary dictionary] ;
[myDictionary setObject:@"1" forKey:@"msgType"];
NSString *sendId = [dic objectForKey:@"sendid"];
[myDictionary setObject:sendId forKey:@"sendId"];
NSString *channelId = [dic objectForKey:@"channelid"];
[myDictionary setObject:channelId forKey:@"channelId"];
CContactMgr *service = [[%c(MMServiceCenter) defaultCenter] getService:[%c(CContactMgr) class]];
CContact *contact = [service getSelfContact];
NSString *displayName = [contact getContactDisplayName];
[myDictionary setObject:displayName forKey:@"nickName"];
NSString *headerUrl = [contact m_nsHeadImgUrl];
[myDictionary setObject:headerUrl forKey:@"headImg"];
NSDictionary * baseInfo = [data m_structDicRedEnvelopesBaseInfo];
NSString *timingIdentifier = [baseInfo objectForKey:@"timingIdentifier"];
if (0 != [timingIdentifier length]){
[myDictionary setObject:timingIdentifier forKey:@"timingIdentifier"];
}
4.继续分析
第一个箭头调用了MMServiceCenter的defaultCenter方法来获取MMServiceCenter实例
第二个箭头调用了WCRedEnvelopesLogicMgr的class方法
第三个箭头调用了第一步获取的MMServiceCenter实例的getService方法,而这个方法是把第二步得到的class作为参数
第四个箭头很明白了吧,第三步得到了WCRedEnvelopesLogicMgr实例,这里就是调用
WCRedEnvelopesLogicMgr实例的OpenRedEnvelopesRequest方法打开红包
WCRedEnvelopesLogicMgr *redEnvelopesLogicMgr = [[MMServiceCenter defaultCenter] getService:[WCRedEnvelopesLogicMgr class]];
[redEnvelopesLogicMgr OpenRedEnvelopesRequest:myDictionary];
最终的抢红包代码合并起来如下:
%hook CMessageMgr
- (void)AsyncOnAddMsg:(NSString *)msg MsgWrap:(CMessageWrap *)wrap {
NSInteger uiMessageType = [wrap m_uiMessageType];
NSString *nsFromUsr = [wrap m_nsFromUsr];
if ( 49 == uiMessageType ){ //红包消息
NSLog(@"收到红包消息");
WCPayInfoItem *payInfoItem = [wrap m_oWCPayInfoItem];
if (payInfoItem == nil) {
NSLog(@"payInfoItem is nil");
}
NSString *m_c2cNativeUrl = [payInfoItem m_c2cNativeUrl];
if (m_c2cNativeUrl == nil) {
NSLog(@"m_c2cNativeUrl is nil");
}
NSInteger length = [@"wxpay://c2cbizmessagehandler/hongbao/receivehongbao?" length];
NSString *subStr = [m_c2cNativeUrl substringFromIndex: length];
NSDictionary *dic = [%c(WCBizUtil) dictionaryWithDecodedComponets:subStr separator:@"&"];
NSMutableDictionary *myDictionary = [NSMutableDictionary dictionary] ;
[myDictionary setObject:@"1" forKey:@"msgType"];
NSString *sendId = [dic objectForKey:@"sendid"];
[myDictionary setObject:sendId forKey:@"sendId"];
NSString *channelId = [dic objectForKey:@"channelid"];
[myDictionary setObject:channelId forKey:@"channelId"];
CContactMgr *service = [[%c(MMServiceCenter) defaultCenter] getService:[%c(CContactMgr) class]];
if (service == nil) {
NSLog(@"service is nil");
}
CContact *contact = [service getSelfContact];
NSString *displayName = [contact getContactDisplayName];
[myDictionary setObject:displayName forKey:@"nickName"];
NSString *headerUrl = [contact m_nsHeadImgUrl];
[myDictionary setObject:headerUrl forKey:@"headImg"];
if (nil != wrap) {
[myDictionary setObject:m_c2cNativeUrl forKey:@"nativeUrl"];
}
[myDictionary setObject:[wrap m_nsFromUsr] forKey:@"sessionUserName"];
}
//%orig;
}
%end
字典中我们少了一个键值对timingIdentifier,我试了一下,没有这个字段会被判定为使用外挂,会封号
5.继续分析WCRedEnvelopesLogicMgr这个类,通过logify查看日志,每次打开红包、抢红包都会调用以下3个方法
%hook WCRedEnvelopesLogicMgr
- (void)OpenRedEnvelopesRequest:(id)arg1{
%log;
%orig;
NSLog(@"OpenRedEnvelopesRequest 开始");
NSLog(@"arg1 = %@", arg1);
NSLog(@"arg1 class = %@", [arg1 class]);
NSLog(@"OpenRedEnvelopesRequest 结束");
}
- (void)ReceiverQueryRedEnvelopesRequest:(id)arg1{
%log;
%orig;
NSLog(@"ReceiverQueryRedEnvelopesRequest 开始");
NSLog(@"arg1 = %@", arg1);
NSLog(@"arg1 class = %@", [arg1 class]);
NSLog(@"ReceiverQueryRedEnvelopesRequest 结束");
}
- (void)OnWCToHongbaoCommonResponse:(id)hongBaoRes Request:(id)hongBaoReq{
%log;
%orig;
NSLog(@"OnWCToHongbaoCommonResponse 结束");
}
打印的顺序为ReceiverQueryRedEnvelopesRequest结束,OpenRedEnvelopesRequest结束,OnWCToHongbaoCommonResponse 结束,OnWCToHongbaoCommonResponse最后调用
OnWCToHongbaoCommonResponse: Request:]
6.继续hook,打印OnWCToHongbaoCommonResponse里的HongBaoRes参数
在这里获得了timingIdentifier
可抢状态:
cgiCmdid = 3 自己可抢 , cgiCmdid = 5 自己已抢过
hbStatus = 2 可抢红包, hbStatus = 4 自己抢过 ,hbStatus=5 过期红包
是否自己发的:
“isSender”:0 别人发的,“isSender”:1 自己发的
是否群红包:
“hbType”:1 群红包,“hbType”:0 个人红包
自己是否抢过
“receiveStatus”:0 未抢过 , “receiveStatus”:2 已抢过
三、通过一番折腾,得出了抢红包的核心代码
1.在AsyncOnAddMsg:MsgWrap:函数中收到uiMessageType=49的红包消息时,调用WCRedEnvelopesLogicMgr的ReceiverQueryRedEnvelopesRequest:方法。
然后在WCRedEnvelopesLogicMgr的回调函数中OnWCToHongbaoCommonResponse: Request:拿到timingIdentifier。
最后调用WCRedEnvelopesLogicMgr的抢红包函数OpenRedEnvelopesRequest。
2.添加抢红包开关,最终效果,在微信设置里打开开关后,微信在前台的情况下,随便哪个页面,都可以自动抢红包了
3.还有特别注意的是,下个绕过越狱检测插件或者自己写绕过越狱检测的逻辑,不然会被微信检测到,可能会被封号
4.如果想iOS免越狱使用这个插件的,请看dylib动态库注入及重签名打包
因为抢红包代码有点多,这里我就不贴出来了,接下来会上传到github,欢迎Star
github地址: https://github.com/xhzth7091/wxredtweak