破解test

先用vc++6.0将test.c编译成test.exe

运行exe文件
如果输入错误的密码,会输出“incorrect password!”,并重新输入。如果正确,则输出“Congratulation! You have passed the verification!”并结束程序。

Ollydbg调试


F8单步运行至停止处,这里需要等待输入,下断点

ctrl+F2重载,F9运行至断点处,F7步入函数查看

这里展示了核心逻辑

  • 提示用户并获取输入 (地址 00401076 - 0040108A)
  • 调用密码验证函数 (地址 0040108F - 00401094)
    • 函数返回值到EAX寄存器中。根据strcmp的原理,如果密码正确,EAX的值会是0;如果错误,则为非0
  • 核心判断逻辑 (地址 0040109C - 0040109E)
    • test eax, eax:如果EAX的值是0,那么零标志位(Zero Flag, ZF)就会被设置为1
  • 两个路径je指令没有跳转,则运行 失败路径je指令成功跳转,则运行 成功路径

破解

法1:反转跳转逻辑

je改成jne即可让跳转逻辑反转,密码错误时输出“Congratulation”

保存修改

运行,逻辑已经相反

法2:直接赋值eax

既然eax=0是密码正确时的返回值,那么可以直接将0赋值给eax。但这里不能用mov eax,0(5个字节),因为test eax,eax指令长度只有2个字节。可以使用xor eax,eax(2个字节)代替

修改后保存
输入任何字符都会成功

破解Crackme

运行,尝试输入,注册失败

Ollydbg调试

右键→查找→所有参考文本字串

双击“crackmepassword”

在此处下断点,F9运行

输入用户名和密码后程序停在断点处

F8单步运行,并在跳转的位置用注释标出“跳转是否实现”

运行到0040163E弹出“注册失败”

由此可知,上面的两个跳转决定了注册成功还是失败
对关键的汇编代码进行分析

法1:修改跳转逻辑

修改后保存,运行
输入密码任意,都会显示注册成功

法2:修改判断逻辑

已经分析得到,字符串比较完后,结果存入eax,相等则是0,不相等非0。又通过test eax,eax判断eax是否为0。
可以直接给eax赋值为0,从而不进行jnz short 00401637的跳转,运行注册成功的函数。

修改后保存,运行
输入任意密码都显示注册成功

法3:NOP填充法

修改后保存,运行