美文网首页利器集合iOS精华iOS
iOS反编译-hook微信之艾特所有人

iOS反编译-hook微信之艾特所有人

作者: 小黑丶 | 来源:发表于2016-09-02 15:17 被阅读7911次

研究了一段时间反编译逆向工程,只是略微了解了一些皮毛,最近忙的事情太杂,就简单写一下吧。
在文章开始之前,首先感谢"蒸米"大神,在乌云上的一些文章引领我进入反编译的,其次也感谢"east520" (http://www.jianshu.com/p/189afbe3b429)
这篇文章给的一些方法和启示.下面说一下我的一些做法,可能会有很多问题.

1.需求

众所周知,在通常情况下,微信只有是群主才能艾特所有人,发消息或者群公告,目前的需求就是非群主,也能艾特群里的所有人。

2.尝试方法

1> 尝试非群主编辑群公告,初步判定是微信发群公告是通过向微信发送一个网络请求,然后由微信进行通知(研究了一段,发现效果不是太好)
2>通过一一艾特群里每一个成员,然后修改发送的内容,再调用微信的发消息方法进行实现。

3.实现方法

1.首先要了解的微信一个很重要的类,<code>CMessageMgr</code>,看名字应该是微信的一个消息管理的类,在<code>class-dump</code>微信头文件之后,找到该类,然后看它的一些属性和方法,下面这两个方法大概就是微信发消息函数和消息处理函数,我们要做的就是hook这两个函数,

Paste_Image.png

2.我在此处用的是通过<code>theos</code>来编写hook,<code>theos</code>的一些安装和使用方法,可以通过<code>iOS应用逆向工程第2版</code>这本书来操作,使用方法已经十分详细.

4.初始化工程

1.创建tweak工程
WechatIMG16.jpeg
2.打开目录,会看见<code>makefile</code><code>control</code>

<code>Tweak.xm</code>三个文件.

2.1 makefile是指定工程用到的文件,框架,库等信息.将整个过程自动化,默认的文件内容
include theos/makefiles/common.mk

TWEAK_NAME = ioswechatselectall
ioswechatselectall_FILES = Tweak.xm // 包含的源文件,不包括头文件

include $(THEOS_MAKE_PATH)/tweak.mk

after-install::                  // 安装完成后杀死某个进程,此处要hook微信,所以进程是WeChat
    install.exec "killall -9 WeChat"

如果我们要导入frameork,需要添加下面的指令,后面要加的就是frameWork的名字

ioswechatselectall_FRAMEWORKS = UIKit CoreFoundation Foundation CoreGraphics QuartzCore Security

指定处理器架构

ARCHS = armv7 arm64

指定SDK版本,最低7.0

TARGET = iphone:latest:7.0

可以设置安装hook设备的ip地址 进行安装

THEOS_DEVICE_IP = 192.168.1.159

最终完整的makeFile文件为

THEOS_DEVICE_IP = 192.168.1.159
TARGET = iphone:latest:7.0
ARCHS = armv7 arm64

include theos/makefiles/common.mk

TWEAK_NAME = ioswechatselectall
ioswechatselectall_FILES = Tweak.xm
ioswechatselectall_FRAMEWORKS = UIKit CoreFoundation Foundation CoreGraphics QuartzCore Security

include $(THEOS_MAKE_PATH)/tweak.mk

after-install::
    install.exec "killall -9 WeChat"

2.2 control文件

control文件相比来说就比较简单,记录了deb包管理系统的所有的基本嘻嘻

Package: com.bykernel.selectall
Name: ioswechatselectall
Depends: mobilesubstrate,firmware(>=8.0) // 设置设备的最低版本号
Version: 1.0
Architecture: iphoneos-arm
Description: An awesome MobileSubstrate tweak!
Maintainer: tg
Author: tg
Section: Tweaks

2.3 Tweak.xm

通过theos创建的tweak工程,默认源文件是Tweak.xm,x表示支持Logos语法只有x则标识支持Logos和C语法,xm则标识支持Logos和C/C++语法,与.m和.mm类似.

基本Logos语法,包含<code>%hook</code>,<code>%log</code>,<code>%orig</code>三个预处理指令
2.3.1
<code>%hook </code>指定要hook的class, 必须以end结尾
<code>%log</code>打印一些信息
<code>%orig</code>非常重要,使用在%hook内部,执行hook函数的原始代码,如果不添加%orig,则原始函数不会得到执行

4.编写代码

4.1先从一个简单的hook代码开始,

我们要做的是hook微信的收发消息函数,在一开始,我已经告诉大家微信收发消息函数是哪两个,现在我们就把他hook掉,看看他里面携带的一些参数

4.1.1Tweak.xm代码


%hook CMessageMgr

- (void)AsyncOnAddMsg:(id)arg1 MsgWrap:(id )wrap{
    
    %orig;
    NSLog(@"AsyncOnAddMsg wrap ====== %@",wrap);
 
}

- (void)AddMsg:(id)arg1 MsgWrap:(id )wrap{
    %orig;
    NSLog(@"AddMsg wrap ====== %@",wrap);

}
%end

①然后通过 <code>make package install</code>方法,讲hook注入,然后收发消息,查看终端打印结果

②当我们发送一个普通文字消息时,终端会打印

<Warning>: AsyncOnAddMsg wrap ====== {m_uiMesLocalID=7, m_ui64MesSvrID=0, m_nsFromUsr=wxi*r22~19, m_nsToUsr=tia*103~11, m_uiStatus=1, type=1, msgSource="(null)"} 

<Warning>: AddMsg wrap ====== {m_uiMesLocalID=7, m_ui64MesSvrID=0, m_nsFromUsr=wxi*r22~19, m_nsToUsr=tia*103~11, m_uiStatus=1, type=1, msgSource="(null)"} 

发送一个语音消息

<Warning>: AsyncOnAddMsg wrap ====== {m_uiMesLocalID=9, m_ui64MesSvrID=0, m_nsFromUsr=wxi*r22~19, m_nsToUsr=tia*103~11, m_uiStatus=1, type=34, msgSource=""} 
<Warning>: AddMsg wrap ====== {m_uiMesLocalID=9, m_ui64MesSvrID=0, m_nsFromUsr=wxi*r22~19, m_nsToUsr=tia*103~11, m_uiStatus=1, type=34, msgSource=""} 

可以初步判断,type的类型,决定了发送消息的类型

③当我们接收到一个普通文字消息时,只会调用AsyncOnAddMsg方法.


Paste_Image.png
 AsyncOnAddMsg wrap ====== {m_uiMesLocalID=8, m_ui64MesSvrID=4596545622562551918, m_nsFromUsr=tia*103~11, m_nsToUsr=wxi*r22~19, m_uiStatus=3, type=1, msgSource=""} 

从里面可以得到一些基本的信息,<code>m_nsFromUsr</code>,<code>m_nsToUsr</code>,<code>m_uiStatus</code>,<code>type</code>

4.1.2 尝试在群里艾特一个好友,然后看看打印结果是什么

<Warning>:AsyncOnAddMsg wrap ====== {m_uiMesLocalID=2, m_ui64MesSvrID=0, m_nsFromUsr=wxi*r22~19, m_nsToUsr=1234567890@chatroom, m_uiStatus=1, type=1, msgSource="<msgsource><atuserlist>weixinzhanghao</atuserlist></msgsource>"} 

<Warning>:AddMsg wrap ====== {m_uiMesLocalID=2, m_ui64MesSvrID=0, m_nsFromUsr=wxi*r22~19, m_nsToUsr=1234567890@chatroom, m_uiStatus=1, type=1, msgSource="<msgsource><atuserlist>weixinzhanghao</atuserlist></msgsource>"} 

会发现,<code>m_nsToUsr</code>这个属性的不再是一个人的id,而是<code>由一串数字+@+chatroom</code>组成的一个房间号,暂且称它为群号,type的类型还是1,文本类型,而最后的<code>msgSource</code>也不再是一个空值,而是<code>"<msgsource><atuserlist>weixinzhanghao</atuserlist></msgsource>"</code>,类似于xml格式的一个字符串在<atuserlist></atuserlist>标签里的就是你要艾特好友的微信帐号.

4.1.3 那么如何才能拿到群里,其他人的这个微信帐号呢?再次感谢http://www.jianshu.com/p/189afbe3b429 这篇文章的作者,和蒸米大神,从他们的文章和代码里,知道了微信另外一个很重要的类<code>CContactMgr</code>,看名字应该是联系人的管理类,在微信头文件里可以看到,他的一些属性和方法,

Paste_Image.png

获取自己contant属性然后再去查找有没有<code>CContact</code>这个类,

Paste_Image.png

,再去看他里面的属性和方法,

Paste_Image.png

通过<code>+ (id)getChatRoomMemberWithoutMyself:(id)arg1;</code>这个方法,可以获取到处自己以外的所有群成员,后面要传的参数就是前面提到的<code>1234567890@chatroom</code>微信群号.得到一个数组,数组里面的值就是除你以外的所有群成员.

4.2 创建一个.h文件,将需要的一些微信的类的头文件导入,以求编译通过,这里就不再太多描述.

通过打印wrap的class ,可以得知它是CMessageWrap类型,里面的一些属性有
都是我们刚才打印得到的信息.而m_nsContent应该就是发送消息的内容,可以通过打印得到


Paste_Image.png
wrap ====== CMessageWrap

4.3 现在大概的了解的内容就做完了,然后开始编写代码,我们需要自己定义一个格式,来规范在输入什么时进行艾特所有人操作,此刻我们定义的一个格式是以 <code>!all</code> 开头.

在<code>- (void)AddMsg:(id)arg1 MsgWrap:(CMessageWrap *)wrap</code>里,加入hook
4.3.1 首先我们要拿到当前我们自身的CContact,
4.3.2 然后判断wrap的消息类型type是否为1,也就是文本消息类型,如果是
4.3.3 判断CMessageWrap的fromUsr是不是selfContact的m_nsUsrName
4.3.4 判断toUsr的是否以@chatroom结尾,也就是判断是否为群聊天
4.3.5 判断wrap.m_nsMsgSource是否为nil,前面打印过,在正常发普通文本消息的时候m_nsMsgSource是空的.
4.3.6 通过<code>[wrap.m_nsContent hasPrefix:@"!all"]</code>判断是否为约定的格式

如果以上几个条件都满足,那么可以再进行我们的hook操作.

4.4 修改wrap的格式内容

4.4.1 通过上面说过的getChatRoomMemberWithoutMyself方法得到群里除自己以外的所有人,遍历数组,取出数组每个属性(CContact)的m_nsUsrName值,拼接成一个字符串.
4.4.2 修改wrap.m_nsContent 的内容,我们不希望被别人看到我们约定的艾特所有人格式,所以通过<code>subStringFromIndex</code>方法, 去掉前缀,取后面的内容作为wrap.m_nsContent 的内容
4.4.3 最重要的设置m_nsMsgSource为<code>[NSString stringWithFormat:@"<msgsource><atuserlist>%@</atuserlist></msgsource>",sourceString];</code>sourceString就是拼接好的字符串,

4.5 将以上内容修改好后,然后在函数的结尾调用<code>%orig</code>也就是调用原始函数,由于经过我们hook,我们发的带格式的消息的m_nsMsgSource已经附有新值,微信就会以为我们艾特每个好友,从而实现艾特所有人的功能.

5.实现效果

1.我不是测试11的群主,我也没有办法艾特所有人

Paste_Image.png

2.按照格式输入测试之后,就会实现艾特所有人的功能

Paste_Image.png

3.其他成员收到的信息

Paste_Image.png Paste_Image.png

应很多人要求把代码贴一下,很久以前的东西了,不知道现在是否能继续使用

#import <UIKit/UIKit.h>
#import "WeChatRedEnvelop.h"
#import <Foundation/Foundation.h>




%hook NewMainFrameViewController
- (void)viewDidLoad
{
    %orig;
    
    UIButton *transparentButton = [UIButton buttonWithType:UIButtonTypeCustom];
    transparentButton.frame = CGRectMake(0, 64, 44, 44);
    transparentButton.layer.cornerRadius = 8;
    transparentButton.clipsToBounds = YES;
    transparentButton.backgroundColor = [UIColor blueColor];
    [transparentButton addTarget:self action:@selector(clickImage) forControlEvents:UIControlEventTouchUpInside];
    [((UIViewController *)self).view addSubview:transparentButton];
}
%new
- (void)clickImage{
    
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"请输入文本" message:@"" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定",nil];
    [alert setAlertViewStyle:UIAlertViewStylePlainTextInput];
    [alert show];

}


%new
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if(buttonIndex == 1){
        
        UITextField *field = [alertView textFieldAtIndex:0];
        NSLog(@"txt ====  %@",field.text);
        
        NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
        NSString *plistPath =  [path stringByAppendingPathComponent:@"data.plist"];
        
        NSMutableArray *roomArray = [NSMutableArray arrayWithContentsOfFile:plistPath];
        NSLog(@"roomArray ===== %@",roomArray);
        
        
        CMessageMgr *messager = [[objc_getClass("MMServiceCenter") defaultCenter] getService:[objc_getClass("CMessageMgr") class]];
        CMessageWrap *wrap = [[%c(CMessageWrap) alloc] initWithMsgType:1];
        
        //
        for(NSString *roomID in roomArray){
            
            
            NSLog(@"顺序测试-----%@",roomID);
            //
            NSTimeInterval time = [[NSDate date] timeIntervalSince1970];
            long long int date = (long long int)time;
            
            
            NSString *name =[%c(SettingUtil) getLocalUsrName:0];
            wrap.m_nsFromUsr = name;
            wrap.m_nsContent = [NSString stringWithFormat:@"#所有人 %@",field.text];
            wrap.m_nsToUsr = roomID;
            wrap.m_uiCreateTime = date;
            wrap.m_uiStatus = 1;
            wrap.m_nsMsgSource = nil;
            [messager AddMsg:roomID  MsgWrap:wrap];
            
            
        }
    }

}

