神刀安全网

iOS逆向篇之微信抢红包(下)

上文已经知道收到红包消息与开红包方法,那么只需在收到红包消息时,调用开红包方法,就可以完成自动抢红包
完整的工程地址

一 红包消息时调用开红包方法

上篇hook到了收到红包消息的方法就是CMessageMgr类中的onNewSyncAddMessage:方法,于是把开红包的代码放到此方法中。
onNewSyncAddMessage:方法中,当m_uiMessageType=49的时候是红包消息,此时判断是否开启了自动抢红包功能

- (void)onNewSyncAddMessage:(CMessageWrap *)m_Wrap{ if(MSHookIvar<unsigned int>(m_Wrap,"m_uiMessageType") != 49){//不是红包消息         %orig;         return;     } if([WCDefaults boolForKey:WCSWITCHKEY] == NO){//是否开启自动抢红包         %orig;         return;     }     WCPayInfoItem *item =[m_Wrap m_oWCPayInfoItem];     NSString *url =[item  m_c2cNativeUrl];     NSInteger length = [@"wxpay://c2cbizmessagehandler/hongbao/receivehongbao?" length];     id componets = [url substringFromIndex:length];     NSDictionary *dictionary=[%c(WCBizUtil) dictionaryWithDecodedComponets:componets separator:@"&"];     NSMutableDictionary *mul_dict =[%c(NSMutableDictionary) dictionary];     [mul_dict setObject:@"1" forKey:@"msgType"];     [mul_dict setObject:dictionary[@"sendid"] forKey:@"sendId"];     [mul_dict setObject:dictionary[@"channelid"] forKey:@"channelId"];     CContactMgr *server =[[%c(MMServiceCenter) defaultCenter] getService:[%c(CContactMgr) class]];     CContact *contact = [server getSelfContact];     id  displayName = [contact getContactDisplayName];     [mul_dict setObject:displayName forKey:@"nickName"];     id m_nsHeadImgUrl = [contact m_nsHeadImgUrl];     [mul_dict setObject:m_nsHeadImgUrl forKey:@"headImg"];     if ( url )     {         [mul_dict setObject:url forKey:@"nativeUrl"];             }      NSString *m_nsUsrName = MSHookIvar<NSString *>(m_Wrap,"m_nsFromUsr");     [mul_dict setObject:m_nsUsrName forKey:@"sessionUserName"];     NSLog(@"---%@",m_nsUsrName); //因为m_data获取不到,所以编译不过     NSDictionary  *m_struct = [m_data m_structDicRedEnvelopesBaseInfo];     NSString *timingIdentifier= [m_struct objectForKey:@"timingIdentifier"];     if ( [timingIdentifier length])     { [mul_dict setObject:timingIdentifier forKey:@"timingIdentifier"];}          WCPayLogicMgr *payLogicMgr =[[%c(MMServiceCenter) defaultCenter] getService:[%c(WCPayLogicMgr) class]];     [payLogicMgr setRealnameReportScene:1003];     id subScript = [m_struct objectForKeyedSubscript:@"agree_duty"];     [payLogicMgr checkHongbaoOpenLicense:subScript acceptCallback:^(){         WCRedEnvelopesLogicMgr *envelopesLogicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCRedEnvelopesLogicMgr) class]];         [envelopesLogicMgr OpenRedEnvelopesRequest:mul_dict];     }denyCallback:^(){              }]; } %end 

这个方法主要就是拼接mul_dict然后作为参数,调用WCRedEnvelopesLogicMgr类的OpenRedEnvelopesRequest:函数。mul_dict需要的参数,能从CMessageWrap中获取的直接获取,但是timingIdentifier获取不到,所以要另作分析,要想办法获取到timingIdentifier。

二 其他方法获取timingIdentifier

当红包消息收到后,点击红包消息时有菊花在转,说明在请求网络,请求过后才是红包弹出的界面,所以现在可以进行hook点击红包消息时的方法

  1. 通过分析知道WCRedEnvelopesLogicMgr类就是红包管理类,所以直接hook这个类中的所有方法:

    iOS逆向篇之微信抢红包(下)

然后进行分析,发现以下三个方法是点击红包消息时调用的方法:

[<WCRedEnvelopesLogicMgr: 0x10ef9aff0> ReceiverQueryRedEnvelopesRequest:{  agreeDuty = 0;  channelId = 1;  inWay = 1;  msgType = 1;  nativeUrl = "wxpay://c2cbizmessagehandler/hongbao/receivehongbao?msgtype=1&channelid=1&sendid=1000039501201805287004922762149&sendusername=wxid_hy6hye79l4q241&ver=6&sign=9995652ef3b076bbc7b626c0272f7cbbb2168732bc1a9af34777acbf4206d97062af9a8e3c84ad8812d45b48039d9c74e2f6fadb01223e74a9361a61947d4a19789abfde732b339ffb17c05c7bd7a2a0";  sendId = 1000039501201805287004922762149;  } ]  2018-05-28 10:21:42.258137+0800 WeChat[28565:2640576] -[<WCRedEnvelopesLogicMgr: 0x10ef9aff0> GetHongbaoBusinessRequest:{  agreeDuty = 0;  channelId = 1;  inWay = 1;  msgType = 1;  nativeUrl = "wxpay://c2cbizmessagehandler/hongbao/receivehongbao?msgtype=1&channelid=1&sendid=1000039501201805287004922762149&sendusername=wxid_hy6hye79l4q241&ver=6&sign=9995652ef3b076bbc7b626c0272f7cbbb2168732bc1a9af34777acbf4206d97062af9a8e3c84ad8812d45b48039d9c74e2f6fadb01223e74a9361a61947d4a19789abfde732b339ffb17c05c7bd7a2a0";  sendId = 1000039501201805287004922762149;  } CMDID:3 OutputType:1 ]   2018-05-28 10:21:42.490993+0800 WeChat[28565:2640576] [<WCRedEnvelopesLogicMgr: 0x10ef9aff0> OnWCToHongbaoCommonResponse:<HongBaoRes: 0x10efd1550> Request:<HongBaoReq: 0x10ed82840> ] 

ReceiverQueryRedEnvelopesRequest:方法和GetHongbaoBusinessRequest:方法都是红包请求方法,参数也差不多,通过ida分析ReceiverQueryRedEnvelopesRequest:发现这个方法就是对GetHongbaoBusinessRequest:方法的封装。

  • 那么可以得到ReceiverQueryRedEnvelopesRequest:和OnWCToHongbaoCommonResponse:Request:这两个就是关键方法
  1. 在onNewSyncAddMessage:收到红包消息的时候,主动调用GetHongbaoBusinessRequest:方法
  WCRedEnvelopesLogicMgr *envelopesLogicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCRedEnvelopesLogicMgr) class]];     NSMutableDictionary *param =[%c(NSMutableDictionary) dictionary];     [param setObject:@"1" forKey:@"msgType"];     [param setObject:dictionary[@"channelid"] forKey:@"channelId"];     [param setObject:@"0" forKey:@"agreeDuty"];     [param setObject:@"1" forKey:@"inWay"]; if([m_nsUsrName cons containsString:@"@chatroom"]){//群红包       [param setObject:@"0" forKey:@"inWay"];     }      [param setObject:dictionary[@"sendid"] forKey:@"sendId"];      [param setObject:url forKey:@"nativeUrl"];     [envelopesLogicMgr ReceiverQueryRedEnvelopesRequest:param]; 
  • 拼接参数,m_nsFromUsr字段包含@chatroom就是群红包

可以得到,主动调用ReceiverQueryRedEnvelopesRequest:方法和手动点击红包消息是一样的效果。那么我们再来分析OnWCToHongbaoCommonResponse:Request:方法,通过打印参数类型得到此方法的发第一个参数是HongBaoRes,然后通过头文件得到HongBaoRes如下:

@interface SKBuiltinBuffer_t : NSObject @property(retain, nonatomic) NSData *buffer;  @property(nonatomic) unsigned int iLen;  @end @interface SKBuiltinString_t : NSObject @property(retain, nonatomic) NSString *string; @end  @interface BaseResponse : NSObject @property(retain, nonatomic) SKBuiltinString_t *errMsg; @property(nonatomic) int ret;  @end @interface HongBaoRes : NSObject @property(retain, nonatomic) BaseResponse *baseResponse; @property(nonatomic) int cgiCmdid; // @dynamic cgiCmdid; @property(retain, nonatomic) NSString *errorMsg; // @dynamic errorMsg; @property(nonatomic) int errorType; // @dynamic errorType; @property(retain, nonatomic) NSString *platMsg; // @dynamic platMsg; @property(nonatomic) int platRet; // @dynamic platRet; @property(retain, nonatomic) SKBuiltinBuffer_t *retText; // @dynamic retText; @end 

然后我们在OnWCToHongbaoCommonResponse:Request:中打印第一个参数的相关信息:

- (void)OnWCToHongbaoCommonResponse:(HongBaoRes *)arg1 Request:(id)arg2 {     NSLog(@"platMsg:%@",arg1.platMsg);     NSLog(@"cgiCmdid:%d",arg1.cgiCmdid);     NSLog(@"platRet:%d",arg1.platRet);     NSLog(@"errorType:%d",arg1.errorType);     NSLog(@"errorMsg:%@",arg1.errorMsg);     NSData *buffer = arg1.retText.buffer;     NSString *aString = [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding];      NSLog(@"retText:%@",aString);     %orig; } 

打印输出:

2018-05-28 11:31:44.197315+0800 WeChat[28877:2671064] platMsg: 2018-05-28 11:31:44.197483+0800 WeChat[28877:2671064] cgiCmdid:3 2018-05-28 11:31:44.197575+0800 WeChat[28877:2671064] platRet:0 2018-05-28 11:31:44.197654+0800 WeChat[28877:2671064] errorType:0 2018-05-28 11:31:44.197852+0800 WeChat[28877:2671064] errorMsg:ok 2018-05-28 11:31:44.198045+0800 WeChat[28877:2671064] retText:{"retcode":0,"retmsg":"ok","sendId":"1000039501201805287004922762149","wishing":"恭喜发财,大吉大利","isSender":0,"receiveStatus":0,"hbStatus":2,"statusMess":"给你发了一个红包","hbType":0,"watermark":"","sendUserName":"wxid_hy6hye79l4q241","timingIdentifier":"35971B49DE4AE3E604E17E3EAB463272"} 

可以得到retText:中有timingIdentifier

  • 所以获取timingIdentifier
    在收到红包消息时主动调用ReceiverQueryRedEnvelopesRequest:方法,然后在- (void)OnWCToHongbaoCommonResponse:(HongBaoRes *)arg1 Request:(id)arg2方法中的第一个参数HongBaoRes的retText属性里面包含timingIdentifier
  • 分析HongBaoRes参数
    cgiCmdid==3,点击红包消息,没有被抢过的红包
    HongBaoRes的retText中:
    receiveStatus == 0没有抢过的红包 receiveStatus == 2抢过的红包;isSender==0自己不是发红包消息的人;isSender==1自己发的红包
  1. 获取到timingIdentifier
    要在红包还没有抢过的情况下才抢红包
NSError *error; NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:arg1.retText.buffer options:NSJSONReadingMutableContainers error:&error]; NSString *receiveStatus =[NSString stringWithFormat:@"%@",responseDict[@"receiveStatus"]]; if(arg1 !=nil && arg2 !=nil && arg1.cgiCmdid==3 && [receiveStatus isEqualToString:@"0"])//没有被抢过的红包  {          NSString *timingIdentifier = responseDict[@"timingIdentifier"]; } 

