Sublime Text是一款强大的文本编辑器,在不注册的情况下也可以使用,但标题栏的未注册字样与时不时弹出的nag窗口有时也让人感觉很不爽,于是尝试对其注册过程进行分析与破解。
截至写本篇文章时,Sublime Text的最新稳定版本为3143版本。由于之前我们破解过其旧版本,所以对其注册机制还算比较了解(已将之前破解Sublime Text 3126版本时写的笔记整理成了博文,请见《Sublime Text 3126 Win32版本暴力破解过程》)。如果有心的话,大家不妨对比两个版本的注册机制和流程,看看从3126更新到3143版本这一年多的时间里,作者为了增大破解的难度做出了哪些努力。毕竟在攻与防的较量中,大家都在进步,我们在提高自己二进制代码分析能力的同时,其实也有幸见证了软件作者的成长。
一、第一次尝试
在上个版本的Sublime中,我们很快就查到了注册相关的逻辑,然后打开了局面。针对新版本,我们当然希望能够故伎重演,就看作者给不给我们这个机会了。
首先随意输入一串注册码,点击确定后弹出错误提示框,此时中断程序,查看调用栈如下图。
根据MessageBoxW的调用者地址即可回溯到Wrapper函数头部。
从调用栈中可以看到再上帧的返回地址为0x00449817,为了保险,我们在Wrapper函数的头部下断后,重新输入一次错误的注册码看看:
试图继续回溯时发现不是第一现场(ecx为0,而主调方是用ecx寻址的)
很明显,这里把ecx清掉了。于是用IDA的交叉引用功能查到了调用源。emmmm,是JMP过去的,并且在之前清了ecx的值,作者也变猥琐了。
继续回溯:
分析发现ecx像是一个结构指针,其中第二个位置放的就是函数指针,第三个位置放的是传入的参数。于是利用函数指针地址下条件断点。显示从ecx开始,[ECX+4]==0x0044F4E0,在下面代码中注释部分标注了下断点的方法,由于ecx的值是通过esi取到的,于是[ESI+4]==0x0044F4E0,然后esi又是通过eax取到的,于是又更进下[[EAX+8]+4]==0x0044F4E0。果然这些条件断点都被命中了。
.text:00589A1D loc_589A1D:
.text:00589A1D 8B 70 08 mov esi, [eax+8] ;[[EAX+8]+4]==0x0044F4E0
.text:00589A20 8D 48 10 lea ecx, [eax+10h]
.text:00589A23 50 push eax
.text:00589A24 E8 B7 62 00 00 call sub_58FCE0
.text:00589A29 83 2D F8 30 8A+sub dword_8A30F8, 10h
.text:00589A30 8B 06 mov eax, [esi]
.text:00589A32 59 pop ecx
.text:00589A33 8B CE mov ecx, esi ;[ESI+4]==0x0044F4E0
.text:00589A35 FF 50 04 call dword ptr [eax+4] ;[ECX+4]==0x0044F4E0
.text:00589A38 8B 06 mov eax, [esi]
.text:00589A3A 8B CE mov ecx, esi
.text:00589A3C 6A 01 push 1
.text:00589A3E FF 10 call dword ptr [eax]
.text:00589A40 E8 3D 6B 00 00 call sub_59058
OD中在这句上下断:
00589A1D >|> 8B70 08 mov esi,dword ptr ds:[eax+0x8]
再来一次,断下后Ctrl+A分析一下程序,程序就显示出了跳转的来源,这里十分不巧,有两点,都下条件断判定一下:
再来一次,嗯,是从下面跳上来的:
此时eax中的值是关键,当前为0x03DCA1C0,应该是堆栈的地址。那是什么时候取出来的呢?
哇,全局变量来了,咱们终于落地了。只要有了全局变量,一切都好商量。
哈哈,全局就只有一处可以设值的,其他三处都是改写的。
大胆猜测,现在所在的函数就是从消息到消息响应函数的映射函数,而目标函数就是负责查出二者映射关系的函数