欢迎光临!
若无相欠,怎会相见

[CrackMe] 160个CrackMe之018-Brad Soblesky.1.exe

序言

最近一直在学习汇编语言、C语言和PE相关的知识,想更好地理解一下底层相关的知识,刚好自己又对逆向工程很有兴趣,因此就拿CrackMe练练手,毕竟光学不练假把式。

CrackMe

之前想的是从头开始练习,也就是从第一个开始练习,结果发现第一个是Delphi编写的,自己对Delphi编写的程序不太了解,因此就选择了第018,它是VC++编写的,比较简单,就拿它开刀了。

STEP 0x0 准备工作

工具:OllyDbg(吾爱破解)、exeinfo PE

CrackMe:Brad Soblesky.1.exe

STEP 0x1 查壳

用exeinfo PE 工具打开Brad Soblesky.1.exe这个可执行文件,可以看到是没有加壳的:

STEP 0x2 打开软件

打开软件,并随机输入注册码,看看会提示什么信息,可以看到含有“Incorrect try again”字符串:

STEP 0x3 OllyDbg爆破

直接使用OllyDbg打开程序,加载完程序,一般会停在程序入口点。直接鼠标右键 -》中文搜索引擎 -》搜索ASCII

搜索的时候正好可以看到之前输入错误注册码的提示信息:

很明显“Correct way to go!!”是注册码正确时的提示,下面的是注册码错误时的提示。双击“Incorrect try again”这一行,跳转到CPU指令界面。

分析这一块的汇编代码:

004015AD  |> \6A 40         push 0x40
004015AF  |.  68 6C304000   push Brad_Sob.0040306C                   ;  CrackMe
004015B4  |.  68 74304000   push Brad_Sob.00403074                   ;  Incorrect try again!!
004015B9  |.  8B4D E0       mov ecx,[local.8]
004015BC  |.  E8 3D050000   call <jmp.&MFC42.#CWnd::MessageBoxA_4224>

push指令一般是将函数的参数压入堆栈,call一般是调用函数,因此这里就相当于调用弹出窗口函数,弹出的是注册码错误的提示信息窗口,再上面就是正确时的提示串口了,继续向上找,在push 0x40 指令,很明显是其他指令跳转而来

jnz指令:jump if not zero,意思是标志寄存器ZF不为0时跳转,jz指令与其相反,jump if zero,标志寄存器ZF为0 时,跳转,test指令:两操作数作与运算,仅修改标志位,不回送结果。

红色的箭头表示当前满足跳转条件,进行跳转。因此jnz指令是关键跳转,它把注册码正确时的窗口跳过了,只需要把jnz跳转到正确时的窗口,也就是跳转到它的下一条指令,就相当于不论填写什么注册码,都会执行注册码正确时的窗口,达到自己想要的目的,我们可以试一下:

达到目的,爆破完成。

STEP 0x4 OllyDbg追码

爆破会修改程序本身,给人一种不安全的感觉,尤其是那些有强迫症的人来说,因此为了提升自我,我就继续追码。代码分析如下:

00401512  /.  55            push ebp
00401513  |.  8BEC          mov ebp,esp
00401515  |.  83EC 20       sub esp,0x20
00401518  |.  894D E0       mov [local.8],ecx
0040151B  |.  66:A1 5C31400>mov ax,word ptr ds:[0x40315C]
00401521  |.  66:8945 F4    mov word ptr ss:[ebp-0xC],ax
00401525  |.  33C9          xor ecx,ecx
00401527  |.  894D F6       mov dword ptr ss:[ebp-0xA],ecx
0040152A  |.  894D FA       mov dword ptr ss:[ebp-0x6],ecx
0040152D  |.  8B15 20304000 mov edx,dword ptr ds:[0x403020]          ;  <BrD-SoB>
00401533  |.  8955 E4       mov [local.7],edx                        ;  堆栈地址[local.7]存的是<BrD-SoB>
00401536  |.  A1 24304000   mov eax,dword ptr ds:[0x403024]          ;  -SoB>
0040153B  |.  8945 E8       mov [local.6],eax
0040153E  |.  66:8B0D 28304>mov cx,word ptr ds:[0x403028]            ;  >
00401545  |.  66:894D EC    mov word ptr ss:[ebp-0x14],cx
00401549  |.  6A 0A         push 0xA
0040154B  |.  8D55 F4       lea edx,[local.3]
0040154E  |.  52            push edx
0040154F  |.  68 E8030000   push 0x3E8
00401554  |.  8B4D E0       mov ecx,[local.8]                        ;  mfc42.5F1D0040
00401557  |.  E8 A8050000   call <jmp.&MFC42.#CWnd::GetDlgItemTextA_>
0040155C  |.  8D45 F4       lea eax,[local.3]                        ;  自己输入的假码,将假码放入eax
0040155F  |.  50            push eax                                 ; /eax作为函数的参数压入堆栈
00401560  |.  FF15 04204000 call dword ptr ds:[<&KERNEL32.lstrlenA>] ; \lstrlenA
00401566  |.  8945 F0       mov [local.4],eax                        ;  上面一行是获取长度,返回值一般存在eax中,再将eax的值存入[local.4]堆栈中
00401569  |.  837D F0 01    cmp [local.4],0x1                        ;  将[local.4]的值与1比较,也就是比较长度
0040156D  |.  73 16         jnb short Brad_Sob.00401585              ;  长度大于或等于1就跳转
0040156F  |.  6A 40         push 0x40
00401571  |.  68 2C304000   push Brad_Sob.0040302C                   ;  CrackMe
00401576  |.  68 34304000   push Brad_Sob.00403034                   ;  Enter Registration Number
0040157B  |.  8B4D E0       mov ecx,[local.8]                        ;  mfc42.5F1D0040
0040157E  |.  E8 7B050000   call <jmp.&MFC42.#CWnd::MessageBoxA_4224>
00401583  |.  EB 3C         jmp short Brad_Sob.004015C1
00401585  |>  8D4D E4       lea ecx,[local.7]                        ;  将堆栈[local.7]存入edx寄存器中
00401588  |.  51            push ecx                                 ; /String2 = NULL
00401589  |.  8D55 F4       lea edx,[local.3]                        ; |将堆栈[local.3]存入edx寄存器中
0040158C  |.  52            push edx                                 ; |String1 = NULL
0040158D  |.  FF15 00204000 call dword ptr ds:[<&KERNEL32.lstrcmpA>] ; \lstrcmpA
00401593  |.  85C0          test eax,eax

这一段就是校验自己输入的注册码是否正确的函数,其中local.x代表的是ebp-(x*4),EBP加一个值一般存储的是函数的参数,减一个值一般存储的是函数的局部变量和返回值,local.x是被OD处理过的,使代码容易阅读。

经过分析,在跳转之前,对堆栈中的local.3和local.7进行了比较,因为是在一个函数内,EBP一般来说是不会变动的,对代码分析发现local.7存储的是“<BrD-SoB>”,而local.3是我们自己输入的注册码,因此基本上确定注册码是固定的“<BrD-SoB>”,尝试一下:

事实说明,注册码是这个。

结语

这个CrackMe是很简单的,是我人生中吃到的第一个草莓(CM:CrackMe),虽然简单,但还是给我了很多启发,让我有了很大的进步,但还需努力。以上只是一个新手的一己之言,见谅

如有错误,敬请指出,感谢指正!      —2019-04-08  22:57:43

 

 

 

赞(0) 打赏
转载请注明:飘零博客 » [CrackMe] 160个CrackMe之018-Brad Soblesky.1.exe
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

欢迎光临