Jirairya

CrackMe1


练手CrackMe1,进一步熟悉调试器和汇编代码。

运行CrackMe1

0x01 查看到该文件是exex。 exex文件.png 0x02 将其后缀名更改为exe,尝试运行。 第一次运行exe.png

弹出错误消息框.png

载入OD

0x03 在运行之后,并不知道该程序的意图,就载入OD分析。 crackme1程序入口点.png

使用高级语言编写程序,在自己编写代码之中,编译器还会添加启动函数,经过反编译之后,代码就会变得复杂。但如果代码用汇编编写的,在OD中直接变成反汇编代码。根据图中,main()直接出现在EP中,且简洁直观,可猜测该程序由汇编语言编写

分析代码

0x04根据OD的反汇编代码和Win32API调用,先整理出,基本代码:

MessageBox("Make me thin your HD is a CD-Rom.")
GetDriveType("C:\\")
...
MessageBox("Nah...This is not a CD-ROM Drive")
MessageBox("Ok,I really think that your HD is a CD-ROM")
ExitProcess()

可分析出程序的大概流程:在消息窗口按“确定”后,程序会调用GetDriveType()API,获取C驱动器的类型,然后操作它,使之识别为CD-ROM类型,再在消息窗口中输出“OK,I really think that your HD is a CD-ROM!”

;调用MessageBoxA()函数
00401000 >/$  6A 00         push 0x0                                 ; /Style = MB_OK|MB_APPLMODAL
00401002  |.  68 00204000   push 0x402000                            ; |Title = "abex' 1st crackme"
00401007  |.  68 12204000   push 0x402012                            ; |Text = "Make me think your HD is a CD-Rom."
0040100C  |.  6A 00         push 0x0                                 ; |hOwner = NULL
0040100E  |.  E8 4E000000   call 00401061                            ; \MessageBoxA
;在函数内部ESI被设置为FFFFFFFF
;调用GetDriveType()函数
00401013  |.  68 94204000   push 0x402094                            ; /RootPathName = "c:\"
00401018  |.  E8 38000000   call 00401055                            ; \GetDriveTypeA
;返回值(EAX)是3(DRIVE_FIXED)
0040101D  |.  46            inc esi
;ESI=0
0040101E  |.  48            dec eax                                  ;  kernel32.BaseThreadInitThunk
;EAX=2
0040101F  |.  EB 00         jmp short 00401021                       ;  abexcm1-.00401021
;无意义的JMP命令(垃圾代码)
00401021  |>  46            inc esi                                  ;ESI=1
00401022  |.  46            inc esi                                  ;ESI=2
00401023  |.  48            dec eax                                  ;  kernel32.BaseThreadInitThunk
EAX=1
00401024  |.  3BC6          cmp eax,esi
;比较eax(1)和esi(2)
00401026  |.  74 15         je short 0040103D                        ;  abexcm1-.0040103D
;JE(Jump if Equal)条件分支命令。若两值相等,则跳转到40103D;若不等则从401028继续执行
;在40103D地址为消息框输出代码
00401028  |.  6A 00         push 0x0                                 ; /Style = MB_OK|MB_APPLMODAL
0040102A  |.  68 35204000   push 0x402035                            ; |Title = "Error"
0040102F  |.  68 3B204000   push 0x40203B                            ; |Text = "Nah... This is not a CD-ROM Drive!"
00401034  |.  6A 00         push 0x0                                 ; |hOwner = NULL
00401036  |.  E8 26000000   call 00401061                            ; \MessageBoxA
0040103B  |.  EB 13         jmp short 00401050                       ;  abexcm1-.00401050
0040103D  |>  6A 00         push 0x0                                 ; |/Style = MB_OK|MB_APPLMODAL
0040103F  |.  68 5E204000   push 0x40205E                            ; ||Title = "YEAH!"
00401044  |.  68 64204000   push 0x402064                            ; ||Text = "Ok, I really think that your HD is a CD-ROM! :p"
00401049  |.  6A 00         push 0x0                                 ; ||hOwner = NULL
0040104B  |.  E8 11000000   call 00401061                            ; |\MessageBoxA
00401050  \>  E8 06000000   call 0040105B                            ; \ExitProcess
00401055   $- FF25 50304000 jmp dword ptr ds:[0x403050]              ;  kernel32.GetDriveTypeA
0040105B   .- FF25 54304000 jmp dword ptr ds:[0x403054]              ;  kernel32.ExitProcess
00401061   $- FF25 5C304000 jmp dword ptr ds:[0x40305C]              ;  user32.MessageBoxA
命令 说明
PUSH 入栈指令
CALL 调用指定位置的函数
INC 值加1
DEC 值减1
JMP 跳转到指定的位置
CMP 比较两个操作数,操作数不变,仅改变EFLAGS寄存器(两操作数一致,SUB为0,ZF被置为1)
JE 条件跳转指令(Jump if equal) *若ZF为1,则跳转

破解

将已有代码(或数据)覆盖为其他代码的行为叫做打补丁

0x05 首先将光标移动到401026地址处,按空格键,在打开的汇编窗口将汇编指令JE SHORT 004103D更改为JMP 0040103D

右键->复制到可执行文件,将修改的代码保存为文件,运行: crackme1破解的结果.png

拓展

函数调用时,将函数参数逆序压入栈。因为栈的结构是FILO(先进后出),所以把参数压入栈时,只有按照逆序的方式压入,MessageBoxA()函数才能以正确顺序接收到这些参数

00401000 >/$  6A 00         push 0x0                                 ; /Style = MB_OK|MB_APPLMODAL
00401002  |.  68 00204000   push 0x402000                            ; |Title = "abex' 1st crackme"
00401007  |.  68 12204000   push 0x402012                            ; |Text = "Make me think your HD is a CD-Rom."
0040100C  |.  6A 00         push 0x0                                 ; |hOwner = NULL
0040100E  |.  E8 4E000000   call 00401061                            ; \MessageBoxA

在调用MessageBoxA()函数之前,使用4个PUSH命令,将函数需要的参数逆序压入栈。

将该汇编代码转换为C语言调用代码如下:

MessageBox(NULL,"Make me think your HD is a CD-Rom.","abex' 1st crackme",MB_OK|MB_APPLMODAL);

压栈顺序.png


上一篇 Misc

下一篇 栈帧

Comments

Content