老牌笔记软件 myBase Pro 破解

0x01 Intro

在整理之前的笔记,突然想起以前小龙猪带队的时候介绍的MyBase,那会儿各类支持多平台同步的笔记软件还没有兴起,MyBase可以算是非常老牌的了。
现在同步网盘也很发达,加之MyBase Pro版本是支持使用AES对本地数据库加密的,且支持跨平台,于是决定把之前撸站的一些敏感资料保存到本地来。
去官网看了一眼( http://www.wjjsoft.com/store.html ),本来打算直接购买一个License,但是发现单用户版要80$,瞬间有一点屌丝上身,加之前不久无敌大哥给了我一个Hopper的License,在将Hopper升级到最新版之后,决定手动Crack掉Mybase。

首先让我们以一个标准的破文起头( 十分怀念破文生成器 )

软件名 myBase Pro
版本 v7.0 b27
URL http://www.wjjsoft.com/downloads/myBase-Desktop-Ver700b27-Pro-MacOSX.dmg
平台 macOS 10.13.3

0x02 Find Key JMP

下载好之后解压到 /Application/myBase.app ,打开体验下功能。非注册版的限制主要在时间上,过了试用时间后则无法使用,所以第一个想到的破解方式就是Patch时间限制达到无限试用。点击了菜单中的Register随意输入几个注册码弹出无效注册码提示( 此时最好将 /Application/myBase.app/Content/MacOS/lang/ 下的chs.ini暂时改名,以便于直接查看弹出的英文提示框,便于后面分析 ),到这里能想到的第二个方法就是经典的字符串搜索加爆破大法了。
祭出Hopper,选择直接读取二进制文件,找到 /Application/myBase.app/Content/MacOS/mybase 并加载,等待Hopper分析完之后就可以开始调试了。直接在Hopper的Str标签中搜索 invalid ,没有发现刚刚弹出的类似提示,继续搜索 license 也是几处无关痛痒的,但是刚刚提示中还有一句 In case of typos, copy/paste license key codes (2-line) instead of typing them manually. 我们直接搜索copy,同时可以在数据段中直接按x查找它的引用,如下图所示:

点进去引用之后,可以看到Hopper已经帮我们分析相关符号了,在注释中可以看到一些调用的名称,从这里可以看出mybase采用了Qt框架来开发。如果不习惯直接看反汇编代码的话,Hopper也提供了类似IDA的f5相同的功能,点击右上角的带有if字样图标即可,同时我建议勾选 no code dup 这个选项,这更符合我们看反汇编代码时的习惯,如下图所示:

Ps: 插句题外话,我自己认为不错讲Qt开发的书籍有《Mastering Qt5》,其中有部分分析了Qt的信号和槽机制的C++实现,这有助于我们在看反汇编时,加深对使用Qt框架编写的程序的理解。

从整段代码可以看出,这里创建了一个QDialog对话框,同时初始化了这个对话框中的相关控件,以及通过Connect函数连接了OK按钮以及Cancel按钮等的信号与槽。但从整段代码中来看,没有看到长跳以及类似的注册码运算函数。为了方便后续调试,我将上图中的sub名称改为了ShowRegisterDlg。关于跟进Button事件不是这里的重点,如何追踪槽函数52pojie上已经有一篇不错的文章了( https://www.52pojie.cn/thread-497018-1-1.html )。我们来查找ShowRegsiterDlg的引用,看看上层还有什么函数调用了,这里只发现一个引用,且中间代码量较少只是简单的Call,所以我们把 ShowRegisterDlg 这个唯一引用它的sub命名为 CallShowRegisterDlg 。继续查找 CallShowRegisterDlg 的引用,发现其返回值作为了QDialog::exec()的参数,且在附近代码处出现了一个长跳转(if中的大段代码),所以伪代码大概像这样:

1
2
3
4
5
6
7
8
9
10
11
12
var result = CallShowRegisterDlg(&x);
if (QDialog::exec(&x) == something) {
if( Func() ) {
... lots of code A ...
} else {
... lots of code B ...
}
}

观察长跳if中代码可以发现类似Base64编码的字符串,尝试进行解码发现不行,估计是类似AES之类的加密只是将Hex编程成了Base64的形式,从注释中可以到这一段Base64最终被传入 _CMsgBox::_CMsgBox,这更加深了条件跳转之前的那个Call是关键Call,而这个跳转是关键跳的想法。且回想到刚刚在搜索字符串时,并未找到相关Invalid以及License字样的提示,可以大胆的猜测作者为了防止调试人员快速找到验证注册的函数,所以对这些字符串进行了加密。如下图所示,我们先对相关分析进行一些标记:

我们保持一下Hopper的工程文件为Mybase.hop,然后使用 Modify —> Assemble Instruction 来修改汇编指令,这里需要注意的地方是,可能和OD不同,在Hopper修改指令,除了需要填写操作指令外,操作数也需要一并带上,修改完成后,我们使用 File —> Produce New Executeble 来覆盖原来的/Application/myBase.app/Content/MacOS/mybase(记得做好备份)。

打开Patch过的可执行文件,在Register的对话框中随意输入一些子串,点击确定提示成功。重新打开之后,发现还弹出了试用即将过期的Nag框,说明刚才的关键Call中可能还有其他地方需要修改。

0x03 Analyze Register Func

我们先还原刚才关键跳处的修改,进入关键Call进行分析:

可以看到在sub开始很近的地方有一个Call,紧接着一个长跳。跳转执行的代码为 xor eax,eax,使用亦或清零了eax的值,紧接着关键Call就返回了(实际从刚才的Patch测试可知,关键Call应该为这里长跳的前面的Call,为了统一说法这里沿用)。所以可以大胆的推测出 sub_10018f5a0 为注册码的运算验证的部分,且查找引用来看,有多处调用,而我们前面分析找关键跳的地方,仅仅只是注册那一部分的调用,所以这个Sub才是真正的注册码验证的关键Call。我们跟进 sub_10018f5a0 进行分析,发现有大量的字符串运算及小跳转,因为不着重分析算法,我们可以使用Hopper的Graph功能看下整个Call的执行流程,如下图所示:

可以看到这个Call最终执行完了返回前对 al 进行了赋值,如果我们只修改这个Call返回后最近的一个条件跳转的话,效果还是和刚刚上一小节修改的方式一样,只会对Register这个流程生效。所以这里我们可以给 al 执行赋值,通过修改汇编指令为 mov al,1,然这个Call恒返回真值。那么其他调用这个Call的验证部分也都能通过了,不用多处Patch。修改导出后,我们运行随意在注册框中输入就能成功注册了,效果如下图:

0x04 Summary

Qt的程序有一点其实不太好分析,就是在不理解信号与槽的机制在C++代码层是如何体现的,在汇编中又是如何体现的。myBase此版本作者只是加了一小段关键字符串的加密,就给找到关键跳增加了些难度,但总体来说还是比较简单的。

最后附上破解好的Bin,直接替换即可。
https://transfer.sh/vEhWV/mybase