【文章标题】: 简单算法追踪过关key
【文章作者】: wyxsky
【软件名称】: crackme
【下载地址】: http://bbs.pediy.com/attachment.php?attachmentid=44257&stc=1&d=1275812142
【保护方式】: 无
【编写语言】: Microsoft Visual C++ 6.0
【使用工具】: OllyDBG v1.10,PEiD
【操作平台】: Windows XP
【软件介绍】: 追踪过关key
【作者声明】: 第一次写这种文章,失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
一个小的crackme,记录一下。
首先运行程序,输入code,得到错误提示:"You Don't Guess it~"
载入OD,搜索字符串,找到关键比较处,"good! the key is your input o(^o^)o\n",看来我们不得不追踪算法部分。
00401000 81EC D0070000 sub esp,7D0
00401006 68 70704000 push CrackMe1.00407070 ; can you guess the code:
0040100B E8 AA010000 call CrackMe1.004011BA
00401010 8D4424 04 lea eax,dword ptr ss:[esp+4]
00401014 50 push eax
00401015 E8 56010000 call CrackMe1.00401170
0040101A 8D4C24 08 lea ecx,dword ptr ss:[esp+8] ; code地址放入ecx中
0040101E 51 push ecx ; code入栈
0040101F E8 3C000000 call CrackMe1.00401060 ; 这个CALL就是判断用户输入是否正确的函数
00401024 83C4 0C add esp,0C ; 平衡堆栈(C调用约定)
00401027 85C0 test eax,eax ; eax保存函数返回值,eax=0则注册失败
00401029 74 16 je short CrackMe1.00401041
0040102B 68 48704000 push CrackMe1.00407048 ; good! the key is your input o(^o^)o\n
00401030 E8 85010000 call CrackMe1.004011BA
00401035 83C4 04 add esp,4
00401038 33C0 xor eax,eax
0040103A 81C4 D0070000 add esp,7D0
00401040 C3 retn
00401041 68 30704000 push CrackMe1.00407030 ; you don't guess it~\n
00401046 E8 6F010000 call CrackMe1.004011BA
0040104B 83C4 04 add esp,4
0040104E 33C0 xor eax,eax
00401050 81C4 D0070000 add esp,7D0
00401056 C3 retn
输入code后,我们在0040101F E8 3C000000 call CrackMe1.00401060,F7步进
00401060 83EC 10 sub esp,10 ; 函数开始的地方。
00401063 A1 8C704000 mov eax,dword ptr ds:[40708C] ; key的1-4位
00401068 8B0D 90704000 mov ecx,dword ptr ds:[407090] ; key的5-8位
0040106E 53 push ebx
0040106F 894424 04 mov dword ptr ss:[esp+4],eax
00401073 66:A1 98704000 mov ax,word ptr ds:[407098] ; key的13-14位
00401079 894C24 08 mov dword ptr ss:[esp+8],ecx
0040107D 8A0D 9A704000 mov cl,byte ptr ds:[40709A] ; 写入最后的00
00401083 56 push esi
00401084 8B7424 1C mov esi,dword ptr ss:[esp+1C] ; esi=早先保存的code
00401088 57 push edi
00401089 66:894424 18 mov word ptr ss:[esp+18],ax
0040108E 884C24 1A mov byte ptr ss:[esp+1A],cl
00401092 8BFE mov edi,esi
00401094 83C9 FF or ecx,FFFFFFFF
00401097 33C0 xor eax,eax ; 清0
00401099 8B15 94704000 mov edx,dword ptr ds:[407094] ; key的9-12位
0040109F F2:AE repne scas byte ptr es:[edi] ; 扫描字符串ES:[EDI]中的AL字节值,遇到AL值停止,求字符串长度
004010A1 F7D1 not ecx
004010A3 49 dec ecx ; 求得输入字符串长度,保存在ecx
004010A4 895424 14 mov dword ptr ss:[esp+14],edx
004010A8 8BD1 mov edx,ecx ; edx=ecx
004010AA 8D7C24 0C lea edi,dword ptr ss:[esp+C]
004010AE 83C9 FF or ecx,FFFFFFFF
004010B1 F2:AE repne scas byte ptr es:[edi]
004010B3 F7D1 not ecx
004010B5 49 dec ecx
004010B6 3BD1 cmp edx,ecx ; edx用户输入code长度,ecx保存key字符串长度,比较输入长度是否为14
004010B8 0F85 9C000000 jnz CrackMe1.0040115A
004010BE 8BFE mov edi,esi
004010C0 83C9 FF or ecx,FFFFFFFF
004010C3 33D2 xor edx,edx
004010C5 F2:AE repne scas byte ptr es:[edi]
004010C7 F7D1 not ecx
004010C9 49 dec ecx ; 再次求用户输入code长度,判断是否为0
004010CA 74 19 je short CrackMe1.004010E5
004010CC 8A0432 mov al,byte ptr ds:[edx+esi] ; 逐位读取用户输入的code
004010CF 8BFE mov edi,esi
004010D1 34 20 xor al,20 ; 特定位翻转,关键
004010D3 83C9 FF or ecx,FFFFFFFF
004010D6 880432 mov byte ptr ds:[edx+esi],al
004010D9 33C0 xor eax,eax ; 清0
004010DB 42 inc edx ; edx++,类似循环变量i
004010DC F2:AE repne scas byte ptr es:[edi]
004010DE F7D1 not ecx
004010E0 49 dec ecx ; 计算字符串长度后保存在ecx中
004010E1 3BD1 cmp edx,ecx ; 计算是否到最后一位了
004010E3 ^ 72 E7 jb short CrackMe1.004010CC
004010E5 8D7C24 0C lea edi,dword ptr ss:[esp+C]
004010E9 83C9 FF or ecx,FFFFFFFF
004010EC 33C0 xor eax,eax
004010EE 33D2 xor edx,edx
004010F0 F2:AE repne scas byte ptr es:[edi]
004010F2 F7D1 not ecx
004010F4 49 dec ecx
004010F5 74 1D je short CrackMe1.00401114 ; 比较key字符串长度是否为0
004010F7 8A4414 0C mov al,byte ptr ss:[esp+edx+C] ; 逐位读取key
004010FB 8D7C24 0C lea edi,dword ptr ss:[esp+C]
004010FF 04 FB add al,0FB ; 对指定位加0FB,关键代码
00401101 83C9 FF or ecx,FFFFFFFF
00401104 884414 0C mov byte ptr ss:[esp+edx+C],al
00401108 33C0 xor eax,eax
0040110A 42 inc edx
0040110B F2:AE repne scas byte ptr es:[edi]
0040110D F7D1 not ecx
0040110F 49 dec ecx
00401110 3BD1 cmp edx,ecx
00401112 ^ 72 E3 jb short CrackMe1.004010F7
00401114 8D7C24 0C lea edi,dword ptr ss:[esp+C]
00401118 83C9 FF or ecx,FFFFFFFF
0040111B 33C0 xor eax,eax
0040111D 33D2 xor edx,edx
0040111F F2:AE repne scas byte ptr es:[edi]
00401121 F7D1 not ecx
00401123 49 dec ecx
00401124 74 28 je short CrackMe1.0040114E
00401126 8D4424 0C lea eax,dword ptr ss:[esp+C]
0040112A 2BF0 sub esi,eax
0040112C 8A5C14 0C mov bl,byte ptr ss:[esp+edx+C]
00401130 8D4414 0C lea eax,dword ptr ss:[esp+edx+C]
00401134 8A0C06 mov cl,byte ptr ds:[esi+eax]
00401137 3ACB cmp cl,bl ; 逐位比较,关键
00401139 75 1F jnz short CrackMe1.0040115A
0040113B 8D7C24 0C lea edi,dword ptr ss:[esp+C]
0040113F 83C9 FF or ecx,FFFFFFFF
00401142 33C0 xor eax,eax
00401144 42 inc edx
00401145 F2:AE repne scas byte ptr es:[edi]
00401147 F7D1 not ecx
00401149 49 dec ecx
0040114A 3BD1 cmp edx,ecx
0040114C ^ 72 DE jb short CrackMe1.0040112C
0040114E 5F pop edi
0040114F 5E pop esi
00401150 B8 01000000 mov eax,1
00401155 5B pop ebx
00401156 83C4 10 add esp,10
00401159 C3 retn
0040115A 5F pop edi
0040115B 5E pop esi
0040115C 33C0 xor eax,eax ; 清0
0040115E 5B pop ebx
0040115F 83C4 10 add esp,10
00401162 C3 retn
大概理清了key的比较流程:对程序的key逐位增加0FB,对用户输入的code逐位进行特定位翻转(第6位翻转:xor al,20),然后逐位比较是否相同。
那我们可以在得到“对程序的key逐位增加0FB”的结果后,再次进行“特定位翻转(第6位翻转:xor al,20)”,即可得到
“对程序的key逐位增加0FB”的结果:63 52 14 43 4b 69 53 73 4f 65 14 53 59 01 00
“对第6位翻转:xor al,20”的结果:43 72 34 63 6B 49 73 53 6F 45 34 73 79 21 00
43 72 34 63 6B 49 73 53 6F 45 34 73 79 21 00转换为ASCII:
Key:Cr4ckIsSoE4sy!
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!