程序简易测试
打开002-abexcm5文件夹,里面有abexcm5.exe的可执行文件。首先尝试运行,如下图:
输入序列号后点击check,弹窗显示输入错误,并结束程序的运行。
逆向实现细节
手动运行已经完毕,下面尝试对此程序进行逆向操作。
首先将exe程序拖入到PEiD(查壳工具)中:
显示的内容说明此程序是由汇编语言编写的,没有在程序上加壳。
随后将此程序拖入OllDbg中调试:
进入OD后点击右键–> 中文搜索引擎 --> 搜索ASCII
可以看到刚才弹窗中的错误提示信息:“The serial you entered is not correct!” 我们双击该语句即可跳转到操作该字符串的位置,如下图所示:
图中所示的汇编代码含义分别是将错误的提示信息和正确的提示信息弹窗,弹窗行为的函数是MessageBoxA,push的内容是该函数的参数。究竟是执行从0x00401101开始的错误提示,还是执行从0x00401117开始的正确提示,取决于je跳转语句的执行与否。若执行此跳转,则提示正确信息,反之亦然。那么je是否跳转取决于上一句的
cmp eax, 0x0
分析至此我们已经对关键信息的输出有了个基本猜想,那么我们顺着这条线索,先执行到这个函数看看再说。向上寻找第一个retn语句,发现在0x00401069,所以我们在它的下一行,即0x0040106C处使用F2打断点。随后使用F9执行,并在弹出的程序中输入monster作为我们的serial序列号,并点击check,程序就跳转到下图所示的位置了:
图中汇编指令集的含义就是执行这几个函数,标红函数的具体含义如果感兴趣可以自己百度,我在这里只放重要函数的含义。我们baidu一下GetVolumeInformationA() 函数的操作内容可知其作用为获取磁盘卷标,也可以理解为获取该可执行文件所在系统盘的名称。我们使用F8执行完GetVolumeInformationA() 函数停下,并查看右下角的堆栈图,发现我的名称“Data”已经存储在VolumeNameBuffer的地址0x0040225C的位置了,并右键单击数据窗口跟随如下图所示:
Data正好是我的D盘名字,我的该程序也确实保存在了D盘。
0040109E |. 68 F3234000 push abexcm5.004023F3 ; /4562-ABEX
004010A3 |. 68 5C224000 push abexcm5.0040225C ; |ConcatString = "Data"
004010A8 |. E8 94000000 call <jmp.&KERNEL32.lstrcatA> ; \lstrcatA
随后执行该段函数,其功能是将第一个字符串参数接在第二个字符串参数的后面,结果也保存在第二个参数的地址中。结果如下图,下面的数据框图、寄存器EAX都有显示:
随后执行下面的汇编指令:
004010AD |. B2 02 mov dl,0x2
004010AF |> 8305 5C224000>/add dword ptr ds:[0x40225C],0x1
004010B6 |. 8305 5D224000>|add dword ptr ds:[0x40225D],0x1
004010BD |. 8305 5E224000>|add dword ptr ds:[0x40225E],0x1
004010C4 |. 8305 5F224000>|add dword ptr ds:[0x40225F],0x1
004010CB |. FECA |dec dl
004010CD |.^ 75 E0 \jnz short abexcm5.004010AF
该段程序的大致含义为:
1、dl作为计数器赋值为2;
2、对0x40225C地址的数据值+1;
3、对0x40225D地址的数据值+1;
4、对0x40225E地址的数据值+1;
5、对0x40225F地址的数据值+1;
6、dl -1
7、如果dl不为0则跳转到0x004010AF;
相当于对刚才字符串的前4个字节的每个字节的ASCII码值+2,结果如下:
Fcvc4562-ABEX
004010CF |. 68 FD234000 push abexcm5.004023FD ; /L2C-5781
004010D4 |. 68 00204000 push abexcm5.00402000 ; |ConcatString = ""
004010D9 |. E8 63000000 call <jmp.&KERNEL32.lstrcatA> ; \lstrcatA
004010DE |. 68 5C224000 push abexcm5.0040225C ; /StringToAdd = "Fcvc4562-ABEX"
004010E3 |. 68 00204000 push abexcm5.00402000 ; |ConcatString = ""
004010E8 |. E8 54000000 call <jmp.&KERNEL32.lstrcatA> ; \lstrcatA
继续执行上述代码,仍然是字符串拼接工作,不在此赘述,执行完这一段,两个值得关注的数据段的值为:
0x00402000=abexcm5.00402000 (ASCII “L2C-5781Fcvc4562-ABEX”)
0x00402324=abexcm5.00402324 (ASCII “monster”)
第一行的值是执行完两次拼接后的字符串的值,第二行的值是我们输入的serial,在该函数的初始位置就保存了下来。
最后的一步就是使用lstrcmpiA函数来比较上述两个字符串的值,如果是相等,则返回给EAX的值就是0,使用je后会跳转到弹出正确提示信息的路径,反之亦然。
正确的序列号为:
L2C-5781Fcvc4562-ABEX
我们将OD动态执行的程序停止,重新手动运行该程序并输入上述序列号得到的结果如下图:
至此,我们得到了最终的比较参数,所以逆向任务基本完成。
暴力破解方案
1、只更改cmp指令:
cmp eax, 0x1
或
mov eax, 0x0
cmp eax, 0x0
这样判断后的程序就能执行je的跳转。
2、只更改je指令:
jne short abexcm5.00401117
这样就可以无论输入什么serial,只要输入错误,都能跳转。
以上就是全部的复现内容了,b站源视频传送门如下,若文章有错误欢迎指出。
新160个CrackMe算法分析-002-abexcm5