飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 4799|回复: 8

一个简单至级的keyfile-crackme分析

[复制链接]

该用户从未签到

发表于 2005-11-29 13:30:57 | 显示全部楼层 |阅读模式
因为这人keyfile的保护比较简单,所以一直不打算写这个教程,我想有的兄弟可能早就把它破了.但看到一些新手不知如何下手,所以还是把这个教程贴出来了,不知道老大是不是允许我这样做.如果我做的不对,请老大批评,下次一定改正.

因为是针对初学者,所以我尽量写的详细些,希望其它兄弟有什么关于攻破keyfile保护的思路及方法,在后面跟下贴子,一起来帮助还在大门外徘徊的新手尽快入门.我写的有什么不对的地方,还望大家指正,以免误人.

od载入之后中断在如下代码处:
---------------------------------
00428001  pushad
00428002  jmp     ex1401.00428444
00428007  jmp     01438531
---------------------------------
分析:一开始PUSHAD把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
这是加壳程序通常的做法,壳代码执行完后会将这些寄存器出栈,并跳到
原始程序的入口代码执行.这里F8单步跟踪一次,看到ESP=0012FFA4,用著
名的ESP定律命令栏下断 hr 0012ffa4,回车,F9运行,断下来了:
--------------------------------
004283AA  popad                                  ; 这里和上面的pushad对应
004283AB  jnz     short ex1401.004283B5 ; 中断在这里,此时esp=0012ffc4,F8跳走
004283AD  mov     eax, 1
004283B2  retn    0C
004283B5  push    ex1401.00401000       ; 跳到这里,把OEP压入堆栈,下面的ret就会返回到OEP.
004283BA  retn
---------------------------------