%end


%hook CMessageMgr

- (void)AsyncOnAddMsg:(id)arg1 MsgWrap:(CMessageWrap *)wrap{
  
    NSLog(@"接收到消息%@",wrap);
    NSString *fromUser = wrap.m_nsFromUsr ;
    if ([fromUser  hasSuffix:@"@chatroom"])
    {
        NSLog(@"chatroom found");
      
        NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
        NSString *plistPath =  [path stringByAppendingPathComponent:@"data.plist"];
        NSMutableArray *arrayM = [NSMutableArray array];
        NSArray *storArray = [NSArray arrayWithContentsOfFile:plistPath];
        [arrayM addObjectsFromArray:storArray];
        
        if (![arrayM containsObject:fromUser]){
            
            [arrayM addObject:fromUser];
            NSLog(@"存储数据");
            NSLog(@"arrayM ==== %@",arrayM);
            [arrayM writeToFile:plistPath atomically:YES];
        }

                          
    }
      %orig;
}

- (void)AddMsg:(id)arg1 MsgWrap:(CMessageWrap *)wrap{
    
    NSLog(@"time ===%ld",(unsigned long)wrap.m_uiCreateTime);
    
    
    
    int type = wrap.m_uiMessageType;
    NSString *knFromUser = wrap.m_nsFromUsr;
    NSString *knToUsr = wrap.m_nsToUsr;
    NSString *knContent = wrap.m_nsContent;
    NSString *knSource = wrap.m_nsMsgSource;
    NSString *message = [NSString stringWithFormat:@"type=%d--knFromUser=%@--knToUsr=%@--knContent=%@--knSource=%@",type,knFromUser,knToUsr,knContent,knSource];
    
    CContactMgr *contactManager = [[objc_getClass("MMServiceCenter") defaultCenter] getService:[objc_getClass("CContactMgr") class]];
    CContact *selfContact = [contactManager getSelfContact];
    

    
    NSLog(@"message =======  %@",message);
    if (type == 1){
        
        if ([knFromUser isEqualToString:selfContact.m_nsUsrName]) {
            
            if ([knToUsr hasSuffix:@"@chatroom"])
            {
                NSLog(@"selfContact ==== %@",selfContact);
                if( knSource == nil){
                    NSString *aaa = [selfContact.m_nsUsrName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
                    NSLog(@"length=%lu,%@",(unsigned long)aaa.length,aaa);
                    NSArray *result = (NSArray *)[objc_getClass("CContact") getChatRoomMemberWithoutMyself:knToUsr];
                    
                    
                    
                    if ([knContent hasPrefix:@"#所有人"]){ // 前缀要求
                        NSString *subStr = [knContent substringFromIndex:4];
                        
                        
                        NSMutableString *string = [NSMutableString string];
                        [result enumerateObjectsUsingBlock:^(CContact *obj, NSUInteger idx, BOOL * _Nonnull stop) {
                            
                            [string appendFormat:@",%@",obj.m_nsUsrName];
                        }];
                        
                        
                        NSString *sourceString = [string substringFromIndex:1];
                        wrap.m_uiStatus = 3;
                        wrap.m_nsContent = subStr;
                        wrap.m_nsMsgSource = [NSString stringWithFormat:@"<msgsource><atuserlist>%@</atuserlist></msgsource>",sourceString];

                        
                        int type2 = wrap.m_uiMessageType;
                        NSString *knFromUser2 = wrap.m_nsFromUsr;
                        NSString *knToUsr2 = wrap.m_nsToUsr;
                        NSString *knContent2 = wrap.m_nsContent;
                        NSString *knSource2 = wrap.m_nsMsgSource;
                        NSString *message2 = [NSString stringWithFormat:@"type=%d--knFromUser=%@--knToUsr=%@--knContent=%@--knSource=%@",type2,knFromUser2,knToUsr2,knContent2,knSource2];
                        
                          NSLog(@"message2 =======  %@",message2);
                    }
                    
                }
                //
                //
                
                //                }
                
                
            }
            
        }
    }
    NSLog(@"wrap =====  %@,=====%@",wrap.m_nsContent,wrap);
    %orig;
    //    NSString *userName = wrap.m_nsUsrName;
    
    
}
%end

相关文章

  • iOS反编译-hook微信之艾特所有人

    研究了一段时间反编译逆向工程,只是略微了解了一些皮毛,最近忙的事情太杂,就简单写一下吧。在文章开始之前,首先感谢"...

  • Block底层hook

    Block内存关系Block经典问题循环引用&解决Block底层分析Block底层HooK 前言 如何反编译出微信...

  • ios逆向工程链接

    逆向论坛 iOS冰与火之歌番外篇 - 在非越狱手机上进行App Hook 给微信加 hook 尝试记录 iOS 逆...

  • 微信技术协议

    微信协议 企业微信hook逆向 微信接口 pc企业微信hook接口,企业微信营销软件,企业微信群发 功能列表: 企...

  • iOS App Hook(微信) 之 JSPatch

    打开Xcode, 新建Project, 选择 iOSOpenDev 中 CaptainHook Tweak,将 J...

  • iOS 逆向hook微信

    参考资料 分分钟让你在 微信运动 霸占榜首 一步一步实现iOS微信自动抢红包(非越狱) 给微信加 hook 尝试记...

  • iOS 艾特、话题功能实现,支持OC、Swift

    目的 仿用于仿微博、微信、钉钉的艾特(@)功能【话题功能类型处理】【swift 已经支持】 艾特所在的特殊文本不支...

  • ios(越狱) 应用脱壳反编译hook教程 (系统ios11.3

    为什么会有这边博文? 因为公司原因,领导又让我捡起荒废了一年多的ios,了解对ios应用脱壳以及反编译hook相关...

  • iOS逆向之HOOK原理

    iOS逆向之HOOK原理 HOOK概述 HOOK(钩子) 其实就是改变程序执行流程的一种技术的统称!image.p...

  • 勿忘国耻|140字微小说

    正上着班,突然微信提示有新消息,原来是有个群员A艾特了所有人。 A说: “今天听到警笛响了很久,是有什么大事吗?”...

网友评论

  • 偏北风23级:OK 刚刚验证过 没问题 就是版主写的太过于复杂
    偏北风23级:@zombieEngineer 这是我去年弄的 好久没搞这块了 上面是之前的代码 应该区别不大
    偏北风23级:@zombieEngineer %hook CMessageMgr

    - (void)AddMsg:(id)arg1 MsgWrap:(id)arg2 {

    if ([arg1 containsString:@"chatroom"]) {
    if ([((CMessageWrap*)arg2).m_nsContent hasPrefix:@"@所有人"]) {
    NSString *subStr = [((CMessageWrap*)arg2).m_nsContent substringFromIndex:4];

    NSMutableString* content = [NSMutableString new];

    NSMutableString* source = [[NSMutableString alloc] initWithString:@"<msgsource><atuserlist>"];

    int i = 0;

    for(CContact* contact in [%c(CContact) getChatRoomMemberWithoutMyself:arg1]) {
    if (i == 0) {
    [content appendFormat:@"@%@",contact.m_nsNickName];
    [source appendFormat:@"%@",contact.m_nsUsrName];
    }
    else {
    [content appendFormat:@" @%@",contact.m_nsNickName];
    [source appendFormat:@",%@",contact.m_nsUsrName];
    }

    i++;
    }

    [content appendString:subStr];

    [source appendString:@"</atuserlist></msgsource>"];

    ((CMessageWrap*)arg2).m_nsContent = content;
    ((CMessageWrap*)arg2).m_nsMsgSource = source;

    NSLog(@"cmessagewrap %@ %@",source,content);
    }
    }

    %orig;
    }

    %end
    zombieEngineer:怎么个实现法?我试了下貌似不行
  • 9de977a656f2:作者的文章写得让我感动,也解除了我心中的疑惑,群主单身么,给你介绍女朋友
  • 馬夫:你好!请问一下,非群主编辑群公告问题解决了没,我玩的非群主删除群成员,出现的问题估计和你一样。
  • 萌小菜:能否分享下代码呀。。学习下。。
  • 0ebaf7f7bc96:请教一下是否了解微信@功能实现的原理
  • 05e83f239b72:没用啊,微信啥版本啊
  • Coding01:共享代码吗?
  • 清無:so diao...
    空壳子XJ:@菲拉兔 :sweat: :cry:
    清無:@小黑丶 万一被群主踢了怎么办?你回头再hook下,看能不能把群主给踢了,😄😆
    小黑丶:@菲拉兔 是站在别人的肩膀上。:smile:
  • 337b94dc718f:有意思
    小黑丶:@Echo_D :smile::smile:

本文标题:iOS反编译-hook微信之艾特所有人

本文链接:https://www.haomeiwen.com/subject/ysghettx.html