微信号:gh_37ebe37722aa

介绍:txx的笔记分享

Tweak With Mac QQ II

2017-02-28 09:23 txx

前言

上一篇文章,我们搞好了 API,在这篇文章我们把剩余的完成。简单思考一下,还差哪些东西:

  • 搜索结果 TableView 点击的响应函数

  • cmd + shift + z 唤起主窗口的响应函数

  • 看看能不能搞定头像?

  • alfred workflow 的封装

  • 如何更简单的 patch QQ

寻找响应函数

故技重施,lldb 挂上去看日志,希望在 Log 上找到目标函数,然而并没有。看到的只有按钮的日志收集,观察堆栈,看起来没有可疑函数。

看来这种投机取巧的方法,不能解决这个问题。于是我们来重新看一下头文件,我们发现 MQSearchViewController 实现了一个协议:ExtendedTableViewDelegate

这个协议实现了这么两个 Method:

@protocol ExtendedTableViewDelegate <NSObject>
- (void)tableView:(NSTableView *)arg1 didClickedRow:(long long)arg2; - (void)tableView:(NSTableView *)arg1 didDoubleClickedRow:(long long)arg2;@end

看起来 didClickedRow 是我们的目标,下个断点发现,果然是响应函数。然而 What’s Next? 貌似只能掏出 ida pro,因为是 64 bit 的 Mach-O 文件,我没有反编译器,凑合看汇编吧。

大量来打量去,发现…..这段代码疑似目标:

这两排代码,右侧的第一句话 AddBuddyController 看起来像是添加好友的对话框,我们就先不理他了。看左边这一排,干掉 ARC 插入的无用代码,我们可以注意到流程大概是这样的:

  1. clearSearchResult

  2. updateTokenfieldState

  3. showAioWithContact

  4. dismissResultPannel

这里可以注意到,showAioWithContact 这个方法非常可疑,我们给它下一个断点。完美,这个就是目标函数,于是对应 Hook 代码就该是这样的:

这里注意一下:这个函数是用作 Server 的 Callback,所以我们不能保证他是在哪个线程执行的,然而这个方法很明显是要在主线程运行。所以这里用 GCD 绕一下

Update 一下 dylib,发现这个 API 会强制显示 QQ 主窗口。

换句话说,解决了我们第二个问题:cmd + shift + z 唤起主窗口的响应函数。

至此,我们主要任务就算做完了。

Alfred 封装

Alfred 文档写的又臭又长的,我找了一个安装好的 Workflow — Colors。找到他的二进制文件,按照 alfred 脚本中的写法,传参数:

➜  Desktop /Users/xiaoxuantang/Library/Application\ Support/Alfred\ 3/Alfred.alfredpreferences/workflows/user.workflow.E1BD517C-A5B7-4020-9A36-80CA0DE5B2ED/colors  "#A"

得到了一坨 xml,整理了一下,模板就清晰多了。

<items>
    <item arg="#AA0000"> 
        <title> #AA0000 </title>
    </item>

</items>

对着构造了一个,得到了下面的效果:


然后发现 Alfred 3 支持 Json 了,所以并不需要这么蛋疼,构造成如下格式即可。

{"items": [    {        "title": "Desktop",        "arg": "~/Desktop",        "icon": {            "path": "~/Desktop"        }    } ]}

搞定头像

对于 QQ 群、讨论组,头像的存在并不重要,然而联系人还是很有用的,毕竟有多个宝贝儿的时候,你需要谁对谁。

还是从头文件入手,观察 Buddy 这个类,我们发现有这么一个方法:

- (id)displayImage;

用 lldb 强行调用一次发现,这玩意吐出来的是 NSBitmapImageRep。然而对于一个 Model,里面放了一个 bitmap 总觉得不太正常,严重的资源浪费,所以我觉得这玩意是个 lazyload,换句话说获取头像路径的方法应该就写在里面。

发现这里调用了 “GetHeadImageWithUin alawysonline WithStatus size “ (拼写错了不说,大小写乱七八糟的,实在是不能忍)

用 ida 跟进去,发现跳了好几次:

  • GetHeadImageWithUin:status:size

  • GetHeadImageWithUin:status:size:withDefaulImage: (大小写乱七八糟 default 还拼错了)

GetHeadImageWithUin:status:size:withDefaulImage: 中,发现一个新的 class:

BHProfileManager, 查看一下头文件,发现它有:getUserAvatarPathByUIN: 这么一个方法。看起来就是我们想要的,而 UIN 呢? Buddy 里面可以拿到。

于是我们有:

更新到 dylib,得到如下效果,到目前为止开发就算完成了。


Patch QQ

对于 QQ 没事就要 Yolo 一下实在是太蛋疼了。特别是 yolo 还没完,还要在此基础上干掉签名什么的。虽说这是 iOS 的标准解决方案,毕竟非越狱环境下只能这么搞,然而我们是 macOS 有更优雅的方法!

在看 Dyld 源码的时候,收获了一大堆环境变量,如图:

我们注意 DYLD_INSERT_LIBRARIES 这个方法,换句话说,我只需要在 QQ 启动前,加一个环境变量即可。

试一下:

DYLD_INSERT_LIBRARIES="libQQHook.dylib" /Applications/QQ.app/Contents/MacOS/QQ

达到期望效果,于是我们做一个 bash 替换掉 QQ 的二进制就好了~

小结

麻雀虽小,五脏俱全。这个小玩意看似实现简单,但涉及到的东西挺多的。最终代码开源在 Github 上,请点击阅读原文查看。

下一篇文章,不出意外将是我这周在东京参加 Try!Swift 期间更新,应该是相关内容,请长按下方二维码关注我。

 
糖炒小虾 更多文章 I have a pod, I have a cartha Tweak With Mac QQ I Tweak With Mac QQ II Tweak With Mac QQ I Tweak With Mac QQ I
猜您喜欢 (完整版)Facebook研发团队的高效秘诀 Python基础教程12:break 语句 MySQL字符集介绍及乱码解决方法 iOS 堆栈符号解析最佳实践 正在找工作的你,是否用尽了洪荒之力?