【破解作者】 shiter
【作者邮箱】 shiter_2000@163.com
【作者主页】 http://shiter.programfan.com
【使用工具】 OD WINDASM98 VS.NET
【破解平台】 WinXP
【软件名称】 echap511.exe
【下载地址】 下载
【软件简介】 这个是一个CRACKME
【软件大小】 4k
【加壳方式】 无
【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享:)
--------------------------------------------------------------------------------
【破解内容】
00401041 /. 55 PUSH EBP
00401042 |. 8BEC MOV EBP,ESP
00401044 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
00401047 |. A3 54304000 MOV DWORD PTR DS:[403054],EAX
0040104C |. 8B45 0C MOV EAX,DWORD PTR SS:[EBP+C]
0040104F |. 3D 10010000 CMP EAX,110
00401054 |. 75 1A JNZ SHORT echap511.00401070
00401056 |. 68 B80B0000 PUSH 0BB8 ; /ControlID = BB8 (3000.)
0040105B |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
0040105E |. E8 19010000 CALL <JMP.&USER32.GetDlgItem> ; \GetDlgItem
00401063 |. A3 58304000 MOV DWORD PTR DS:[403058],EAX
00401068 |. 50 PUSH EAX ; /hWnd
00401069 |. E8 1A010000 CALL <JMP.&USER32.SetFocus> ; \SetFocus
0040106E |. EB 50 JMP SHORT echap511.004010C0
00401070 |> 83F8 10 CMP EAX,10
00401073 |. 75 0C JNZ SHORT echap511.00401081
00401075 |. 6A 00 PUSH 0 ; /Result = 0
00401077 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
0040107A |. E8 F7000000 CALL <JMP.&USER32.EndDialog> ; \EndDialog
0040107F |. EB 3F JMP SHORT echap511.004010C0
00401081 |> 3D 11010000 CMP EAX,111
00401086 |. 75 2F JNZ SHORT echap511.004010B7
00401088 |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
0040108B |. 66:3D B90B CMP AX,0BB9
0040108F |. 75 2F JNZ SHORT echap511.004010C0
00401091 |. C1E8 10 SHR EAX,10
00401094 |. 66:0BC0 OR AX,AX
00401097 |. 75 1C JNZ SHORT echap511.004010B5
00401099 |. 6A 0A PUSH 0A ; /Count = A (10.)
0040109B |. 68 44304000 PUSH echap511.00403044 ; |Buffer = echap511.00403044 字符变量地址为00403044
004010A0 |. 68 B80B0000 PUSH 0BB8 ; |ControlID = BB8 (3000.)
004010A5 |. FF35 54304000 PUSH DWORD PTR DS:[403054] ; |hWnd = NULL
004010AB |. E8 D2000000 CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004010B0 |. E8 14000000 CALL echap511.004010C9
004010B5 |> EB 09 JMP SHORT echap511.004010C0
004010B7 |> B8 00000000 MOV EAX,0
004010BC |. C9 LEAVE
004010BD |. C2 1000 RETN 10
004010C0 |> B8 01000000 MOV EAX,1
004010C5 |. C9 LEAVE
004010C6 \. C2 1000 RETN 10
004010C9 /$ 56 PUSH ESI
004010CA |. 57 PUSH EDI
004010CB |. 51 PUSH ECX
004010CC |. 33F6 XOR ESI,ESI
004010CE |. 33FF XOR EDI,EDI
004010D0 |. B9 08000000 MOV ECX,8 ECX=8 充当循环变量
004010D5 |. BE 44304000 MOV ESI,echap511.00403044 ESI="shitersh" 是我自己输入的注册码ASCII=73 68 69 74 65 72 73 68
004010DA |> 8036 32 /XOR BYTE PTR DS:[ESI],32 /将我输入的"shitersh"的ASCII码每个字节与0x32进行异或
004010DD |. 46 |INC ESI |
004010DE |.^E2 FA \LOOPD SHORT echap511.004010DA \一共循环8次,循环结果为41 5A 5B 46 57 40 41 5A
004010E0 |. BE 44304000 MOV ESI,echap511.00403044 令ESI=41 5A 5B 46 57 40 41 5A
004010E5 |. B9 04000000 MOV ECX,4 ECX=4 充当循环变量
004010EA |> 8A06 /MOV AL,BYTE PTR DS:[ESI] /AL和BL分别取41 5A 5B 46 57 40 41 5A中的相邻的前后两个字节
004010EC |. 8A5E 01 |MOV BL,BYTE PTR DS:[ESI+1] |即 (AL=41 BL=5A)(AL=5B BL=46)...
004010EF |. 32C3 |XOR AL,BL |AL 与 BL异或
004010F1 |. 8887 4C304000 |MOV BYTE PTR DS:[EDI+40304C],AL |将异或结果放入0040304C+EDI地址
004010F7 |. 83C6 02 |ADD ESI,2 |ESI地址当然要加2
004010FA |. 47 |INC EDI |EDI地址加1
004010FB |.^E2 ED \LOOPD SHORT echap511.004010EA \一共循环4次,循环结果为1B 1D 17 1B
004010FD |. BE 4C304000 MOV ESI,echap511.0040304C 令ESI=1B 1D 17 1B
00401102 |. 8A06 MOV AL,BYTE PTR DS:[ESI]
00401104 |. 8A5E 01 MOV BL,BYTE PTR DS:[ESI+1] 这几行的意思就是将1B 1D 17 1B按顺序将第一字节和第二字节异或
00401107 |. 32C3 XOR AL,BL 将第三和第四字节异或,最后再将分别异或后的两个结果进行异或
00401109 |. 8A5E 02 MOV BL,BYTE PTR DS:[ESI+2]
0040110C |. 8A4E 03 MOV CL,BYTE PTR DS:[ESI+3]
0040110F |. 32D9 XOR BL,CL
00401111 |. 32C3 XOR AL,BL 得到结果是AL=0xA
00401113 |. B9 08000000 MOV ECX,8 ECX=8 充当循环变量
00401118 |. BE 44304000 MOV ESI,echap511.00403044 令ESI=41 5A 5B 46 57 40 41 5A
0040111D |> 3006 /XOR BYTE PTR DS:[ESI],AL 将41 5A 5B 46 57 40 41 5A中的每个字节与0xA
0040111F |. 46 |INC ESI
00401120 |.^E2 FB \LOOPD SHORT echap511.0040111D 一共循环8次 循环结果为4B 50 51 4C 5D 4A 5B 50
00401122 |. B9 08000000 MOV ECX,8 ECX=8 充当循环变量
00401127 |. BE 44304000 MOV ESI,echap511.00403044 令ESI=4B 50 51 4C 5D 4A 5B 50
0040112C |. BF 08304000 MOV EDI,echap511.00403008 令EDI=71 18 59 1B 79 42 45 4C 这个系统内定的注册码
00401131 |> 8A06 /MOV AL,BYTE PTR DS:[ESI] /以下这几句的意思就是将ESI和EDI所指向的两组数据足个字节的比较
00401133 |. 3A07 |CMP AL,BYTE PTR DS:[EDI] |
00401135 |. 75 1D |JNZ SHORT echap511.00401154 |如果有一位不相同就跳转向死亡。
00401137 |. 46 |INC ESI |
00401138 |. 47 |INC EDI |好了到了这里就算是分析完了吧!
00401139 |.^E2 F6 \LOOPD SHORT echap511.00401131 \
0040113B |. 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040113D |. 68 35304000 PUSH echap511.00403035 ; |Title = "Crackme 1.0"
00401142 |. 68 10304000 PUSH echap511.00403010 ; |Text = "Good Work Cracker"
00401147 |. FF35 54304000 PUSH DWORD PTR DS:[403054] ; |hOwner = NULL
0040114D |. E8 3C000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
00401152 |. EB 17 JMP SHORT echap511.0040116B
00401154 |> 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401156 |. 68 35304000 PUSH echap511.00403035 ; |Title = "Crackme 1.0"
0040115B |. 68 22304000 PUSH echap511.00403022 ; |Text = "Bad Serial, Sorry!"
00401160 |. FF35 54304000 PUSH DWORD PTR DS:[403054] ; |hOwner = NULL
00401166 |. E8 23000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
0040116B |> 5F POP EDI
0040116C |. 5E POP ESI
0040116D |. 59 POP ECX
0040116E \. C3 RETN
0040116F CC INT3
--------------------------------------------------------------------------------
【破解总结】
这个程序是很简单的
思路就是
假设我输入的是"shitersh"
ASCII: 73 68 69 74 65 72 73 68
与0x32异或后 41 5A 5B 46 57 40 41 5A
\ / \ / \ / \ /
然后相临两为异或 1B 1D 17 1B
\ / \ /
然后在相临异或 6 C
\ /
然后在异或 A
然后将 41 5A 5B 46 57 40 41 5A 与 A 进行异或
得到 4B 50 51 4C 5D 4A 5B 50
而真正程序需要得到的是71 18 59 1B 79 42 45 4C
假设有X这个数值它的取值范围为0~0xFF
所以就需要将71 18 59 1B 79 42 45 4C先与X异或
而这个X又等于71 18 59 1B 79 42 45 4C先与X异或的结果再依照以上分析的方式进行异或后的值
X=F((71 18 59 1B 79 42 45 4C) XOR X)
用手算挺麻烦
写个程序让电脑来算算
--------------------------------------------------------------------------------
【算法注册机】
// vcstd1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "conio.h"
int _tmain(int argc, _TCHAR* argv[])
{
int sn[] = {0x71,0x18,0x59,0x1b,0x79,0x42,0x45,0x4c};
int sn1[8];
int sn2[4];
int sn3[2];
int keysn = 0x0;
for(int i = 0x0; i <= 0xff; i++)
{
for(int j = 0; j < 8; j++)
sn1[j] = sn[j] ^ i;
for(int j = 0,k = 0; j < 8; j+=2,k++)
sn2[k] = sn1[j] ^ sn1[j+1];
sn3[0] = sn2[0] ^ sn2[1];
sn3[1] = sn2[2] ^ sn2[3];
keysn = sn3[0] ^ sn3[1];
if(keysn == i)
{
for(int j = 0; j < 8; j++)
{
sn1[j] = sn[j] ^ keysn;
sn1[j] = sn1[j] ^0x32;
printf("%c",sn1[j]);
}
getch();
}
}
return 0;
}
--------------------------------------------------------------------------------
【爆破地址】
00401135 |. 75 1D |JNZ SHORT echap511.00401154
--------------------------------------------------------------------------------
【用户名、密码】
结果为Z3r0Ring 此为注册码
在对程序的编写的时候满以为我会得到好几组注册码
结果只有一组,然后就对我的程序进行调试发现
71 18 59 1B 79 42 45 4C不论与什么数字异或后,然后依照前面分析的方式进行异或后得到的那个X的值都是固定的0x19
然后还对其他的八个字节的这类进行测试,发现得到的都是固定数字
所以我就得到了一个结论
凡是8个字节的一组ASCII码依照以上方式异或,得到的结果都是一样的
如果知道了这个结论的话,那这个计算方式就简单多了...
--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!
下载
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)