===============================================================
脱壳后命令行下断bp CreateFileA,F9运行程序断下来了,堆栈提示如下:
---------------------------------------------------------------
0012FD40   004010B4  /CALL 到 CreateFileA 来自 1.004010AF
0012FD44   004020E5  |FileName = "[BCG].Key"
0012FD48   C0000000  |Access = GENERIC_READ|GENERIC_WRITE
0012FD4C   00000003  |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
0012FD50   00000000  |pSecurity = NULL
0012FD54   00000003  |Mode = OPEN_EXISTING
0012FD58   004020EF  |Attributes = READONLY|HIDDEN|SYSTEM|ARCHIVE|NORMAL|4>
0012FD5C   00000000  \hTemplateFile = NULL
---------------------------------------------------------------
从这里看出是要读取[BCG].Key文件,调用来自004010AF,Alt+F9返回到程序领空
---------------------------------------------------------------------
00401098  push    0                                 ; /hTemplateFile = NULL
0040109A  push    1.004020EF                  ; |Attributes = READONLY|HIDDEN|SYSTEM|ARCHIVE|NORMAL|402048
0040109F  push    3                                 ; |Mode = OPEN_EXISTING
004010A1  push    0                                ; |pSecurity = NULL
004010A3  push    3                                ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
004010A5  push    C0000000                    ; |Access = GENERIC_READ|GENERIC_WRITE
004010AA  push    1.004020E5                  ; |FileName = "[BCG].Key"
004010AF  call    <jmp.&kernel32.CreateFileA> ; \CreateFileA
004010B4  mov     dword ptr ds:[402000], eax  ;  此时eax=ffffffff是-1,说明打开[BCG].Key文件失败了,
004010B9  cmp     dword ptr ds:[402000], -1
004010C0  je      1.00401158                  ;  所以就会跳走了,
----------------------------------------------------------------
跳走之后就到这里了,可以看出是显示尚未成功的消息框.
----------------------------------------------------------------
00401158  push    1000                         ; /Style = MB_OK|MB_SYSTEMMODAL
0040115D  push    1.00402026                ; |Title = "OfficialCrackme"
00401162  push    1.00402083                ; |Text = "革命尚未成功,破解者仍需努力阿。^_^ GOOD LUCK!"
00401167  push    0                               ; |hOwner = NULL
00401169  call    <jmp.&user32.MessageBoxA> ; \MessageBoxA
================================================================
以上完成初步的粗跟踪,知道了程序要打开一个名为[BCG].Key的文件,
如果没有这个文件,就出现尚未成功的消息框,所以建一个文本文件,
命名为[BCG].Key,输入一些数据我输入的是123456.
Ctrl+F2重新运行,命令行下断点bp CreateFileA,F9运行程序,断下来后,
Alt+F9返回到程序领空
----------------------------------------------------------------
00401098  push    0                           ; /hTemplateFile = NULL
0040109A  push    1.004020EF                  ; |Attributes = READONLY|HIDDEN|SYSTEM|ARCHIVE|NORMAL|402048
0040109F  push    3                           ; |Mode = OPEN_EXISTING
004010A1  push    0                           ; |pSecurity = NULL
004010A3  push    3                           ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
004010A5  push    C0000000                    ; |Access = GENERIC_READ|GENERIC_WRITE
004010AA  push    1.004020E5                  ; |FileName = "[BCG].Key"
004010AF  call    <jmp.&kernel32.CreateFileA> ; \CreateFileA
004010B4  mov     dword ptr ds:[402000], eax  ;  此时eax返回打开文件的句柄.保存在402000
004010B9  cmp     dword ptr ds:[402000], -1
004010C0  je      1.00401158                  ;  这里不会跳走了,
----------------------------------------------
打开[bcg].key文件成功了,接着开始读文件里的内容
----------------------------------------------
004010C6  push    0                                 ; /pOverlapped = NULL
004010C8  push    1.00402107                  ; |pBytesRead = 1.00402107
004010CD  push    0A                               ; |BytesToRead = A (10.)
004010CF  push    1.004020F3                  ; |这里是读取的缓冲区指针,在命令行下d 4020f3观察一下
004010D4  push    dword ptr ds:[402000]       ; |这里就是上面打开的那个文件的句柄
004010DA  call    <jmp.&kernel32.ReadFile>    ; \ReadFile
-----------------------------------------------
这时在命令行下d 4020f3命令,查看一下4020f3的内容,
如下会看到我输入的123456.
---------
004020F3  31 32 33 34 35 36 00 00  123456..
-----------------------------------------------
004010DF  test    eax, eax
004010E1  je      short 1.00401158             ;  这里是判断是不是读取成功
004010E3  push    0                                  ; /pOverlapped = NULL
004010E5  push    1.00402107                   ; |pBytesRead = 1.00402107
004010EA  push    0A                                ; |读取缓冲区大小为10个字节
004010EC  push    1.004020FD                   ; |这里是读取的缓冲区指针,在命令行下d 4020fd观察一下
004010F1  push    dword ptr ds:[402000]        ; |这里就是上面打开的那个文件的句柄
004010F7  call    <jmp.&kernel32.ReadFile>     ; \ReadFile
----------------------------------------------------
从上面看来对这个[bcg].key文件读了两次,每次读10个字节
分别放在了内存地址004020F3和004020FD
----------------------------------------------------
004010FC  test    eax, eax
004010FE  je      short 1.00401158                 ;  这里是判断是不是读取成功
00401100  push    dword ptr ds:[402000]        ; /这里就是上面打开的那个文件的句柄
00401106  call    <jmp.&kernel32.CloseHandle>  ; \关闭前面打开的文件对象
0040110B  xor     eax, eax
0040110D  jmp     short 1.00401113                ;  跳到关键的地方去了!
0040110F  leave
00401110  retn    10
-----------------------------------------------
下面就是关键了,在命令行下d 4020f3,一边跟踪
一边观察数据的变化
-----------------------------------------------
00401113  xor     byte ptr ds:[eax+4020F3], 58 ;  将缓冲区字符串依次与0x58异或
0040111A  inc     eax
0040111B  cmp     byte ptr ds:[eax+4020F3], 0  ;  直到遇到00结尾
00401122  jnz     short 1.00401113
-----------------------------------------------
处理完后来个比较
-------------------
00401124  push    1.004020F3                   ; /字符串地址
00401129  push    1.004020FD                   ; |字符串地址
0040112E  call    <jmp.&kernel32.lstrcmp>   ; \比较是不是相等
00401133  cmp     eax, 0
00401136  je      short 1.0040113E             ;  相等就成功了
-----------------------------------------------
00401138  jmp     short 1.00401158
0040113A  leave
0040113B  retn    10
0040113E  push    1000                         ; /Style = MB_OK|MB_SYSTEMMODAL
00401143  push    1.00402026                   ; |Title = "OfficialCrackme"
00401148  push    1.004020BF                   ; |Text = "注册验证成功,恭喜您成功破解了这个程序"
0040114D  push    0                            ; |hOwner = NULL
0040114F  call    <jmp.&user32.MessageBoxA>    ; \MessageBoxA
00401154  leave
00401155  retn    10
00401158  push    1000                         ; /Style = MB_OK|MB_SYSTEMMODAL
0040115D  push    1.00402026               ; |Title = "OfficialCrackme"
00401162  push    1.00402083                ; |Text = "革命尚未成功,破解者仍需努力阿。^_^ GOOD LUCK!"
00401167  push    0                               ; |hOwner = NULL
00401169  call    <jmp.&user32.MessageBoxA>    ; \MessageBoxA
0040116E  leave
0040116F  retn    10
00401172  push    1000                          ; /Style = MB_OK|MB_SYSTEMMODAL
00401177  push    1.00402026                 ; |Title = "OfficialCrackme"
0040117C  push    1.00402036                 ; |Text = "中国破解组织BCG(BeNGiN's CrACKiNG GrOUp)Official CrackMe程序  娃娃/[BCG]制作"
00401181  push    0                                 ; |hOwner = NULL
00401183  call    <jmp.&user32.MessageBoxA>    ; \MessageBoxA
00401188  leave
00401189  retn    10
======================================================================
总结一下:
只要保证运算后的内存地址004020F3和004020FD指向的字符串相等就能成功,
大家都知道,字符串是以0结尾的.因为运算是简单的与58异或,而0 == 58 xor 58
58就是字符X,所以文件内容可以是如下形式:
*********X*********X
********X*********X*
......
只要X前后的*相等就可以,有很多种组合.
-------------------------------------------
另外如果文件小于10个字符,004020FD指向的总会是个空串,004020F3要构造一个空串
只要内容第一个是X其它任意,总计小于10个字符就行了,
所以还可以是如下形式:
X*********
======================================================================
surge[PYG]
surgefree@163.com
2005-11-29
完.
PYG19周年生日快乐!

该用户从未签到

发表于 2005-11-29 15:39:09 | 显示全部楼层
兄弟好样的,写的好详细啊```分析得很好,学习了  ^_^
PYG19周年生日快乐!

该用户从未签到

发表于 2005-12-27 14:01:52 | 显示全部楼层
看着相当的不错啊   我代新手们谢谢你了   看这个让我想了半天  最后终于是看懂了  不错
PYG19周年生日快乐!
  • TA的每日心情
    开心
    2018-5-6 16:27
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    发表于 2006-3-27 00:26:46 | 显示全部楼层
    学习咯。。。
    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2015-12-17 23:46
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2006-7-24 13:11:43 | 显示全部楼层

    懂了,

    明白了,谢谢
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2006-7-25 09:04:47 | 显示全部楼层
    提示: 作者被禁止或删除 内容自动屏蔽
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2006-7-26 19:39:26 | 显示全部楼层
    没弄名太keyfile怎么搞,米玩过
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2006-7-28 23:09:58 | 显示全部楼层
    新手来学习的好文章哦~~~
    楼主不要那么谦虚哦~~
    严重支持~~
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2006-7-29 15:09:08 | 显示全部楼层
    看着相当的不错啊   我代新手们谢谢你了
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表