分析cbex crackme#1
crackme就是“破解我”的意思,它们都是一些公开用作破解练习的小程序
下载地址:https://github.com/idea-oss/example-/tree/main/01/06/bin
-
运行程序

点击确定后,然后几出错了

-
用od打开调试
用之前的方法找到入口函数

-
代码分析
#这里是给messagebox()函数传参,并调用
PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
PUSH abexcm1-.00402000 ; |Title = "abex' 1st crackme"
PUSH abexcm1-.00402012 ; |Text = "Make me think your HD is a CD-Rom."
PUSH 0 ; |hOwner = NULL
CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
#给getdrivetype()函数传参并调用,getdrivetype() api,获取c驱动的类型(大部分返回的是HDD类型)
PUSH abexcm1-.00402094 ; /RootPathName = "c:\"
CALL <JMP.&KERNEL32.GetDriveTypeA> ; \GetDriveTypeA 返回值(eax)是三(drive_fixed)
INC ESI ;inc esi为自加一操作,esi的值为0
DEC EAX ;dec为自减一操作,所以eax变成了2
JMP SHORT abexcm1-.00401021 ;无用操作,就是跳到下一行代码处
INC ESI
INC ESI
DEC EAX
CMP EAX,ESI ;比较eax,esi
JE SHORT abexcm1-.0040103D ;若上面比较的值相等就跳转40103D,否则就向下执行命令
PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
PUSH abexcm1-.00402035 ; |Title = "Error"
PUSH abexcm1-.0040203B ; |Text = "Nah... This is not a CD-ROM Drive!"
PUSH 0 ; |hOwner = NULL
CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
JMP SHORT abexcm1-.00401050
PUSH 0 ; |/Style = MB_OK|MB_APPLMODAL
PUSH abexcm1-.0040205E ; ||Title = "YEAH!"
PUSH abexcm1-.00402064 ; ||Text = "Ok, I really think that your HD is a CD-ROM! :p"
PUSH 0 ; ||hOwner = NULL
CALL <JMP.&USER32.MessageBoxA> ; |\MessageBoxA
CALL <JMP.&KERNEL32.ExitProcess> ; \ExitProcess
| 指令 | 说明 |
|---|---|
| push | 入栈操作 |
| call | 调用指定位置的函数 |
| inc | 值加1 |
| dec | 值减1 |
| jmp | 跳转到指定地址 |
| cmp | 比较给定的两个操作数与sub命令类似,但是操作数的值不会改变,仅改变eflags寄存器(若两个操作数的值一致,sub结果为0,zf被置为1) |
| je | 条件跳转指令(jump if equal) 若zf为1,则跳转 |
- 破解
在如下位置,按空格

将JE条件跳转指令改成JMP无条件跳转即可

copy to executable



然后运行修改后的程序

破解成功
栈帧
栈帧在程序中用于声明局部变量、调用函数。栈帧就是利用EBP(栈帧指针,请注意不是ESP)寄存器访问栈内部局部变量、参数函数返回地址等手段ESP承担着栈顶指针的作用,而EBP寄存器则负责行使栈帧指针的职能。程序运行中,ESP寄存器的值随时变化,访问栈中函数的局部变量、参数时,若以ESP值为基准编写程序会十分困难,并且也很难使CPU引用到准确的地址。所以,调用某函数时,先要把用作基准点(函数起始地址)的ESP值保存到EBP并维持在函数内部。这样,无论ESP的值如何变化,以EBP的值为基准能够安全访问到相关函数的局部变量、参数、返回地址,这就是EBP寄存器作为栈帧指针的作用
栈帧对应的汇编代码
push ebp ;函数开始,使用ebp前先把已有的值保存到栈中
mov ebp,esp ;保存当前esp到ebp中
......
mov esp,ebp ;将函数的起始地址返回到esp中
pop ebp ;函数返回前弹出保存在栈中的ebp值
retn ;函数终止
本文详细介绍了如何分析和破解一个名为cbexcrackme#1的Crackme程序。通过OD调试器,我们追踪了程序的执行流程,特别是调用了GetDriveTypeA函数来检查C盘是否为CD-ROM。程序通过比较GetDriveTypeA的返回值来决定显示错误或成功的消息框。破解的关键在于将条件跳转指令JE替换为无条件跳转JMP,从而绕过检查。此外,文章还简单介绍了栈帧的概念及其在程序中的作用。
985

被折叠的 条评论
为什么被折叠?



