微信抢红包(三)
前言
在 微信抢红包(二) 中,我们已经知道了调用 抢红包时返回的 URL,如下:
![](https://img.haomeiwen.com/i4790087/532524a4f2427612.png)
继续分析
通过 微信抢红包(二) 中的分析,看到了 IDA 分析的汇编代码,但是 IDA还有一个强大的功能,就是可以还原源码,快捷键 F5 , 还原后的 WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes 方法如下:(删除部分定义和release),这样看起来就清爽多了,容易分析多了
... 定义
void __cdecl -[WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes](#9116 *self, SEL a2)
{
v2 = self;
v3 = objc_msgSend(*(void **)((char *)self + 57), "m_oSelectedMessageWrap");
v4 = (void *)objc_retainAutoreleasedReturnValue(v3);
v5 = v4;
v6 = objc_msgSend(v4, "m_oWCPayInfoItem");
v7 = (void *)objc_retainAutoreleasedReturnValue(v6);
v8 = v7;
v9 = objc_msgSend(v7, "m_c2cNativeUrl");
v10 = (void *)objc_retainAutoreleasedReturnValue(v9);
v11 = objc_msgSend(CFSTR("wxpay://c2cbizmessagehandler/hongbao/receivehongbao?"), "length");
v12 = objc_msgSend(v10, "substringFromIndex:", v11);
v13 = (struct objc_object *)objc_retainAutoreleasedReturnValue(v12);
objc_release(v10);
objc_release(v8);
objc_release(v5);
v90 = v13;
v14 = ((id (__cdecl *)(#9596 *, SEL, id, id))objc_msgSend)(
(#9596 *)&OBJC_CLASS___WCBizUtil,
"dictionaryWithDecodedComponets:separator:",
v13,
(id)CFSTR("&"));
v15 = (void *)objc_retainAutoreleasedReturnValue(v14);
v16 = objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "dictionary");
v17 = (void *)objc_retainAutoreleasedReturnValue(v16);
objc_msgSend(v17, "safeSetObject:forKey:", CFSTR("1"), CFSTR("msgType"));
v18 = objc_msgSend(v15, "objectForKey:", CFSTR("sendid"));
v19 = objc_retainAutoreleasedReturnValue(v18);
objc_msgSend(v17, "safeSetObject:forKey:", v19, CFSTR("sendId"));
objc_release(v19);
v89 = v15;
v20 = objc_msgSend(v15, "objectForKey:", CFSTR("channelid"));
v21 = objc_retainAutoreleasedReturnValue(v20);
objc_msgSend(v17, "safeSetObject:forKey:", v21, CFSTR("channelId"));
objc_release(v21);
v22 = objc_msgSend(&OBJC_CLASS___MMServiceCenter, "defaultCenter");
v23 = (void *)objc_retainAutoreleasedReturnValue(v22);
v24 = objc_msgSend(&OBJC_CLASS___CContactMgr, "class");
v25 = objc_msgSend(v23, "getService:", v24);
v26 = (void *)objc_retainAutoreleasedReturnValue(v25);
v27 = v26;
v28 = objc_msgSend(v26, "getSelfContact");
v29 = (void *)objc_retainAutoreleasedReturnValue(v28);
objc_release(v27);
objc_release(v23);
v30 = objc_msgSend(v29, "getContactDisplayName");
v31 = objc_retainAutoreleasedReturnValue(v30);
objc_msgSend(v17, "safeSetObject:forKey:", v31, CFSTR("nickName"));
objc_release(v31);
v88 = v29;
v32 = objc_msgSend(v29, "m_nsHeadImgUrl");
v33 = objc_retainAutoreleasedReturnValue(v32);
objc_msgSend(v17, "safeSetObject:forKey:", v33, CFSTR("headImg"));
objc_release(v33);
v34 = objc_msgSend(*(void **)((char *)v2 + 57), "m_oSelectedMessageWrap");
v35 = objc_retainAutoreleasedReturnValue(v34);
objc_release(v35);
if ( v35 )
{
v36 = objc_msgSend(*(void **)((char *)v2 + 57), "m_oSelectedMessageWrap");
v37 = (void *)objc_retainAutoreleasedReturnValue(v36);
v38 = v37;
v39 = objc_msgSend(v37, "m_oWCPayInfoItem");
v40 = (void *)objc_retainAutoreleasedReturnValue(v39);
v41 = v40;
v42 = objc_msgSend(v40, "m_c2cNativeUrl");
v43 = objc_retainAutoreleasedReturnValue(v42);
objc_msgSend(v17, "safeSetObject:forKey:", v43, CFSTR("nativeUrl"));
objc_release(v43);
objc_release(v41);
objc_release(v38);
}
v44 = objc_msgSend(&OBJC_CLASS___MMServiceCenter, "defaultCenter");
v45 = (void *)objc_retainAutoreleasedReturnValue(v44);
v46 = objc_msgSend(&OBJC_CLASS___MMMsgLogicManager, "class");
v47 = objc_msgSend(v45, "getService:", v46);
v48 = (void *)objc_retainAutoreleasedReturnValue(v47);
v49 = v48;
v50 = objc_msgSend(v48, "GetCurrentLogicController");
v51 = (void *)objc_retainAutoreleasedReturnValue(v50);
objc_release(v49);
objc_release(v45);
if ( v51 )
{
v52 = objc_msgSend(v51, "m_contact");
v53 = objc_retainAutoreleasedReturnValue(v52);
if ( v53 )
{
v54 = objc_msgSend(v51, "m_contact");
v55 = (void *)objc_retainAutoreleasedReturnValue(v54);
v56 = v55;
v57 = objc_msgSend(v55, "m_nsUsrName");
v58 = objc_retainAutoreleasedReturnValue(v57);
objc_release(v58);
objc_release(v56);
objc_release(v53);
if ( v58 )
{
v59 = objc_msgSend(v51, "m_contact");
v60 = (void *)objc_retainAutoreleasedReturnValue(v59);
v61 = v60;
v62 = objc_msgSend(v60, "m_nsUsrName");
v63 = objc_retainAutoreleasedReturnValue(v62);
objc_msgSend(v17, "safeSetObject:forKey:", v63, CFSTR("sessionUserName"));
objc_release(v63);
objc_release(v61);
}
}
}
v64 = objc_msgSend(*(void **)((char *)v2 + 57), "m_structDicRedEnvelopesBaseInfo");
v65 = (void *)objc_retainAutoreleasedReturnValue(v64);
v66 = v65;
v67 = objc_msgSend(v65, "stringForKey:", CFSTR("timingIdentifier"));
v68 = (void *)objc_retainAutoreleasedReturnValue(v67);
objc_release(v66);
if ( objc_msgSend(v68, "length") )
objc_msgSend(v17, "safeSetObject:forKey:", v68, CFSTR("timingIdentifier"));
objc_initWeak(&v103, v2);
v69 = objc_msgSend(&OBJC_CLASS___MMServiceCenter, "defaultCenter");
v70 = (void *)objc_retainAutoreleasedReturnValue(v69);
v71 = v68;
v72 = v2;
v73 = objc_msgSend(&OBJC_CLASS___WCPayLogicMgr, "class");
v74 = objc_msgSend(v70, "getService:", v73);
v75 = (void *)objc_retainAutoreleasedReturnValue(v74);
objc_msgSend(v75, "setRealnameReportScene:", 1003LL);
objc_release(v75);
objc_release(v70);
v76 = objc_msgSend(&OBJC_CLASS___MMServiceCenter, "defaultCenter");
v77 = (void *)objc_retainAutoreleasedReturnValue(v76);
v78 = objc_msgSend(&OBJC_CLASS___WCPayLogicMgr, "class");
v79 = objc_msgSend(v77, "getService:", v78);
v80 = (void *)objc_retainAutoreleasedReturnValue(v79);
v81 = objc_msgSend(*(void **)((char *)v72 + 57), "m_structDicRedEnvelopesBaseInfo");
v82 = (void *)objc_retainAutoreleasedReturnValue(v81);
v83 = v82;
v84 = objc_msgSend(v82, "objectForKeyedSubscript:", CFSTR("agree_duty"));
v85 = objc_retainAutoreleasedReturnValue(v84);
v97 = _NSConcreteStackBlock;
v98 = 3254779904LL;
v99 = sub_1015C17E0;
v100 = &unk_10390BBD0;
v101 = v17;
v86 = objc_retain(v17);
v87 = objc_retain(v72);
v102 = v87;
v91 = _NSConcreteStackBlock;
v92 = 3254779904LL;
v93 = sub_1015C18F8;
v94 = &unk_10390BC00;
objc_copyWeak(&v96, &v103);
v95 = objc_retain(v87);
objc_msgSend(v80, "checkHongbaoOpenLicense:acceptCallback:denyCallback:", v85, &v97, &v91);
... release
}
参数字典:
![](https://img.haomeiwen.com/i4790087/d8fe91391e3ae441.png)
一步一步调试,查看真实类型, 这里就不再一一展示了:
![](https://img.haomeiwen.com/i4790087/cc5803d04f360de7.png)
最终还原到这个地方:
![](https://img.haomeiwen.com/i4790087/1cbb74b3fa2aba57.png)
要看到 Block 的名字,就要恢复 Block 的符号表了。
整个抢红包核心汇编代码还原的过程:
void __cdecl -[WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes](#9116 *self, SEL a2)
{
v2 = self;
// m_data = self + 57
// v3 = objc_msgSend(*(void **)((char *)self + 57), "m_oSelectedMessageWrap");
// 伪代码
WCRedEnvelopesControlData *m_data = self.m_data;
// v3
CMessageWrap *mesWrap = [m_data m_oSelectedMessageWrap];
// v4 = (void *)objc_retainAutoreleasedReturnValue(v3);
// v4=v3
// v5 = objc_msgSend(v4, "m_oWCPayInfoItem");
// 伪代码 v6
WCPayInfoItem *infoItem = [mesWrap m_oWCPayInfoItem];
// v7=v6
// v7 = (void *)objc_retainAutoreleasedReturnValue(v6);
// v8 = v7;
// v9 = objc_msgSend(v7, "m_c2cNativeUrl");
// 伪代码 v9
NSString *c2cNativeUrl = [infoItem m_c2cNativeUrl];
// v10 = (void *)objc_retainAutoreleasedReturnValue(v9);
// v11 = objc_msgSend(CFSTR("wxpay://c2cbizmessagehandler/hongbao/receivehongbao?"), "length");
// 伪代码 v11
NSUInteger length = [urlStr length];
// v12 = objc_msgSend(v10, "substringFromIndex:", v11);
// 伪代码:生成一个新的字符串 v12
NSString *subString = [c2cNativeUrl substringFromIndex:length];
// v13 = v12
// v13 = (struct objc_object *)objc_retainAutoreleasedReturnValue(v12);
// objc_release(v10);
// objc_release(v8);
// objc_release(v5);
// v90 = v13;
// v14 = ((id (__cdecl *)(#9596 *, SEL, id, id))objc_msgSend)(
// (#9596 *)&OBJC_CLASS___WCBizUtil,
// "dictionaryWithDecodedComponets:separator:",
// v13,
// (id)CFSTR("&"));
// 伪代码 v14
id url_dic = [WCBizUtil dictionaryWithDecodedComponets:subString separator:"&"];
// v15=v14
// v15 = (void *)objc_retainAutoreleasedReturnValue(v14);
// v16 = objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "dictionary");
// v16 创建一个字典
NSMutableDictionary *mutableDic = [%c(NSMutableDictionary) dictionary];
// v17 = v16
// v17 = (void *)objc_retainAutoreleasedReturnValue(v16);
// objc_msgSend(v17, "safeSetObject:forKey:", CFSTR("1"), CFSTR("msgType"));
// "safeSetObject:forKey:" 重写 setObject:forKey:
[mutableDic setObject:@"1" forKey:@"msgType"];
// v18 = objc_msgSend(v15, "objectForKey:", CFSTR("sendid"));
// v18
[url_dic objectForKey:@"sendid"];
// v19 = v18
// v19 = objc_retainAutoreleasedReturnValue(v18);
// objc_msgSend(v17, "safeSetObject:forKey:", v19, CFSTR("sendId"));
// 伪代码
[mutableDic setObject:[url_dic objectForKey:@"sendid"] forKey:@"sendId"];
// objc_release(v19);
// v89 = v15;
// v20 = objc_msgSend(v15, "objectForKey:", CFSTR("channelid"));
// v21 = objc_retainAutoreleasedReturnValue(v20);
// objc_msgSend(v17, "safeSetObject:forKey:", v21, CFSTR("channelId"));
// objc_release(v21);
// 伪代码
[mutableDic setObject:[url_dic objectForKey:@"channelid"] forKey:@"channelId"];
// v22 = objc_msgSend(&OBJC_CLASS___MMServiceCenter, "defaultCenter");
// 伪代码 v22 类方法
MMServiceCenter *serCenter = [%c(MMServiceCenter) defaultCenter];
// v23 = (void *)objc_retainAutoreleasedReturnValue(v22);
// v24 = objc_msgSend(&OBJC_CLASS___CContactMgr, "class");
// v24
Class conMgr = [%c(CContactMgr) class];
// v25 = objc_msgSend(v23, "getService:", v24);
// v26 = (void *)objc_retainAutoreleasedReturnValue(v25);
// v27 = v26;
// v27 = v26 = v25
id service = [serCenter getService:conMgr];
// v28 = objc_msgSend(v26, "getSelfContact");
// v29 = v28
// v29 = (void *)objc_retainAutoreleasedReturnValue(v28);
id selfContact = [service getSelfContact];
// objc_release(v27);
// objc_release(v23);
// v30 = objc_msgSend(v29, "getContactDisplayName");
// v30
id displayName = [selfContact getContactDisplayName];
// v31 = objc_retainAutoreleasedReturnValue(v30);
// objc_msgSend(v17, "safeSetObject:forKey:", v31, CFSTR("nickName"));
// objc_release(v31);
[mutableDic setObject:displayName forKey:@"nickName"];
// v88 = v29;
// v32 = objc_msgSend(v29, "m_nsHeadImgUrl");
// v33 = objc_retainAutoreleasedReturnValue(v32);
id headImgUrl = [selfContact m_nsHeadImgUrl];
// objc_msgSend(v17, "safeSetObject:forKey:", v33, CFSTR("headImg"));
[mutableDic setObject:headImgUrl forKey:@"headImg"];
// objc_release(v33);
// v34 = objc_msgSend(*(void **)((char *)v2 + 57), "m_oSelectedMessageWrap");
// v35 = objc_retainAutoreleasedReturnValue(v34);
// objc_release(v35);
// v2 = self;
// self.m_data = self + 57
// v35 = v34 == mesWrap
// 就是开始的第一句和第二句
CMessageWrap *mesWrap = [self.m_data m_oSelectedMessageWrap];
if ( v35 )// mesWrap
{
// v36 = objc_msgSend(*(void **)((char *)v2 + 57), "m_oSelectedMessageWrap");
// v37 = (void *)objc_retainAutoreleasedReturnValue(v36);
// v38 = v37;
// v39 = objc_msgSend(v37, "m_oWCPayInfoItem");
// v40 = (void *)objc_retainAutoreleasedReturnValue(v39);
// v41 = v40;
// v42 = objc_msgSend(v40, "m_c2cNativeUrl");
// v43 = objc_retainAutoreleasedReturnValue(v42);
// v43 = v42 就是上面获取的 c2cNativeUrl
// objc_msgSend(v17, "safeSetObject:forKey:", v43, CFSTR("nativeUrl"));
[mutableDic setObject:c2cNativeUrl forKey:@"nativeUrl"];
objc_release(v43);
objc_release(v41);
objc_release(v38);
}
// v44 = objc_msgSend(&OBJC_CLASS___MMServiceCenter, "defaultCenter");
// v45 = (void *)objc_retainAutoreleasedReturnValue(v44);
// v45 = v44
MMServiceCenter *serCenter2 = [%c(MMServiceCenter) defaultCenter];
// v46 = objc_msgSend(&OBJC_CLASS___MMMsgLogicManager, "class");
// v46
[%c(MMMsgLogicManager) class];
// v47 = objc_msgSend(v45, "getService:", v46);
// v48 = (void *)objc_retainAutoreleasedReturnValue(v47);
// v49 = v48; = v47
// 红包逻辑管理者对象
MMMsgLogicManager * redEnvolopesLogicManager = [serCenter2 getService:[%c(MMMsgLogicManager) class]];
// v50 = objc_msgSend(v48, "GetCurrentLogicController");
// v51 = (void *)objc_retainAutoreleasedReturnValue(v50);
// v51 = v50 // WeixinContentLogicController
WeixinContentLogicController *currentLogicController = [redEnvolopesLogicManager GetCurrentLogicController];
// objc_release(v49);
// objc_release(v45);
if ( v51 ) // currentLogicController
{
// v52 = objc_msgSend(v51, "m_contact");
// v53 = objc_retainAutoreleasedReturnValue(v52);
// v53 = v52
// CContact 头文件中寻找
CBaseContact * m_contact = [currentLogicController m_contact];
if ( v53 )// m_contact
{
// v54 = objc_msgSend(v51, "m_contact");
// v55 = (void *)objc_retainAutoreleasedReturnValue(v54);
// v56 = v55;
// v54/v55/v56 = m_contact
// CBaseContact * m_contact = [currentLogicController m_contact];
// v57 = objc_msgSend(v55, "m_nsUsrName");
// v58 = objc_retainAutoreleasedReturnValue(v57);
// v58 = v57
NSString *nsUsrName = [m_contact m_nsUsrName];
// objc_release(v58);
// objc_release(v56);
// objc_release(v53);
if ( v58 )// nsUsrName
{
// v59 = objc_msgSend(v51, "m_contact");
// v60 = (void *)objc_retainAutoreleasedReturnValue(v59);
// v61 = v60;
m_contact
// v62 = objc_msgSend(v60, "m_nsUsrName");
nsUsrName
v63 = objc_retainAutoreleasedReturnValue(v62);
// objc_msgSend(v17, "safeSetObject:forKey:", v63, CFSTR("sessionUserName"));
// 其实就这一句代码
[mutableDic setObject:nsUsrName forKey:@"sessionUserName"];
// objc_release(v63);
// objc_release(v61);
}
}
}
// v64 = objc_msgSend(*(void **)((char *)v2 + 57), "m_structDicRedEnvelopesBaseInfo");
NSDictionary *m_dicBaseInfo = [m_data m_structDicRedEnvelopesBaseInfo];
// v65 = (void *)objc_retainAutoreleasedReturnValue(v64);
// v66 = v65;= v64
// v67 = objc_msgSend(v65, "stringForKey:", CFSTR("timingIdentifier"));
NSString *timingIdentifier = [m_dicBaseInfo stringForKey:@"timingIdentifier"];
// v68 = (void *)objc_retainAutoreleasedReturnValue(v67);
// objc_release(v66);
v68 = v67
// if ( objc_msgSend(v68, "length") )
// objc_msgSend(v17, "safeSetObject:forKey:", v68, CFSTR("timingIdentifier"));
if ([timingIdentifier length]){
// objc_msgSend(v17, "safeSetObject:forKey:", v68, CFSTR("timingIdentifier"));
[mutableDic setObject:timingIdentifier forKey:@"timingIdentifier"];
}
objc_initWeak(&v103, v2);
// v69 = objc_msgSend(&OBJC_CLASS___MMServiceCenter, "defaultCenter");
// MMServiceCenter *serCenter = [%c(MMServiceCenter) defaultCenter];
// v70 = (void *)objc_retainAutoreleasedReturnValue(v69);
// v71 = v68;
// v72 = v2;
// v73 = objc_msgSend(&OBJC_CLASS___WCPayLogicMgr, "class");
// v74 = objc_msgSend(v70, "getService:", v73);
// 支付逻辑管理者对象
WCPayLogicMgr * payLogicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCPayLogicMgr) class]];
// v75 = (void *)objc_retainAutoreleasedReturnValue(v74);
// 不知道参数是什么?可以直接 Hook 这个方法,或者直接看头就可以看出来
// objc_msgSend(v75, "setRealnameReportScene:", 1003LL);
[payLogicMgr setRealnameReportScene:(unsign int)1003];
// objc_release(v75);
// objc_release(v70);
// v76 = objc_msgSend(&OBJC_CLASS___MMServiceCenter, "defaultCenter");
// v77 = (void *)objc_retainAutoreleasedReturnValue(v76);
// v78 = objc_msgSend(&OBJC_CLASS___WCPayLogicMgr, "class");
// v79 = objc_msgSend(v77, "getService:", v78);
WCPayLogicMgr * payLogicMgr2 = payLogicMgr;
// v80 = v79
// v80 = (void *)objc_retainAutoreleasedReturnValue(v79);
// v81 = objc_msgSend(*(void **)((char *)v72 + 57), "m_structDicRedEnvelopesBaseInfo");
// v82 = (void *)objc_retainAutoreleasedReturnValue(v81);
// v83 = v82;
// 同上
// NSDictionary *m_dicBaseInfo = [m_data m_structDicRedEnvelopesBaseInfo];
v81 = v82 = v83 = m_dicBaseInfo;
// v84 = objc_msgSend(v82, "objectForKeyedSubscript:", CFSTR("agree_duty"));
// v85 = objc_retainAutoreleasedReturnValue(v84);
// v84
id subscript = [m_dicBaseInfo objectForKey:@"agree_duty"];
/* 关键的地方:调用方法*/
// 要看到 Block 的名字,就要恢复 Block 的符号表
// Block
v97 = _NSConcreteStackBlock;
// 其实可以看到 Block 的名字
v98 = 3254779904LL;
// 地址
v99 = sub_1015C17E0;
v100 = &unk_10390BBD0;
v101 = v17;
v86 = objc_retain(v17);
v87 = objc_retain(v72);
v102 = v87;
v91 = _NSConcreteStackBlock;
v92 = 3254779904LL;
v93 = sub_1015C18F8;
v94 = &unk_10390BC00;
objc_copyWeak(&v96, &v103);
v95 = objc_retain(v87);
objc_msgSend(v80, "checkHongbaoOpenLicense:acceptCallback:denyCallback:", v85, &v97, &v91);
}
恢复 Block 的符号表
与恢复符号表 类似,稍有所不同。
- 首先在 IDA 中运行 名称为 ida_search_block.py 的脚本文件,(快捷键:Windows 下 alt + F7, Mac: option + F2)网上可以下载。
![](https://img.haomeiwen.com/i4790087/b1793fc97056452e.png)
运行完毕以后,这个过程还好,挺快,文件夹中会多一个 名称为 block_symbol.json 的 json 文件,如图:
![](https://img.haomeiwen.com/i4790087/bea14992953c7cfc.png)
- 然后继续使用 之前的 restore-symbol 工具,进行恢复!
使用上次恢复符号表的 Mach-o 文件,并且添加 Block 的符号表
./restore-symbol WeChat2 -o WeChat_block -j block_symbol.json
恢复完成:
![](https://img.haomeiwen.com/i4790087/242b183b26d1dfc2.png)
![](https://img.haomeiwen.com/i4790087/2336e2bcff1a3206.png)
接着把恢复好的 Mach-o 文件拷贝至原始工程中的 TargetApp 中的 APP 包中,重新 拖入 IDA 分析,F5 转换,(不得不说一句,IDA 在 Mac 下,简直是没法用,恨不得砸了电脑,这个过程非常漫长,也不见得成功,有条件的装 Windows 虚拟机或直接用 PC 可惜目前都不具备)。
恢复 Block 的符号表后代码分析
![](https://img.haomeiwen.com/i4790087/0e86836d1d674a07.png)
/* 关键的地方:调用方法*/
// 要看到 Block 的名字,就要恢复 Block 的符号表
// Block
/*
v97 = _NSConcreteStackBlock;
// 其实可以看到 Block 的名字
v98 = 3254779904LL;
// 地址
v99 = sub_1015C17E0;
v100 = &unk_10390BBD0;
v101 = v17;
v86 = objc_retain(v17);
v87 = objc_retain(v72);
v102 = v87;
v91 = _NSConcreteStackBlock;
v92 = 3254779904LL;
v93 = sub_1015C18F8;
v94 = &unk_10390BC00;
objc_copyWeak(&v96, &v103);
v95 = objc_retain(v87);
objc_msgSend(v80, "checkHongbaoOpenLicense:acceptCallback:denyCallback:", v85, &v97, &v91);
*/
// 恢复 Block 的符号表后转换的内容
v97 =_ NSConcreteStackBlock;
v98 = 3254779904LL;
v99 = - [WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHmeViewOpenRedEnvelopes]_block;
v100 = &unk_10390BBD0;
v86 = objc_retain(v17); I
v87 = objc_retain(v72);
v102 = v87;
v91 =_ NSConcreteStackBlock;
v92 = 3254779904LL; I
v93 = - [WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHomeViewpenRedEnvelopes]_block_0;
v94 = &unk_10390BC00;
objc_ copyWeak(&v96, &v103);
v95 = objc_retain(v87);
objc_ msgSend(v80, "checkHongbaoOpenLicense:acceptCallback: denyCallback:", v85, &v97, &v91);
objc_ release(v85);
// v80 : payLogicMgr 后三个参数:v85, &v97, &v91
[payLogicMgr checkHongbaoOpenLicense:subscript acceptCallback:^(){
[WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHmeViewOpenRedEnvelopes]_block;
} denyCallback:^(){
[WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHomeViewpenRedEnvelopes]_block_0;
}]
接收的Block:
![](https://img.haomeiwen.com/i4790087/0cf5282ad52618a6.png)
继续分析:
[payLogicMgr checkHongbaoOpenLicense:subscript acceptCallback:^(){
// [WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHmeViewOpenRedEnvelopes]_block;
// - [WCRedEnvelopesReceiveControlLogi WCRedEnvelopesReceivemView0penedEnvelopes]_block(__ int64 a1)
// v1=a1;
// objc_ msgSend(&OBJC_ CLASS___ MServiceCenter, "defaultCenter");
// (void *)objc_ retainAutoreleasedeturu2 ;
// v4 = objc_ msgSend(&OBJC_ CLASS___ WCRedEnvelopesLogicMgr, "class");
// v5 = objc_ msgSend(v3,_ "getService:", v4);
// v6 = (void *)objc_ retainAutoreleasedReturalue(v5)
// 红包逻辑管理者对象
WCRedEnvelopesLogicMgr * redEnveLogicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCRedEnvelopesLogicMgr) class]];
// objc_ msgSend(v6, "OpenRedEnvelopesRequest:", *(_ QWORD *)(v1 + 32));
// objc_ release(v6);
// objc_ release(v3);
// - (void)OpenRedEnvelopesRequest:(id)arg1; // v1+32
// hook 之后可以看出就是上面拼接的 mutableDic
[redEnveLogicMgr OpenRedEnvelopesRequest:mutableDic];
// 动画效果,不需要
// *(_ DWORD *)(*(_ QWORD *)(v1 + 40) + 16LL) = 4; I
// return objc_ msgSend(*(void **)(*(_ QWORD *)(v1 + 40) + 73LL), "startReceiveAnimation");
} denyCallback:^(){
// 拒绝回调,不需要
[WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHomeViewpenRedEnvelopes]_block_0;
}]
hook OpenRedEnvelopesRequest:
![](https://img.haomeiwen.com/i4790087/950cfd03ab90bbb2.png)
可以看出参数就是上面拼接的 mutableDic
至此,抢红包的核心代码基本上分析完毕,接下来就是手动实现的过程。
手动实现抢红包过程
#pragma mark -- 手动实现抢红包过程
- (void)WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes
{
WCRedEnvelopesControlData *m_data = self.m_data;
WCRedEnvelopesControlData *data = MSHookIvar<WCRedEnvelopesControlData *>(self, "m_data");
CMessageWrap *mesWrap = [m_data m_oSelectedMessageWrap];
WCPayInfoItem *infoItem = [mesWrap m_oWCPayInfoItem];
NSString *c2cNativeUrl = [infoItem m_c2cNativeUrl];
NSUInteger length = [urlStr length];
NSString *subString = [c2cNativeUrl substringFromIndex:length];
id url_dic = [WCBizUtil dictionaryWithDecodedComponets:subString separator:"&"];
NSMutableDictionary *mutableDic = [%c(NSMutableDictionary) dictionary];
[mutableDic setObject:@"1" forKey:@"msgType"];
[url_dic objectForKey:@"sendid"];
[mutableDic setObject:[url_dic objectForKey:@"sendid"] forKey:@"sendId"];
[mutableDic setObject:[url_dic objectForKey:@"channelid"] forKey:@"channelId"];
MMServiceCenter *serCenter = [%c(MMServiceCenter) defaultCenter];
Class conMgr = [%c(CContactMgr) class];
id service = [serCenter getService:conMgr];
id selfContact = [service getSelfContact];
id displayName = [selfContact getContactDisplayName];
[mutableDic setObject:displayName forKey:@"nickName"];
id headImgUrl = [selfContact m_nsHeadImgUrl];
[mutableDic setObject:headImgUrl forKey:@"headImg"];
CMessageWrap *mesWrap = [self.m_data m_oSelectedMessageWrap];
if ( mesWrap )
{
[mutableDic setObject:c2cNativeUrl forKey:@"nativeUrl"];
}
MMServiceCenter *serCenter2 = [%c(MMServiceCenter) defaultCenter];
[%c(MMMsgLogicManager) class];
// 红包逻辑管理者对象
MMMsgLogicManager * redEnvolopesLogicManager = [serCenter2 getService:[%c(MMMsgLogicManager) class]];
WeixinContentLogicController *currentLogicController = [redEnvolopesLogicManager GetCurrentLogicController];
if(currentLogicController){
CBaseContact * m_contact = [currentLogicController m_contact];
if(m_contact){
NSString *nsUsrName = [m_contact m_nsUsrName];
if ( nsUsrName )//
{
[mutableDic setObject:nsUsrName forKey:@"sessionUserName"];
}
}
}
NSDictionary *m_dicBaseInfo = [m_data m_structDicRedEnvelopesBaseInfo];
NSString *timingIdentifier = [m_dicBaseInfo stringForKey:@"timingIdentifier"];
if ([timingIdentifier length]){
[mutableDic setObject:timingIdentifier forKey:@"timingIdentifier"];
}
// 支付逻辑管理者对象
WCPayLogicMgr * payLogicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCPayLogicMgr) class]];
[payLogicMgr setRealnameReportScene:(unsign int)1003];
WCPayLogicMgr * payLogicMgr2 = payLogicMgr;
id subscript = [m_dicBaseInfo objectForKey:@"agree_duty"];
[payLogicMgr checkHongbaoOpenLicense:subscript acceptCallback:^(){
// 红包逻辑管理者对象
WCRedEnvelopesLogicMgr * redEnveLogicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCRedEnvelopesLogicMgr) class]];
// hook 之后可以看出就是上面拼接的 mutableDic
[redEnveLogicMgr OpenRedEnvelopesRequest:mutableDic];
} denyCallback:^(){
// 拒绝回调,不需要
// [WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHomeViewpenRedEnvelopes]_block_0;
}]
}
%end
这个会有很多错误,没关系,一个一个解决掉!!!
最终修改完成的代码如下:
#pragma mark -- 手动实现抢红包过程
- (void)WCRedEnvelopesReceiveHomeViewOpenRedEnvelopes
{
WCRedEnvelopesControlData *m_data = MSHookIvar<WCRedEnvelopesControlData *>(self, "m_data");
// 消息类
CMessageWrap *mesWrap = [m_data m_oSelectedMessageWrap];
WCPayInfoItem *infoItem = [mesWrap m_oWCPayInfoItem];
NSString *c2cNativeUrl = [infoItem m_c2cNativeUrl];
NSString *urlStr = @"wxpay://c2cbizmessagehandler/hongbao/receivehongbao?";
NSUInteger length = [urlStr length];
// @"msgtype=1&channelid=1&sendid=1000039501201808076017246068172&sendusername=wxid_erhumb6yg9yu22&ver=6&sign=be26a8e8bfc8ac1cf33d5556623803044f234e4bc58fb2d2b634e8d7532f940686498bcfaa51cde8c201cbd0de2f8a12c2f1e39d66c41757826b18004585d9bf975d9a1c66e7fd8c4d75107d28a2a785"
NSString *subString = [c2cNativeUrl substringFromIndex:length];
/*
{
channelid = 1;
msgtype = 1;
sendid = 1000039501201808076017246068172;
sendusername = "wxid_erhumb6yg9yu22";
sign = be26a8e8bfc8ac1cf33d5556623803044f234e4bc58fb2d2b634e8d7532f940686498bcfaa51cde8c201cbd0de2f8a12c2f1e39d66c41757826b18004585d9bf975d9a1c66e7fd8c4d75107d28a2a785;
ver = 6;
}
*/
id url_dic = [%c(WCBizUtil) dictionaryWithDecodedComponets:subString separator:@"&"];
NSMutableDictionary *mutableDic = [%c(NSMutableDictionary) dictionary];
[mutableDic setObject:@"1" forKey:@"msgType"];
[url_dic objectForKey:@"sendid"];
[mutableDic setObject:[url_dic objectForKey:@"sendid"] forKey:@"sendId"];
[mutableDic setObject:[url_dic objectForKey:@"channelid"] forKey:@"channelId"];
MMServiceCenter *serCenter = [%c(MMServiceCenter) defaultCenter];
Class conMgr = [%c(CContactMgr) class];
id service = [serCenter getService:conMgr];
// id selfContact = [service getSelfContact];
// NSLog(@"%@",[selfContact class]);
CContact *selfContact = [service getSelfContact];
NSString * displayName = [selfContact getContactDisplayName];
[mutableDic setObject:displayName forKey:@"nickName"];
id headImgUrl = [selfContact m_nsHeadImgUrl];
[mutableDic setObject:headImgUrl forKey:@"headImg"];
if (mesWrap)
{
[mutableDic setObject:c2cNativeUrl forKey:@"nativeUrl"];
}
MMServiceCenter *serCenter2 = [%c(MMServiceCenter) defaultCenter];
[%c(MMMsgLogicManager) class];
// 红包逻辑管理者对象
MMMsgLogicManager * redEnvolopesLogicManager = [serCenter2 getService:[%c(MMMsgLogicManager) class]];
WeixinContentLogicController *currentLogicController = [redEnvolopesLogicManager GetCurrentLogicController];
if(currentLogicController){
CBaseContact * m_contact = [currentLogicController m_contact];
if(m_contact){
NSString *nsUsrName = [m_contact m_nsUsrName];
if (nsUsrName)//
{
[mutableDic setObject:nsUsrName forKey:@"sessionUserName"];
}
}
}
NSDictionary *m_dicBaseInfo = [m_data m_structDicRedEnvelopesBaseInfo];
NSString *timingIdentifier = m_dicBaseInfo[@"timingIdentifier"];
if ([timingIdentifier length]){
[mutableDic setObject:timingIdentifier forKey:@"timingIdentifier"];
}
// 支付逻辑管理者对象
WCPayLogicMgr * payLogicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCPayLogicMgr) class]];
[payLogicMgr setRealnameReportScene:(unsigned int)1003];
id subscript = [m_dicBaseInfo objectForKey:@"agree_duty"];
[payLogicMgr checkHongbaoOpenLicense:subscript acceptCallback:^(){
// 红包逻辑管理者对象
WCRedEnvelopesLogicMgr * redEnveLogicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCRedEnvelopesLogicMgr) class]];
// hook 之后可以看出就是上面拼接的 mutableDic
[redEnveLogicMgr OpenRedEnvelopesRequest:mutableDic];
} denyCallback:^(){
// 拒绝回调,不需要
// [WCRedEnvelopesReceiveControlLogic WCRedEnvelopesReceiveHomeViewpenRedEnvelopes]_block_0;
}];
}
运行,抢红包,OK,Very Good!!! 成功抢到红包!
![](https://img.haomeiwen.com/i4790087/d484a3f8ec39d560.png)
后记
目前手动抢红包过程已经实现了,那下一步怎么做呢?是不是放到之前节后到消息的方法中执行呢???
具体过程怎么实现呢???