写在前面的话:在下完全就是一个新手,现在目前在学16位汇编,偶尔用OD调试看看程序,主要就是为了学习,今天写这个帖子,完全就是笔记用,然后拿出来和大家一起讨论交流。
因为刚开始接触,文章可能一些地方有错误,如果有错误的地方还请指出来,毕竟刚学,确实差的十万八千里。而且这个程序也很简单,主要还是为了做记录。
网上找了个abexcm1,然后进行调试。
我个人的习惯,当首先拿到 程序的时候,我都会按F8直接把程序走一遍,看看大概的流程。
这个程序的功能很简单,匹配C:\驱动器的属性,如果成功,就弹出开OK,如果失败,就弹出来失败。两者均退出程序。
00401000 >/$ 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL ;将数据入栈 00401002 |. 68 00204000 push 00402000 ; |Title = "abex‘ 1st crackme" 将数据入栈 00401007 |. 68 12204000 push 00402012 ; |Text = "Make me think your HD is a CD-Rom." 将数据入栈 0040100C |. 6A 00 push 0 ; |hOwner = NULL 将数据入栈 0040100E |. E8 4E000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA 调用WIN API 00401013 |. 68 94204000 push 00402094 ; /RootPathName = "c:\" ;将00402094 数据入栈 00401018 |. E8 38000000 call <jmp.&KERNEL32.GetDriveTypeA> ; \GetDriveTypeA ; ; 调用WIN API 0040101D |. 46 inc esi ;esi +1 =1 eax = 03 0040101E |. 48 dec eax exc-1 = 02 0040101F |. EB 00 jmp short 00401021 ;垃圾指令 00401021 |> 46 inc esi esi = 2 00401022 |. 46 inc esi esi = 3 00401023 |. 48 dec eax eax-1 = 01 00401024 |. 3BC6 cmp eax, esi ; 比较值,如果值相等,JE条件跳转,如果不相等,继续走下去 00401026 |. 74 15 je short 0040103D ;值不相等,无法段内段转移,继续走下去 00401028 |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL 0040102A |. 68 35204000 push 00402035 ; |Title = "Error" 0040102F |. 68 3B204000 push 0040203B ; |Text = "Nah... This is not a CD-ROM Drive!" 00401034 |. 6A 00 push 0 ; |hOwner = NULL 00401036 |. E8 26000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA ;调用MESSAGEBOX弹出错误 0040103B |. EB 13 jmp short 00401050 ;t跳转 0040103D |> 6A 00 push 0 ; |/Style = MB_OK|MB_APPLMODAL ;调用成功的函数, 0040103F |. 68 5E204000 push 0040205E ; ||Title = "YEAH!" 00401044 |. 68 64204000 push 00402064 ; ||Text = "Ok, I really think that your HD is a CD-ROM! :p" 00401049 |. 6A 00 push 0 ; ||hOwner = NULL 0040104B |. E8 11000000 call <jmp.&USER32.MessageBoxA> ; |\MessageBoxA 00401050 \> E8 06000000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess ;程序退出。
从以上我们可以看出,程序2次弹出来了MESSAGEBOX,那如何来破解呢?、
我们知道,破解中最注意的应该就是跳转之前的比较指令,
0040101D |. 46 inc esi 0040101E |. 48 dec eax 0040101F |. EB 00 jmp short 00401021 00401021 |> 46 inc esi 00401022 |. 46 inc esi 00401023 |. 48 dec eax 00401024 |. 3BC6 cmp eax, esi 00401026 |. 74 15 je short 0040103D
以上可以看出,如果比较的值相等,就继续执行,如果不相等,就转到另外一个MESSAGEBOX函数出,直接调用API。
那我们可以直接让他相等就好了,或者直接JMP 无条件跳转到0040103D地址处调用成功的MESSAGEBOX API,就达到了破解的功能。
下面我们来跟踪每一次执行完以后的寄存器的变化。
寄存器相关的值:
EAX= 75E23358 ;一般用来存放临时数据 ECX= 00000000 ;ECX一般用来进行LOOP循环才会用到 EDX= 00401000 ;数据寄存器, EBX= 7EFDE000 ;基址寄存器,常用来存放访问内在时的基地址 ESP= 0018FF8C ;栈顶指针,指向栈顶地址,在32为寄存器中,碰到PUSH的时候,SP = SP-4,pop的时候,POP = POP + 4 EBP= 0018FF94 ;是基址指针,段地址默认在SS中.可以定位物理地址 ESI= 00000000 ;源变址寄存器,默认段地址和DI一样,在DS中.和DS联用 EDI= 00000000 ;变址寄存器.可以和bx.bp联用 EIP= 00401000 ;EIP指向当前要执行的指令,每次EIP= EIP+执行指令的长度
//标志位没写 00401000 >/$ 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL 00401002 |. 68 00204000 push 00402000 ; |Title = "abex‘ 1st crackme" 00401007 |. 68 12204000 push 00402012 ; |Text = "Make me think your HD is a CD-Rom." 0040100C |. 6A 00 push 0 ; |hOwner = NULL 0040100E |. E8 4E000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA 00401013 |. 68 94204000 push 00402094 ; /RootPathName = "c:\" 00401018 |. E8 38000000 call <jmp.&KERNEL32.GetDriveTypeA> ; \GetDriveTypeA
当执行push 00402000,其实就是将 00402000 这个内存地址的数据压入桟。
我们来看00402000的数据
00402000 61 62 65 78 27 20 31 73 74 20 63 72 61 63 6B 6D abex‘ 1st crackm push 00402012 将 00402012 内存地址数据压入桟 00402012 4D 61 6B 65 20 6D 65 20 74 68 69 6E 6B 20 79 6F Make me think yo 00402022 75 72 20 48 44 20 69 73 20 61 20 43 44 2D 52 6F ur HD is a CD-Ro 00402032 6D 2E
push 0
为空
call <jmp.&USER32.MessageBoxA> 调用MESSAGEBOX API
在执行CALL <jmp.&USER32.MessageBoxA>,MessageBoxA 的内存地址在 00401061,直接 调用了API,弹出MESSAGEBOX
CALL API(也可以说是标号)。将执行2步操作:
1:PUSH IP 1:JMP NEAR PTR 标号
0040101D |. 46 inc esi 0040101E |. 48 dec eax 0040101F |. EB 00 jmp short 00401021 ;垃圾指令 00401021 |> 46 inc esi 00401022 |. 46 inc esi 00401023 |. 48 dec eax 00401024 |. 3BC6 cmp eax
以上均是数据比较。
然后在进行条件跳转。
这次的分析就到这儿了,因为初学,难免错误,还请多多指点。各位勿喷。谢谢
原文:http://www.cnblogs.com/killbit/p/4851398.html