Divvy个人感觉是最棒的一款窗口管理软件了~, 但是它动不动就会提示个五秒的窗口让你注册License,最近小试牛刀完IOSApp, 它给我提供一个入门的机会…

工具准备


mac上的逆向其实比较省, 你不需要额外的砸壳,直接就能能从包里面拿到执行文件.
class-dump 头文件.
用Hopper打开,反汇编一下方便待会查看.
然后神器依旧是monkeyDev, 它帮我们省去注入.dylib 和 重签名等”繁杂步骤”~

入口分析

本来大多数的步骤一定是从view开始, 有一款神器就[interface inspector], 但总会报错一些乱七八糟的问题,暂时还没调好, 于是乎我粗糙的从hopper搜索”Register”,(如果一开始搜的是首字母小写的话可能不会饶那么弯…),结果是这样子的,

也查到其他无关的,最后确定就是这里,伪代码和汇编看并没有看出什么头绪,于是乎先看看有没有调用这里这个类相关.

追踪前,这里有一款强大的工具说下:
frida-trace: frida-trace -m “-[PTHotKeyCenter _]” Divvy

用法是frida-trace -m “<+类方法/-实例方法>[类名 方法名<_代表全部>]”
执行后它会自动帮你生成跟踪的js文件,然后监听所指定的方法.

一开始觉得吧, PTHotKeyCenter不像是很关键的类, 也是没怎么写Mac的App的原因,但还是监听了一下:

我尝试打开它,然后随便输入一串号码注册, 发现他怎么整都只打印这些, 而且就在我使用快捷键的时候~
随意也明白了,这就是”热键”,仅此而已…

动态调试

进行到这里其实是无头绪的, 然后想着是从mondev进行动态调试,看看能不能从调用栈看看这里的情况.
想着hook哪个方法的时候,脑子冒个灵光,想到了这个view的展示, 我就输入”)show”看看有没有什么可疑的,结果:
十分意外第一个方法,很明显这个方法应该是展示注册这个View的,而且还待会参数时间.
如果是这个方法果然没错, 那么我可能得到,一是找不到更好的hook方法,duration的参数改为最少的时间,或者可以尝试return这部展示的操作. 其次先Hook下看看调用栈,是什么决定它展示也是可以的, 于是开始我的Hook代码.
MonkeyDev默认是subStrate的hook方法代码, 当然也是可以替换成其它的(按道理当然可以~):
这是一开始的代码:

但是允许会报错,其中需要修改:

1
2
3
4
5
6
7
8
9
10
11


1

2

3

4


1
2
3
4
5
6
7
8
9
10
11


static void newHookFunc(AppController\* self,SEL \_cmd,id array){ // }

//replacet to | //下面

static void newHookFunc(AppController\* self,SEL \_cmd,id arg1, id arg2){ // }

// 需要指明多少个参数, 不知道参数类型就使用泛型id


build一下且进入调试后, 用时在static void newHookFunc(AppController* self,SEL _cmd,id arg1, id arg2){ 这里Xcode断点一下:
但如果直接执行还需要做两部:

然后进入注册页面,果不其然的断点触发.然后我打印了一下调用栈:

是的,一眼看去都是非Divvy调用栈的可用信息~ 有点陷入僵局了.

人品才是最高逆向

有点朦胧的时候, 我回到- (void)showLicensingWindow:(id)arg1 withTimeoutDuration:(int)arg2;这个方法中, 结果真的很意外,其中有个地方很雷人:

- (BOOL)verifyLicense;这真的不能再明白的一个方法了,不管是不是依然开始Hook一下.mac的逆向就是各种Hook~
hook代码如下:

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


1

2

3

4

5

6

7

8

9

10

11

12

13


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23


#import "Divvy.h"

#import "substrate.h"

@class AppController;

static BOOL (\*originFunc)(AppController\*,SEL,id);

static BOOL newHookFunc(AppController\* self,SEL \_cmd,id array){

return YES;

}

static void \_\_attribute\_\_((constructor)) initialize(void) {

MSHookMessageEx(objc\_getClass("AppController"),@selector(verifyLicense), (IMP)&newHookFunc, (IMP\*)&originFunc);

}


依然Build一下跑起来, 真的很意外,因为启动的时候默认也是要弹一次注册框的, 这次启动并没有,启动后直接什么也展示(而且我忘记断点了). 手动选到注册框看一下怎么肥事:

真的很意外, 就像小黄书的作者狗神中说的,运气也是逆向的一部分.嗨森~

总结

谁说人品不是逆向的一部分呢, 实践就能找到快乐.第一次Mac的调试竟然这么快就收获自我成就感,赚到了.
App的话我打包上传到这里

特别鸣谢大佬协助:
monkeyDev之MAC应用
庆哥的一篇文章走进MAC逆向
膜庆哥