Easy CrackMe

发布日期:2019年02月03日 类别:reversing 题目来源:reversing.kr 题目链接:http://reversing.kr/challenge.php

双击点开 Easy CrackMe.exe,将弹出一个对话框,要求输入密码。点击按钮后将对密码进行验证。

screenshot

点击此处显示 Writeup
点击此处隐藏 Writeup

首先用 Cutter 打开 Easy CrackMe.exe,看看 Strings 里面有没有什么特别的:

strings

AGR3versing 似乎有点奇怪。输进去看看,不对。除此之外,就是 Wrong PasswordCongratulations 最吸引我们了。看一下 Congratulations 的交叉引用,跳到了:

看起来这就是最终弹出检查结果的地方了。往上翻一下,在同一个函数里面,就是检查的逻辑:

/ (fcn) sub.USER32.dll_GetDlgItemTextA_401080 205
|   long sub.USER32.dll_GetDlgItemTextA_401080 (HWND hDlg, int nIDDlgItem, LPSTR lpString, int nMaxCount);
|           ; var unsigned int local_4h @ esp+0x4
|           ; var unsigned int local_5h @ esp+0x5
|           ; var int local_8h @ esp+0x8
|           ; var int local_ah @ esp+0xa
|           ; var int local_10h @ esp+0x10
|           ; arg int arg_70h @ esp+0x70
|           0x00401080      sub  esp, 0x64 ; 'd'
|           0x00401083      push edi
|           0x00401084      mov  ecx, 0x18 ; 24
|           0x00401089      xor  eax, eax
|           0x0040108b      lea  edi, [local_5h] ; 5
|           0x0040108f      mov  byte [local_4h], 0
|           0x00401094      push 0x64 ; 'd' ; 100
|           0x00401096      rep  stosd dword es:[edi], eax
|           0x00401098      stosw word es:[edi], ax
|           0x0040109a      stosb byte es:[edi], al
|           0x0040109b      mov  edi, dword [arg_70h] ; [0x70:4]=-1 ; 'p' ; 112
|           0x0040109f      lea  eax, [local_8h] ; 8 ;; !local_4h
|           0x004010a3      push eax
|           0x004010a4      push 0x3e8 ; 1000
|           0x004010a9      push edi
|           0x004010aa      call dword [sym.imp.USER32.dll_GetDlgItemTextA] ; 0x40509c ; "\U"
|           0x004010b0      cmp  byte [local_5h], 0x61 ; 'a' ; [0x5:1]=255 ; 97
|       ,=< 0x004010b5      jne  0x401135
|       |   0x004010b7      push 2 ; 2
|       |   0x004010b9      lea  ecx, 
|           0x004010b9      lea  ecx, [local_ah] ; 0xa ; 10 ;; local_6h
|           0x004010bd      push 0x406078 ; 'x`@' ; "5y"
|           0x004010c2      push ecx
|           0x004010c3      call fcn.00401150
|           0x004010c8      add  esp, 0xc
|           0x004010cb      test eax, eax
|       ,=< 0x004010cd      jne  0x401135
|       |   0x004010cf      push ebx
|       |   0x004010d0      push esi
|       |   0x004010d1      mov  esi, 0x40606c ; 'l`@' ; "R3versing"
|       |   0x004010d6      lea  eax, [local_10h] ; 0x10 ; 16 ;; local_8h
|      .--> 0x004010da      mov  dl, byte [eax]
|      :|   0x004010dc      mov  bl, byte [esi]
|      :|   0x004010de      mov  cl, dl
|      :|   0x004010e0      cmp  dl, bl
|     ,===< 0x004010e2      jne  0x401102
|     |:|   0x004010e4      test cl, cl
|    ,====< 0x004010e6      je   0x4010fe
|    ||:|   0x004010e8      mov  dl, byte [eax + 1] ; [0x1:1]=255 ; 1
|    ||:|   0x004010eb      mov  bl, byte [esi + 1] ; [0x1:1]=255 ; 1
|    ||:|   0x004010ee      mov  cl, dl
|    ||:|   0x004010f0      cmp  dl, bl
|   ,=====< 0x004010f2      jne  0x401102
|   |||:|   0x004010f4      add  eax, 2
|   |||:|   0x004010f7      add  esi, 2
|   |||:|   0x004010fa      test cl, cl
|   |||`==< 0x004010fc      jne  0x4010da
|   |`----> 0x004010fe      xor  eax, eax
|   | |,==< 0x00401100      jmp  0x401107
|   `-`---> 0x00401102      sbb  eax, eax
|      ||   0x00401104      sbb  eax, 0xffffffffffffffff
|      `--> 0x00401107      pop  esi
|       |   0x00401108      pop  ebx
|       |   0x00401109      test eax, eax
|      ,==< 0x0040110b      jne  0x401135
|      ||   0x0040110d      cmp  byte [local_4h], 0x45 ; 'E' ; [0x4:1]=255 ; 69
|     ,===< 0x00401112      jne  0x401135
|     |||   0x00401114      push 0x40 ; '@' ; 64
|     |||   0x00401116      push str.EasyCrackMe ; 0x406058 ; "EasyCrackMe"
|     |||   0x0040111b      push str.Congratulation ; 0x406044 ; "Congratulation !!"

由于这个函数的局部变量由 esp 索引,而 R2 没有捕捉到 esp 的变化,导致函数中的变量名的使用会有些误导,在分析时需要注意。举例来说,上面的代码片段 14 行有一处 push,导致第 20 行的 local_8h(esp+8)实际应为 local_4h。我在有问题的语句后做了注释。

首先来看第 24 行,GetDlgItemText 是一个 Win32 API,其中第三个参数是字符串的地址。第 21 行压入的 eax 即为第三个参数,它指向的是 local_4h,因此 local_4h 就是字符串的第零个字符的地址。

随后,第 25 行判断了一下第一个字符的内容是否为 a;第 32 行将 5y 和第三个字符地址的地址传入了 fcn.00401150。去看一下这个函数:

看起来只是在做字符串比较,所以第三四个字符应该是 5y 。再继续看,从第38行开始,字符串 R3versing 出现了,下面的代码又是在不断地比较每一个字符是否与 R3versing 相同。最后 64 行比较了第一个字符是否为 E,至此密码已经找到了:Ea5yR3versing

dontpan1c 的 CTF 笔记
南阳一出即相,淮阴一出即将。

知识共享许可协议

本站所有作品均采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

本站不包含明令禁止公开解题过程的题目。

本站由 Jekyll 强力驱动。