1
2
https://wangjinli.com/blog/2016/08/12/jailbreak-development-2-wechat-dice/
http://bbs.iosre.com/t/topic/8717

想通过tweak发送名片消息, 之前通过itchat, wxpy发过名片消息。现在尝试下iOS下的tweak如何发名片消息。
微信里面发送文本消息主要通过全局的LogicController实现。查看hopper可以看到formTextMsg和formImageMsg的方法。但是不太清楚名片消息如何构造,因为查看headers并没有发现类似的方法。所以看下如何自己研究。
以下记录研究过程:

  • 查看了微信名片消息的类为ShareCardMessageCellView,没有找到相关线索。其实长按此view可以转发名片,但是通过UI的方式来发送名片太繁琐。所以先放弃了
  • hopper看了下CMessageMgr的方法,没有找到有关card相关的内容
  • 尝试给CMessagerMgr打断点。根据论坛同学提供的方法,找到两种方式来打断点,一个是通过hopper中的偏移地址,一个是通过lldb的method_getImplementation 拿到方法指针
1
2
3
4
5
6
7
8
9
10
11
12
通过内存地址来打断点:
[ 0] 0x000000000002c000 /usr/lib/dyld(0x000000012002c000)
[ 1] 0x00000000000c8000 /var/containers/Bundle/Application/029BAFCF-953E-4D4A-9F82-77462B0D9BB1/WeChat.app/WeChat(0x00000001000c8000)
ASLR偏移量:0x00000000000c8000
偏移后基地址: 0x00000001000c8000

hopper看到AddMsg:MsgWrap地址为0x0000000102382640
In [3]: hex(0x0000000102382640+0xc8000)
Out[3]: '0x10244a640'

(lldb) br s -a 0x10244a640
Breakpoint 4: where = WeChat`ClearDataItem::compareTime(std::1::shared_ptr const&, std::1::shared_ptr const&) + 5480180, address = 0x000000010244a640
1
2
3
4
5
(lldb) call (void*)method_getImplementation((void*)class_getInstanceMethod((void*)objc_getClass("CMessageMgr"),@selector(AddMsg:MsgWrap:)))
(void *) $3 = 0x0000000102df3118
(lldb) br s -a 0x0000000102df3118
Breakpoint 1: where = WeChat`ClearDataItem::compareTime(std::__1::shared_ptr<ClearDataItem> const&, std::__1::shared_ptr<ClearDataItem> const&) + 15837644, address = 0x0000000102df3118
(lldb) c

虽然发送名片确认仍然跟发送文本文字一样都是通过CMessageMgr来发送。但是lldb仍然没有思路。(汇编太差了)

于是想到cycript,发送文字的时候hook一下CMessageMgr中的AddMsg:MsgWrap方法。文档在http://www.cycript.org/manual/

1
2
3
4
5
6
cy# @import com.saurik.substrate.MS
{getImageByName:(extern "C" void *MSGetImageByName(char const*)),findSymbol:(extern "C" void *MSFindSymbol(void *, char const*)),hookFunction:function (r,i,n){var e,t;t=typeid(r);if(n==null||typeof n==="undefined")e=null;else{e=new(new Type("v").pointerTo().pointerTo());n.$cyi=function(){return t(e.$cyi).apply(null,arguments)}}MSHookFunction(r.valueOf(),t(i),e)},hookMessage:function (t,r,s,e){var n,i;i=r.type(t);if(e==null||typeof e==="undefined")n=null;else{n=new(new Type("v").pointerTo().pointerTo());e.$cyi=function(){var e;e=this;return i(n.$cyi).apply(null,[e,r].concat(a.call(arguments)))}}MSHookMessageEx(t,r,i(function(t,e){return s.apply(t,a.call(arguments,2))}),n)}}
cy# MS.hookMessage(CMessageMgr,@selector(AddMsg:MsgWrap:), function(arg1, arg2){
var alert = [[UIAlertView alloc] initWithTitle:[arg1 description] message:[arg2 description] delegate:nil cancelButtonTitle:@"cancel" otherButtonTitles:@"yes", nil];
[alert show];
}, NULL)

可以打出来具体两个类的description.这样只需要顺着description中的信息自己alloc, init构造即可以发送名片消息了。

