逆向学习笔记三

本文详细介绍了如何分析和破解一个名为cbexcrackme#1的Crackme程序。通过OD调试器,我们追踪了程序的执行流程,特别是调用了GetDriveTypeA函数来检查C盘是否为CD-ROM。程序通过比较GetDriveTypeA的返回值来决定显示错误或成功的消息框。破解的关键在于将条件跳转指令JE替换为无条件跳转JMP,从而绕过检查。此外,文章还简单介绍了栈帧的概念及其在程序中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分析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				;函数终止
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值