-
-
KEYFILE分析实例
-
发表于:
2006-7-21 12:28
7091
-
【破文标题】KEYFILE实例分析(简单)
【破文作者】逍遥风
【作者邮箱】tc-xb@163.com
【破解工具】OD winHex
【破解平台】winXp
【软件名称】FaNt0m's CrackMe #6
【原版下载】www.crackmes.de
----------------------------------------------------------------------
最近有好多CRACKME的分析但很少见KF类型的.
所以写一个简单的KEYFILE的CRACKMEDE的分析。过程比较典型,拿来与广大菜鸟享。
高手见笑。
话不多说。直接开始。
对付这类简单的KEYFILE,可以按找两个大的步骤进行
1)找出KEY文件的文件名
用OD载入这个CRACKME。
先用字符串查找看看能不能得到些有用的信息。打开字符串参考(如图1)。成功与失败的提示都有,看来重要的线索已经找到了。
双击任意一个提示,就来到了相对应的代码处。
0040116C |> \6A 10 PUSH 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
0040116E |. 68 23304000 PUSH CRACKME6.00403023 ; |error!
00401173 |. 68 52304000 PUSH CRACKME6.00403052 ; |invalid key!
00401178 |. 6A 00 PUSH 0 ; |hOwner = NULL
0040117A |. E8 2F000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
0040117F |. EB 15 JMP SHORT CRACKME6.00401196
00401181 |> 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401183 |. 68 76304000 PUSH CRACKME6.00403076 ; |correct!!!
00401188 |. 68 5F304000 PUSH CRACKME6.0040305F ; |correct key! good job!
0040118D |. 6A 00 PUSH 0 ; |hOwner = NULL
0040118F |. E8 1A000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
我们的目标不是这些,而是根据这些提示找到验证开始的地方。从这段代码开始向上找,由于这个CRACKME是KEYFILE型的
所以一般情况下我们的目标就是要找到CreateFileA这个函数。一路向上找到这里。
004010E1 /$ 6A 00 PUSH 0 ; /hTemplateFile = NULL(下断点)
004010E3 |. 68 80000000 PUSH 80 ; |Attributes = NORMAL
004010E8 |. 6A 03 PUSH 3 ; |Mode = OPEN_EXISTING
004010EA |. 6A 00 PUSH 0 ; |pSecurity = NULL
004010EC |. 6A 01 PUSH 1 ; |ShareMode = FILE_SHARE_READ
004010EE |. 68 00000080 PUSH 80000000 ; |Access = GENERIC_READ
004010F3 |. 68 17304000 PUSH CRACKME6.00403017 ; |keyfile.dat (注意这个)
004010F8 |. E8 BD000000 CALL <JMP.&KERNEL32.CreateFileA> ; \CreateFileA
找到这个函数了,注意它的上面有一个keyfile.dat。没错这就是我们要找的KEY文件的文件名了。
第一个目标已经完成了。现在打开WINHEX新建一个文件,字节数先随便输入一个但要记住。已10个字节为例建立
一个名位keyfile.dat的文件(如图2),保存。在004010E1处下断点,用OD重新载入。
2)开始跟踪,
在CRACKME中点击CHECK后程序中断了。
下面就开始了一个典型的KEYFILE验证过程。这个过程可以分为三个步骤
第一步:查找KEY文件。
004010F8 |. E8 BD000000 CALL <JMP.&KERNEL32.CreateFileA> ; \CreateFileA
004010FD |. A3 88304000 MOV DWORD PTR DS:[403088],EAX ; 开始读文件
00401102 |. 83F8 FF CMP EAX,-1 ; 文件存在吗
00401105 |. 75 14 JNZ SHORT CRACKME6.0040111B ; KEY文件已存在就继续验证,不存在就跳出错误提示
00401107 |. 6A 10 PUSH 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401109 |. 68 23304000 PUSH CRACKME6.00403023 ; |error!
0040110E |. 68 2A304000 PUSH CRACKME6.0040302A ; |key file not found!
00401113 |. 6A 00 PUSH 0 ; |hOwner = NULL
00401115 |. E8 94000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
如果没有一个名为“keyfile.dat”的文件,那么就会出现key file not found。
第二步:检验KEY文件
联系上一段代码中的“JNZ SHORT CRACKME6.0040111B”如果KEY文件存在就会来到这里
0040111B |> \6A 00 PUSH 0 ; /pOverlapped = NULL
0040111D |. 68 96304000 PUSH CRACKME6.00403096 ; |pBytesRead = CRACKME6.00403096
00401122 |. 6A 0A PUSH 0A ; |BytesToRead = A (10.)
00401124 |. 68 8C304000 PUSH CRACKME6.0040308C ; |Buffer = CRACKME6.0040308C
00401129 |. FF35 88304000 PUSH DWORD PTR DS:[403088] ; |hFile = 00000080 (window)
0040112F |. E8 98000000 CALL <JMP.&KERNEL32.ReadFile> ; \ReadFile
00401134 |. 83F8 00 CMP EAX,0 ;
00401137 |. 75 15 JNZ SHORT CRACKME6.0040114E ;
00401139 |. 6A 10 PUSH 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
0040113B |. 68 23304000 PUSH CRACKME6.00403023 ; |error!
00401140 |. 68 3E304000 PUSH CRACKME6.0040303E ; |error reading file!
00401145 |. 6A 00 PUSH 0 ; |hOwner = NULL
00401147 |. E8 62000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
这可以看作是对KEY文件的一个检验过程。可以理解为“这个KEY文件可读吗?”。不同的CRACKME对KEY文件的要求是不一样的。大多数KEYFILE型的CRACKME都会用
GetFileSize这个函数来检验文件的字节数是否符合要求。
例:http://bbs.pediy.com/showthread.php?s=&threadid=23785
http://bbs.pediy.com/showthread.php?s=&threadid=25086
第三步:读取KEY文件。
经过了前面两步,程序就开始读取KEY文件的内容了。程序是按怎样的顺序读取文件的内容呢?
0040114E |> \8D15 8C304000 LEA EDX,DWORD PTR DS:[40308C] ; 取KEY文件的内容放进EDX中
为什么说这句代码就是取KEY文件的内容的?
在F8单步到这一句时,在命令行输入命令:d 40308C.显示的结果(如图3)。地址40308C处的内容就是KEY文件的内容
所以程序在这里将KEY文件的内容放进了EDX中
00401154 |. 83C2 05 ADD EDX,5 ; EDX=EDX+5(即:取文件的第6个字节的内容)
为什么说是取文件的第6个字节的内容呢?
在执行这段代码前注意EDX的值(如图4) ,执行过ADD EDX,5后EDX的值(如图5)
在命令行输入命令:d 403091结果(如图6)。地址403091处的内容正是KEY文件中第6字节的内容,所以程序在这里读取了文件第6字节的内容。
00401157 |. 803A 31 CMP BYTE PTR DS:[EDX],31 ; 第六个字节的内容与0x31相比较
0040115A |. 75 10 JNZ SHORT CRACKME6.0040116C ; 不相等就跳向失败
0040115C |. 83C2 03 ADD EDX,3 ; EDX=EDX+3(即:取KEY文件第9个字节的内容)
执行过这一句后在一次注意EDX的值,(如图7)。在命令行输入d 403094
结果(如图8)
0040115F |. 803A 33 CMP BYTE PTR DS:[EDX],33 ; 第9个字节的内容与0x33相比较
00401162 |. 75 08 JNZ SHORT CRACKME6.0040116C ; 不相等就跳向失败
00401164 |. 42 INC EDX ; EDX+1(即:取KEY文件的第10个字节的内容)
这里方法和上面一样,动手试一下。
00401165 |. 803A 30 CMP BYTE PTR DS:[EDX],30 ; 第10个字节的内容与0x30相比较
00401168 |. 74 02 JE SHORT CRACKME6.0040116C ; 相等就跳向失败
0040116A |. EB 15 JMP SHORT CRACKME6.00401181 ; 第10个字节的内容不等于0x30就成功
经过了一个简单的算法验证,如果符合算法要求就成功。
0040116C |> \6A 10 PUSH 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
0040116E |. 68 23304000 PUSH CRACKME6.00403023 ; |error!
00401173 |. 68 52304000 PUSH CRACKME6.00403052 ; |invalid key!
00401178 |. 6A 00 PUSH 0 ; |hOwner = NULL
0040117A |. E8 2F000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
0040117F |. EB 15 JMP SHORT CRACKME6.00401196
00401181 |> 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401183 |. 68 76304000 PUSH CRACKME6.00403076 ; |correct!!!
00401188 |. 68 5F304000 PUSH CRACKME6.0040305F ; |correct key! good job!
0040118D |. 6A 00 PUSH 0 ; |hOwner = NULL
0040118F |. E8 1A000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
总结一下
1)KEY文件的文件名必须是keyfile.dat
2)KEY文件的字节数必须大于9
3)KEY文件第6字节内容必须为31,第9字节内容必须为33,第10字节内容不能为30
所以用WINHEX建立的文件(如图9)
----------------------------------------------------------------------
一点心得,希望对大家有所帮助
----------------------------------------------------------------------
【版权声明】本文只为交流,转载请保留作者及文章完整性
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课