本文将带你了解IOS开发入门iOS反编译实例之hook微信艾特所有人功能实现,希望本文对大家学IOS有所帮助。
研究了一段时间反编译逆向工程,只是略微了解了一些皮毛,最近忙的事情太杂,就简单写一下吧。
这篇文章给的一些方法和启示.下面说一下我的一些做法,可能会有很多问题.
1.需求
众所周知,在通常情况下,微信只有是群主才能艾特所有人,发消息或者群公告,目前的需求就是非群主,也能艾特群里的所有人。
2.尝试方法
1> 尝试非群主编辑群公告,初步判定是微信发群公告是通过向微信发送一个网络请求,然后由微信进行通知(研究了一段,发现效果不是太好)
2>通过一一艾特群里每一个成员,然后修改发送的内容,再调用微信的发消息方法进行实现。
3.实现方法
1.首先要了解的微信一个很重要的类,CMessageMgr,看名字应该是微信的一个消息管理的类,在class-dump微信头文件之后,找到该类,然后看它的一些属性和方法,下面这两个方法大概就是微信发消息函数和消息处理函数,我们要做的就是hook这两个函数,
Paste_Image.png
2.我在此处用的是通过theos来编写hook,theos的一些安装和使用方法,可以通过iOS应用逆向工程第2版这本书来操作,使用方法已经十分详细.
4.初始化工程
1.创建tweak工程
WechatIMG16.jpeg
2.打开目录,会看见makefilecontrol
Tweak.xm三个文件.
2.1makefile是指定工程用到的文件,框架,库等信息.将整个过程自动化,默认的文件内容
?
1
2
3
4
5
6
7
8
9
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的名字
?
1
ioswechatselectall_FRAMEWORKS = UIKit CoreFoundation Foundation CoreGraphics QuartzCore Security
指定处理器架构
?
1
ARCHS = armv7 arm64
指定SDK版本,最低7.0
?
1
TARGET = iphone:latest:7.0
可以设置安装hook设备的ip地址 进行安装
?
1
THEOS_DEVICE_IP = 192.168.1.159
最终完整的makeFile文件为
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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.2control文件
control文件相比来说就比较简单,记录了deb包管理系统的所有的基本嘻嘻
?
1
2
3
4
5
6
7
8
9
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语法,包含%hook,%log,%orig三个预处理指令
2.3.1
%hook 指定要hook的class, 必须以end结尾
%log打印一些信息
%orig非常重要,使用在%hook内部,执行hook函数的原始代码,如果不添加%orig,则原始函数不会得到执行
4.编写代码
4.1先从一个简单的hook代码开始,
我们要做的是hook微信的收发消息函数,在一开始,我已经告诉大家微信收发消息函数是哪两个,现在我们就把他hook掉,看看他里面携带的一些参数
4.1.1Tweak.xm代码
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
%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
①然后通过 make package install方法,讲hook注入,然后收发消息,查看终端打印结果
②当我们发送一个普通文字消息时,终端会打印
?
1
2
3
4
: 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)"}
: 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)"}
发送一个语音消息
?
1
2
3
: AsyncOnAddMsg wrap ====== {m_uiMesLocalID=9, m_ui64MesSvrID=0, m_nsFromUsr=wxi*r22~19, m_nsToUsr=tia*103~11, m_uiStatus=1, type=34, msgSource=""}
: 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
?
1
AsyncOnAddMsg wrap ====== {m_uiMesLocalID=8, m_ui64MesSvrID=4596545622562551918, m_nsFromUsr=tia*103~11, m_nsToUsr=wxi*r22~19, m_uiStatus=3, type=1, msgSource=""}
从里面可以得到一些基本的信息,m_nsFromUsr,m_nsToUsr,m_uiStatus,type
4.1.2 尝试在群里艾特一个好友,然后看看打印结果是什么
?
1
2
3
4
:AsyncOnAddMsg wrap ====== {m_uiMesLocalID=2, m_ui64MesSvrID=0, m_nsFromUsr=wxi*r22~19, m_nsToUsr=1234567890@chatroom, m_uiStatus=1, type=1, msgSource="weixinzhanghao"}
:AddMsg wrap ====== {m_uiMesLocalID=2, m_ui64MesSvrID=0, m_nsFromUsr=wxi*r22~19, m_nsToUsr=1234567890@chatroom, m_uiStatus=1, type=1, msgSource="weixinzhanghao"}
会发现,m_nsToUsr这个属性的不再是一个人的id,而是由一串数字+@+chatroom组成的一个房间号,暂且称它为群号,type的类型还是1,文本类型,而最后的msgSource也不再是一个空值,而是"weixinzhanghao",类似于xml格式的一个字符串在标签里的就是你要艾特好友的微信帐号.
4.1.3 那么如何才能拿到群里,其他人的这个微信帐号呢?再次感谢https://www.jianshu.com/p/189afbe3b429 这篇文章的作者,和蒸米大神,从他们的文章和代码里,知道了微信另外一个很重要的类CContactMgr,看名字应该是联系人的管理类,在微信头文件里可以看到,他的一些属性和方法,
Paste_Image.png
获取自己contant属性然后再去查找有没有CContact这个类,
Paste_Image.png
,再去看他里面的属性和方法,
Paste_Image.png
通过+ (id)getChatRoomMemberWithoutMyself:(id)arg1;这个方法,可以获取到处自己以外的所有群成员,后面要传的参数就是前面提到的1234567890@chatroom微信群号.得到一个数组,数组里面的值就是除你以外的所有群成员.
4.2 创建一个.h文件,将需要的一些微信的类的头文件导入,以求编译通过,这里就不再太多描述.
通过打印wrap的class ,可以得知它是CMessageWrap类型,里面的一些属性有
都是我们刚才打印得到的信息.而m_nsContent应该就是发送消息的内容,可以通过打印得到
Paste_Image.png
?
1
wrap ====== CMessageWrap
4.3 现在大概的了解的内容就做完了,然后开始编写代码,我们需要自己定义一个格式,来规范在输入什么时进行艾特所有人操作,此刻我们定义的一个格式是以 !all 开头.
在- (void)AddMsg:(id)arg1 MsgWrap:(CMessageWrap *)wrap里,加入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 通过[wrap.m_nsContent hasPrefix:@"!all"]判断是否为约定的格式
如果以上几个条件都满足,那么可以再进行我们的hook操作.
4.4 修改wrap的格式内容
4.4.1 通过上面说过的getChatRoomMemberWithoutMyself方法得到群里除自己以外的所有人,遍历数组,取出数组每个属性(CContact)的m_nsUsrName值,拼接成一个字符串.
4.4.2 修改wrap.m_nsContent 的内容,我们不希望被别人看到我们约定的艾特所有人格式,所以通过subStringFromIndex方法, 去掉前缀,取后面的内容作为wrap.m_nsContent 的内容
4.4.3 最重要的设置m_nsMsgSource为[NSString stringWithFormat:@"%@",sourceString];sourceString就是拼接好的字符串,
4.5 将以上内容修改好后,然后在函数的结尾调用%orig也就是调用原始函数,由于经过我们hook,我们发的带格式的消息的m_nsMsgSource已经附有新值,微信就会以为我们艾特每个好友,从而实现艾特所有人的功能.
5.实现效果
1.我不是测试11的群主,我也没有办法艾特所有人
Paste_Image.png
2.按照格式输入测试之后,就会实现艾特所有人的功能
Paste_Image.png
3.其他成员收到的信息
Paste_Image.pngPaste_Image.png
应很多人要求把代码贴一下,很久以前的东西了,不知道现在是否能继续使用
<
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之IOS频道!