那么获取到timingIdentifier后怎么通知收到红包消息的方法->CMessageMgr类中的onNewSyncAddMessage:方法呢?而且红包消息方法一下来很多条呢?
我们可以用单例队列来保存红包消息,在获取到timingIdentifier后取出队列中的参数,然后调用开红包方法

三 开始抢红包

  1. 单例队列来保存红包消息
    WeChatMessageWarp.h
@interface WeChatMessageWarp : NSObject  +(instancetype)shareInstanceQueue;  - (void)inputQueue:(NSMutableDictionary *)param; - (NSMutableDictionary *)getParamQueue; @end 

WeChatMessageWarp.m

@interface WeChatMessageWarp() @property (nonatomic,strong)NSMutableArray  *queue; @end  @implementation WeChatMessageWarp +(instancetype)shareInstanceQueue {     static WeChatMessageWarp *queue = nil;     static dispatch_once_t  once;     dispatch_once(&once,^{         queue = [[WeChatMessageWarp alloc]init];     });     return queue; } - (instancetype)init {     self = [super init];     if (self) {         _queue = [NSMutableArray array];     }     return self; }  - (void)inputQueue:(NSMutableDictionary *)param{     [self.queue addObject:param]; } - (NSMutableDictionary *)getParamQueue{     if (self.queue.count == 0 && !self.queue.firstObject) {         return nil;     }      NSMutableDictionary *first = self.queue.firstObject;     [self.queue removeObjectAtIndex:0];     return first;      } @end 
  • 在收到红包消息的时候保存参数mul_dict,参数重可以标记是不是自己写的红包插件
 WeChatMessageWarp *share = [WeChatMessageWarp shareInstanceQueue];     //标记是插件抢红包     [mul_dict setObject:@"YES" forKey:@"isMySelfMeryin"];     [share inputQueue:mul_dict]; 
  • 然后在获取到timingIdentifier后把参数取出来,并判断是不是自己写的插件
 WeChatMessageWarp *share = [WeChatMessageWarp shareInstanceQueue];  NSMutableDictionary *warp = [share getParamQueue];  NSString *flag = [warp objectForKey:@"isMySelfMeryin"];  if(![flag isEqualToString:@"YES"]){//自己写的插件抢红包         return;   }  [warp removeObjectForKey:@"isMySelfMeryin"];  if(timingIdentifier.length >0 && warp.count >0){         [warp setObject:timingIdentifier forKey:@"timingIdentifier"];   } 
  1. 开始抢红包
    抢红包的时候,要判断插件是否设置了延迟时间,然后延迟几秒开始抢红包
//开始开红包              WCRedEnvelopesLogicMgr *envelopesLogicMgr = [[%c(MMServiceCenter) defaultCenter] getService:[%c(WCRedEnvelopesLogicMgr) class]];             if(envelopesLogicMgr){                 //延迟抢红包时间                 NSString *time = [WCDefaults valueForKey:WCTIMEKEY];                 float second = 1;                 if(time){//默认1秒                     second =[time floatValue];                 }                                  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(second * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{                      [envelopesLogicMgr OpenRedEnvelopesRequest:warp];                 });                              } 

四 优化工程结构

完成了自动抢红包代码后,一个类中的代码太多,我们可以按功能拆分代码

  • 把设置界面的代码出来
    新建->iOS -Other -Empty->WeChatSettingViewControllerCell.xm 注意targets勾选dylib
    把设置界面的代码拷贝到WeChatSettingViewControllerCell.xm 然后build生成WeChatSettingViewControllerCell.mm,然后把.mm拖到工程中,注意targets勾选dylib

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » iOS逆向篇之微信抢红包(下)

分享到:更多 ()