具体名片消息如何拿到具体参数呢,我们先拿到方法的具体地址打好断点。等到函数执行的时候pinternals

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(lldb) call (void*)method_getImplementation((void*)class_getInstanceMethod((void*)objc_getClass("CMessageMgr"),@selector(AddMsg:MsgWrap:)))
(void *) $3 = 0x0000000102df3118
(lldb) br s -a 0x0000000102df3118
Breakpoint 1: where = WeChat`ClearDataItem::compareTime(std::__1::shared_ptr<ClearDataItem> const&, std::__1::shared_ptr<ClearDataItem> const&) + 15837644, address = 0x0000000102df3118

(lldb) pinternals $x3
(CMessageWrap) $11 = {
MMObject = {
NSObject = {
isa = CMessageWrap
}
}
m_bIsSplit = false
m_bNew = true
m_uiMesLocalID = 0
m_n64MesSvrID = 0
m_nsFromUsr = 0x00000001278b4f90 @"wxid_zvl16nyvtkdh12"
m_nsToUsr = 0x0000000128d40ca0 @"chinaliyudong"
m_uiMessageType = 42
m_nsContent = 0x0000000128906a40 @"<msg username=\"gh_6c02c9119583\" nickname=\"ddd\" fullpy=\"ddd\" shortpy=\"\" alias=\"fupingjia\" imagestatus=\"3\" scene=\"17\" province=\"Hebei\" city=\"China\" sign=\"、出行之路更美好\" sex=\"0\" certflag=\"24\" certinfo=\"网络科技服务中心\" brandIconUrl=\"http://mmbiz.qpic.cn/mmbiz_png/IdqOXlib7oo1n8EBQuvCKDWv4MwGWNXSKqVzoCqVzaXgkIfJW3l3Fvu03DoWWguCHVMh6FKGPmkoo20fx4FSibHg/0?wx_fmt=png\" brandHomeUrl=\"{&quot;RoleId&quot;:&quot;1&quot;,&quot;IsShowHeadImgInMsg&quot;:&quot;1&quot;,&quot;RegisterSource&quot;:{&quot;IntroUrl&quot;:&quot;http://mp.weixin.qq.com/mp/getverifyinfo?__biz=MzUyNDAyMjM5MQ==&amp;type=reg_info#wechat_redirect&quot;,&quot;RegisterBody&quot;:&quot;&quot;},&quot;IsTrademarkProtection&quot;:&quot;0&quot;,&quot;MMBizMenu&quot;:{&quot;button_list&quot;:[{&quot;native_url&quot;:&quot;&quot;,&quot;id&quot;:429191183,&quot;key&quot;:&quot;rselfmenu_0&quot;,&quot;type&quot;:0,&quot;value&quot;:&quot;&quot;,&quot;name&quot;:&quot;拼车信息&quot;,&quot;sub_button_list&quot;:[{&quot;native_url&quot;:&quot;&q"...
m_uiStatus = 1
m_uiImgStatus = 1
m_uiMsgFlag = 0
m_uiCreateTime = 1500942006
m_nsPushContent = nil
m_nsPushTitle = nil
m_nsPushPrefix = nil
m_nsPushBody = nil
m_nsMsgSource = nil
m_nsRealChatUsr = 0x00000001039e7328 @""
m_dtThumbnail = nil
m_uiSendTime = 0
m_uiEmojiStatFlag = 0
m_nsPattern = nil
m_bForward = false
m_bCdnForward = false
m_uiPercent = 0
m_uiDownloadStatus = 0
m_extendInfoWithMsgTypeForBiz = nil
m_extendInfoWithMsgType = nil
m_extendInfoWithFromUsr = nil
m_nsLastDisplayContent = nil
m_isTempSessionMsg = false
m_isEnterpriseMsg = false
m_sequenceId = 0
m_bIsFromBrandSession = false
m_bIsBrandSendMass = false
m_uiBizChatVer = 0
_m_forwardType = 2
m_nsKFWorkerOpenID = nil
m_nsBizClientMsgID = nil
m_nsBizChatId = nil
m_nsAtUserList = nil
watchMsgSourceType = 0
m_nsDisplayName = nil
_m_dicForwardParas = nil
}

之后直接构造一下应该就可以了