发送微信名片消息的思路


#1

需求: 发送微信名片消息

操作步骤:
1.查看了微信名片消息的类为ShareCardMessageCellView,没有找到相关线索
2.hopper看了下CMessageMgr的方法,没有找到有关card相关的内容
3.尝试给CMessagerMgr打断点打不上

(lldb) breakpoint set --selector AddMsg:MsgWrap:
error: wechatHookTest.dylib(0x00000001050e8000) debug map object file ‘/Users/yudun1989/Desktop/wechat/wechathooktest/.theos/obj/debug/arm64/Tweak.xm.3276db1b.o’ has changed (actual time is 0x5964d570, debug map time is 0x59642e07) since this executable was linked, file will be ignored
Breakpoint 1: no locations (pending).
WARNING: Unable to resolve breakpoint to any actual locations.

求解


#2

通过内存地址来打断点:

[  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

结果打到了另外一个方法上。。


#3

call (void*)method_getImplementation((void*)class_getInstanceMethod((void*)objc_getClass("%s"),@selector(%s))


#4

是说hook住方法然后 调用拿到地址吗?

lldb有什么办法吗。
或者cycript

每次hook都要重启app好麻烦。


#5
(lldb) help call
     Evaluate an expression on the current thread.  Displays any returned value with LLDB's default formatting.
     Expects 'raw' input (see 'help raw-input'.)

Syntax:

Command Options Usage:
  call <expr>


'call' is an abbreviation for 'expression --'

lldb有个call命令


#6
(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

好吧。看起来打完断点后他就是会显示WeChatClearDataItem::compareTime(std::__1::shared_ptr const&, std::__1::shared_ptr const&) + 15837644, add` 这一段,不知道是啥原因。。

_< 接下来进行不下去了。不知道这个发送名片该怎么弄了。。。囧。:no_mouth:


#7

因为那个oc方法本身没有符号表所以用的是上一个符号+偏移的方式来表示而已


#8

谢谢。明白
请问下如果想要做发送微信名片消息,这个有什么思路吗?
看了 https://github.com/iosre/WeChatRobotForExample/
大致明白发送文本消息其实是通过LogicController 的formText来构造文本消息

但是发送名片的话不知道该怎么发,通过刚才的方式断点到 CMessageMgr 调用AddMsg:MsgWrap方法了。
但是没有想清楚接下来该怎么弄。

看了之前抢红包的帖子,发现都是基于UI上的操作(l类似于手动点击拆红包)。但是对于发送名片这个事情来说,UI操作没有那么简单。所以没有想清楚具体该怎么弄。


#9

我没兴趣凑合微信那些不干不净的活计。抱歉


#10

…好吧…虽然其实并不是不干不净的东西…


#11

sorry。没关系


#12

如果断到了AddMsg:MsgWrap,可以把参数打印出来看看,就知道名片应该是一个App message


#13

你不能保证拼接的数据是否全是否对 模拟点击两三下最简单辣


#14

名片这个不像其他消息,得先点进公众号,然后再选择联系人点击。太麻烦。


#15

调用 ShareFriendOnChatLogicController 类的contactShareMsgFromUser: toUser: sharedContact:方法可以得出CMessageWrap类型的对象,再拼接CMessageMgr的参数,调用AddMsg: MsgWrap:方法即可!


#16
+ (void)sendPersonalCardWithUserName:(NSString *)username toUser:(NSString *)toUser { CContact *contact = [[WXContactMgr defaultMgr] getContactByName: username]; NSString *content = [contact xmlForMessageWrapContent];
NSString *fromUser = [WXCommonHelper getCurUsrName];

Class messageWrapClass = NSClassFromString(@"CMessageWrap");
CMessageWrap *msg = [(CMessageWrap *)[messageWrapClass alloc] initWithMsgType: 0x2a];
[msg setM_nsFromUsr: fromUser];
[msg setM_nsToUsr: toUser];
[msg setM_nsContent: content];

MMNewSessionMgr *sessionMgr = [WXCommonHelper getService: @"MMNewSessionMgr"];
[msg setM_uiCreateTime: [sessionMgr GenSendMsgTime]];
[msg setM_uiStatus: 0x1];

CMessageMgr *messageMgr = [WXCommonHelper getService: @"CMessageMgr"];
[messageMgr AddMsg: toUser MsgWrap: msg];
INSLog(@"WXMessageMgr.sendPersonalCardWithUserName:[fromUser:%@, toUser:%@, content: %@]", fromUser, toUser, content);

}