【文章标题】: 菜鸟也写注册机
【文章作者】: 范晨鹏
【作者邮箱】: [email]p_168@163.com[/email]
【作者主页】: 111K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3c8A6P5h3I4S2j5W2)9J5k6h3y4F1j5X3I4G2k6%4y4Q4x3X3g2U0L8$3@1`.
【作者QQ号】: 109427716
【软件名称】: crackme
【软件大小】: 10k
【下载地址】: 见附件
【加壳方式】: 无
【编写语言】: c
【使用工具】: OllyDbg1.1
【操作平台】: windowsXP
【软件介绍】: 就是用来练手的。
【作者声明】: 第一次搞全程破解。本人没学过汇编,也没搞过破解。所以,文章中一些经验只是主观想象加片面之言。千万别当得和高手的箴言一样值钱。
若有高手飘过顺手做做指点,则不胜受恩感激。
--------------------------------------------------------------------------------
【详细过程】
说两句废话:
有的朋友喜欢私下要求搞破解。借此声明一下:
一、本人是菜鸟。只会找软柿子捏。真活是干不了的。
二、本人胆小,怕惹出官司来。所以从来没破过真软件,也没打算过破真软件。
废话说完啦。开始啦。
摘要:本文从错误提示入手,以寻找关键跳转、分析关键比较、反向跟踪堆栈寄存器三个层次,得出了分析算法的一般过程。
阅读本文需要且仅需要具备C语言基础知识以及认识简单的汇编命令。
阅读本文,你可以学到:
1、怎样在不懂汇编的情况下搞破解;
2、怎样在不懂算法的情况下分析算法;
3、OllyDbg的入门用法。
先来个感性认识:
这是一个别处的竞赛(霏凡论坛 07cK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3u0T1M7#2)9J5k6h3y4J5M7$3E0&6i4K6u0W2j5$3!0E0)题目。( 一个项目忙了两个多月。回来后发现学院悄悄的组织了一次crackme竞赛。恨得牙痒痒)
软件界面:

如果注册不成功,会在“注册码”文本框中显示 :"plz try again!"
如果注册成功……注册成功了还用破吗?
用C语言写了个注册机。不会写图形界面的,见笑。

有用的信息就一条"plz try again"。呵呵,有这个就不错了,没有它我还不知道怎么破呢。我们以下的操作都是基于这么错误信息展开的。
一 暴破手!GoOoGo!--寻找关键跳转
1、暴破和跳转
简单地说,爆破==找跳转。
其实不是找“简单地说”。是“本质上讲”。
就像路要一步一步走一样,程序也是一步一步执行的。在OD中,我们每按一下F8。程度便往下走一步。直到程序退出。
在我们注册的过程中,输入注册码,程序再往前走便会走到十字路口(应该说是丁字路口):前面有两个选择:如果注册码正确,向左转,如果不正确,则向右转。这里的“转”,就是跳转。
跳转有若干种,总体分为两种:绝对跳转和相对跳转。绝对跳转,又叫无条件跳转,用汇编表示就是JMP。相对跳转则五花八门:intel的汇编指令手册中,条件跳转的指令多达三十多种。它们都有个统一的前缀‘j’。程序破解中,我们只关心三种相对跳转。
jg 若大于则跳转;
jge 若大于等于则跳转;
jz 若前面比较结果为零则跳转;
知道这三种就够啦。其它的跳转指令都大同小异,比如”若小于则跳转“(jl),见了面一猜就猜到了。用到的时候再查手册就行了。
2 寻找合适的断点
最理想的断点的位置是关键跳转处。这等于废话。怎么找到关键跳转处呢?最好的办法是使用字符串参考。用错误提示信息快速找到丁字路口。
本例中,错误提示是: “plz try again”
运行Ollydbg。按F3载入crackme。右键,查找,“所有的文本字符串”。弹出“文本字符串参考”窗口,我们很容易找到错误提示所在地。 一共有三处。如图:

在有错误提示的三行的“地址”列分别按F2设断点。最前面的地址列就变成了红色。
按F9,我们的小程序便运行起来了。提示输入用户名和密码。我们用户名输入"Crackme",密码输入"78787878"。
点“注册”,程序停在了断点处:
00401CA4 |. BA CA514600 mov edx, 004651CA ; ASCII "Plz try again!"
00401C28 |. 83C4 08 add esp, 8
00401C2B |. 33D2 xor edx, edx ; edx清零
00401C2D |. 3B5D AC cmp ebx, dword ptr [ebp-54] ; 公约数相等?
00401C30 |. 8AD0 mov dl, al
00401C32 |. 0F94C1 sete cl
00401C35 |. 83E1 01 and ecx, 1
00401C38 |. 8D5C33 01 lea ebx, dword ptr [ebx+esi+1] ; esi 用户名ASCII
00401C3C |. 23D1 and edx, ecx
00401C3E |. 3B75 B4 cmp esi, dword ptr [ebp-4C] ; 用户名ascii之和 小于 密码ascii之和
00401C41 |. 0F9CC0 setl al
00401C44 |. 83E0 01 and eax, 1
00401C47 |. 23D0 and edx, eax
00401C49 |. 3B5D B4 cmp ebx, dword ptr [ebp-4C] ; ebx 大于 密码ascii之和
00401C4C |. 0F9FC0 setg al ;
00401C4F |. 83E0 01 and eax, 1
00401C52 |. 23D0 and edx, eax ; if (edx = false) jmp
00401C54 |. 74 48 je short 00401C9E ; 关键跳转 若不跳转则成功
00401C56 |. 66:C745 CC 5C>mov word ptr [ebp-34], 5C
00401C54 90 nop ; 关键跳转 若不跳转则成功
00401C55 90 nop
00401C28 |. 83C4 08 add esp, 8
00401C2B |. 33D2 xor edx, edx ; edx清零
00401C2D |. 3B5D AC cmp ebx, dword ptr [ebp-54] ; 公约数相等?
00401C30 |. 8AD0 mov dl, al
00401C32 |. 0F94C1 sete cl
00401C35 |. 83E1 01 and ecx, 1
00401C38 |. 8D5C33 01 lea ebx, dword ptr [ebx+esi+1] ; esi 用户名ASCII
00401C3C |. 23D1 and edx, ecx
00401C3E |. 3B75 B4 cmp esi, dword ptr [ebp-4C] ; 用户名ascii之和 小于 密码ascii之和
00401C41 |. 0F9CC0 setl al
00401C44 |. 83E0 01 and eax, 1
00401C47 |. 23D0 and edx, eax
00401C49 |. 3B5D B4 cmp ebx, dword ptr [ebp-4C] ; ebx 大于 密码ascii之和
00401C4C |. 0F9FC0 setg al ;
00401C4F |. 83E0 01 and eax, 1
00401C52 |. 23D0 and edx, eax ; if (edx = false) jmp
00401C54 |. 74 48 je short 00401C9E ; 关键跳转 若不跳转则成功
00401C56 |. 66:C745 CC 5C>mov word ptr [ebp-34], 5C
00401C2D |. 3B5D AC cmp ebx, dword ptr [ebp-54] ; 当前的问题是这里不等
[培训]科锐逆向工程师培训第53期2025年7月8日开班!