【破解作者】 Night
【作者主页】 www.freecracker.com
【使用工具】 OD
【破解平台】 Win7
【软件名称】 riijj_cm_20041121.zip
------------------------------------------------------------------------------------------------------------
00401030 /$ A1 846B4000 mov eax,dword ptr ds:[0x406B84] ; 这里是验证部分
00401035 |. 85C0 test eax,eax
00401037 |. 0F84 90000000 je riijj_cr.004010CD
0040103D |. 56 push esi
0040103E |. 57 push edi
0040103F |. E8 BCFFFFFF call riijj_cr.00401000
00401044 |. BF F06B4000 mov edi,riijj_cr.00406BF0 ; ASCII "Night"
00401049 |. 83C9 FF or ecx,0xFFFFFFFF ; ecx = 4
0040104C |. 33C0 xor eax,eax ; eax = 0
0040104E |. C705 846B4000>mov dword ptr ds:[0x406B84],0x0 ; ds:[0x406B84] = 0
00401058 |. F2:AE repne scas byte ptr es:[edi] ; 获取用户名字符串长度
0040105A |. F7D1 not ecx ; ecx中存放的是用户名长度
0040105C |. 2BF9 sub edi,ecx ; edi 指向了用户名
0040105E |. C705 506C4000>mov dword ptr ds:[0x406C50],0x1 ; 0x406C50 = 1
00401068 |. 8BC1 mov eax,ecx ; eax 中存放用户名长度
0040106A |. 8BF7 mov esi,edi ; esi指向了 用户名
0040106C |. BF 406C4000 mov edi,riijj_cr.00406C40 ; ASCII "Night"
00401071 |. C1E9 02 shr ecx,0x2 ; ecx = ecx >> 2
00401074 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi] ; 把用户名赋值到 es:[edi] 中 长度为 ecx
00401076 |. 8BC8 mov ecx,eax ; ecx 中存放用户名长度
00401078 |. 33C0 xor eax,eax ; eax = 0
0040107A |. 83E1 03 and ecx,0x3 ; ecx = ecx & 3
0040107D |. F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[esi] ; 把用户名赋值到 es:[edi] 中 长度为 ecx
0040107F |. BF 006C4000 mov edi,riijj_cr.00406C00 ; edi 指向了 Key值
00401084 |. 83C9 FF or ecx,0xFFFFFFFF ; ecx = -1
00401087 |. F2:AE repne scas byte ptr es:[edi]
00401089 |. F7D1 not ecx ; 取Key值长度 保存到 ecx 中
0040108B |. 2BF9 sub edi,ecx ; edi 指向了Key值
0040108D |. A1 7C6B4000 mov eax,dword ptr ds:[0x406B7C] ; eax = 10001010
00401092 |. 8BD1 mov edx,ecx ; edx 中保存Key值的长度
00401094 |. 8BF7 mov esi,edi ; esi 指向了Key值
00401096 |. BF 206C4000 mov edi,riijj_cr.00406C20 ; ASCII "1234567890"
0040109B |. C1E9 02 shr ecx,0x2 ; ecx = ecx >> 2
0040109E |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi] ; 把Key值保存到es:[edi] 中 长度为 ecx
004010A0 |. 8BCA mov ecx,edx ; Key值长度保存到 ecx 中
004010A2 |. 83E1 03 and ecx,0x3 ; ecx = ecx & 3
004010A5 |. F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[esi] ; 把Key值保存到es:[edi] 中 长度为 ecx
004010A7 |. 5F pop edi
004010A8 |. 5E pop esi
004010A9 |. 85C0 test eax,eax ; 判断eax 是否为 0 如果 为 0 就挂掉了
004010AB |. 74 16 je Xriijj_cr.004010C3
004010AD |. 8B0D 806B4000 mov ecx,dword ptr ds:[0x406B80] ; ds:[0x406B80] = 3044E
004010B3 |. 51 push ecx
004010B4 |. 68 206C4000 push riijj_cr.00406C20 ; ASCII "1234567890"
004010B9 |. 68 406C4000 push riijj_cr.00406C40 ; ASCII "Night"
004010BE |. FFD0 call eax
{
10001010 > 81EC 84000000 sub esp,0x84
10001016 B9 19000000 mov ecx,0x19
1000101B 33C0 xor eax,eax ; eax = 0
1000101D 53 push ebx
1000101E 55 push ebp
1000101F 56 push esi
10001020 57 push edi
10001021 BE 54500010 mov esi,pf1.10005054 ; fytugjhkuijonlbpvqmcnxbvzdaeqrwtryetdgfkgphonuivmdbxfanqydexzwztqnkcfkvcpvlbmhotyiufdkdnjxuzyqhfstae
10001026 8D7C24 30 lea edi,dword ptr ss:[esp+0x30]
1000102A F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi]
1000102C 8B9C24 98000000 mov ebx,dword ptr ss:[esp+0x98] ; 用户名保存到 ebx中
10001033 83C9 FF or ecx,0xFFFFFFFF ; ecx = -1
10001036 8BFB mov edi,ebx ; edi 指向了用户名
10001038 F2:AE repne scas byte ptr es:[edi] ; 求用户名长度 保存到 ecx 中
1000103A 8BBC24 9C000000 mov edi,dword ptr ss:[esp+0x9C] ; edi 指向了Key值
10001041 F7D1 not ecx ; ecx 中保存了用户名的长度
10001043 49 dec ecx ; ecx = ecx - 1
10001044 8BE9 mov ebp,ecx ; ebp = ecx
10001046 83C9 FF or ecx,0xFFFFFFFF ; ecx = ecx | 0xFFFFFFFF
10001049 F2:AE repne scas byte ptr es:[edi]
1000104B F7D1 not ecx ; ecx 中保存Key值的长度
1000104D 49 dec ecx ; ecx = ecx - 1
1000104E 8D7C24 10 lea edi,dword ptr ss:[esp+0x10]
10001052 8BD1 mov edx,ecx ; edx = ecx
10001054 B9 07000000 mov ecx,0x7 ; ecx = 0x7
10001059 F3:AB rep stos dword ptr es:[edi] ; 清空 一块内存 存放数据 大小为 ecx * 4
1000105B 66:AB stos word ptr es:[edi] ; 清空一块内存 大小为4字节
1000105D 83FD 0F cmp ebp,0xF ; 用户名的长度必须在4到15位之间
10001060 AA stos byte ptr es:[edi] ; 清空一字节内存
10001061 0F8F A1000000 jg pf1.10001108
10001067 83FD 04 cmp ebp,0x4
1000106A 0F8C 98000000 jl pf1.10001108
10001070 83FA 1E cmp edx,0x1E ; Key值的长度必须在4到30位之间
10001073 0F8F 8F000000 jg pf1.10001108
10001079 83FA 04 cmp edx,0x4
1000107C 0F8C 86000000 jl pf1.10001108
10001082 33C9 xor ecx,ecx ; ecx = 0
10001084 85ED test ebp,ebp ; 用户名长度不能为 0
10001086 76 26 jbe Xpf1.100010AE
10001088 8D7424 11 lea esi,dword ptr ss:[esp+0x11] ; esi 指向刚才新初始化的一块内存
1000108C 0FBE0419 movsx eax,byte ptr ds:[ecx+ebx] ; eax 中存放用户名的第一位
10001090 99 cdq
10001091 BF 62000000 mov edi,0x62 ; edi = 0x62
10001096 83C6 02 add esi,0x2 ; esi = esi + 2
10001099 F7FF idiv edi ; eax / edi 商保存到 eax中 余数保存到 edx 中
1000109B 41 inc ecx
1000109C 3BCD cmp ecx,ebp ; 循环 的判断条件
1000109E 8A4414 30 mov al,byte ptr ss:[esp+edx+0x30] ; 在初始化字符串中按照余数搜索出指定的字符 保存到 al中
100010A2 8A5414 31 mov dl,byte ptr ss:[esp+edx+0x31] ; 搜索出上面字符所在位置的下一个位置字符 保存到 dl中
100010A6 8846 FD mov byte ptr ds:[esi-0x3],al ; 保存数据到数组
100010A9 8856 FE mov byte ptr ds:[esi-0x2],dl ; 保存数据到数组
100010AC ^ 72 DE jb Xpf1.1000108C
100010AE 8BB424 9C000000 mov esi,dword ptr ss:[esp+0x9C] ; esi指向了Key值
100010B5 C64424 2E 00 mov byte ptr ss:[esp+0x2E],0x0
100010BA 8D4424 10 lea eax,dword ptr ss:[esp+0x10] ; eax 指向了 新生成的数组中的数据
100010BE 8A10 mov dl,byte ptr ds:[eax] ; 新生成的数据和Key值按位比较
100010C0 8A1E mov bl,byte ptr ds:[esi]
100010C2 8ACA mov cl,dl ; cl = dl 新数组数据的第一位
100010C4 3AD3 cmp dl,bl
100010C6 75 1E jnz Xpf1.100010E6
100010C8 84C9 test cl,cl ; 判断是否为结束符
100010CA 74 16 je Xpf1.100010E2
100010CC 8A50 01 mov dl,byte ptr ds:[eax+0x1] ; 新数组数据的第二位
100010CF 8A5E 01 mov bl,byte ptr ds:[esi+0x1] ; Key值的第二位
100010D2 8ACA mov cl,dl
100010D4 3AD3 cmp dl,bl
100010D6 75 0E jnz Xpf1.100010E6
100010D8 83C0 02 add eax,0x2 ; eax = eax + 2
100010DB 83C6 02 add esi,0x2 ; esi = esi + 2
100010DE 84C9 test cl,cl
100010E0 ^ 75 DC jnz Xpf1.100010BE
100010E2 33C0 xor eax,eax
100010E4 EB 05 jmp Xpf1.100010EB
100010E6 1BC0 sbb eax,eax
100010E8 83D8 FF sbb eax,-0x1
100010EB 85C0 test eax,eax
100010ED 75 19 jnz Xpf1.10001108
100010EF 50 push eax
100010F0 8B8424 A4000000 mov eax,dword ptr ss:[esp+0xA4]
100010F7 68 4C500010 push pf1.1000504C ; Crackme
100010FC 68 30500010 push pf1.10005030 ; Registration successful !
10001101 50 push eax
10001102 FF15 B0400010 call dword ptr ds:[<&USER32.MessageBoxA>] ; user32.MessageBoxA
10001108 5F pop edi
10001109 5E pop esi
1000110A 5D pop ebp
1000110B 5B pop ebx
1000110C 81C4 84000000 add esp,0x84
10001112 C3 retn
}
004010C0 |. 83C4 0C add esp,0xC
004010C3 |> C705 506C4000>mov dword ptr ds:[0x406C50],0x0
004010CD \> C3 retn
2 算法注册机的实现
// CrackMe4.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
/***
* riijj_crackme.exe 程序注册机
* 完成时间: 2014年9月2日 1:40
* 完成人 : Night
*/
int _tmain(int argc, _TCHAR* argv[])
{
//存放用户名
char userName[100]={0};
//初始化字符串
char ch[100]="ytugjhkuijonlbpvqmcnxbvzdaeqrwtryetdgfkgphonuivmdbxfanqydexzwztqnkcfkvcpvlbmhotyiufdkdnjxuzyqhfstae";
//存放商
unsigned int quotient = 0;
//存放余数
unsigned int mod = 0;
//存放结果
char result [100] = {0};
//循环变量
int k = 0;
printf("请输入用户名:");
gets_s(userName);
if (strlen(userName)>15 || strlen(userName) < 4)
{
printf("用户名必须是4到15位");
return 1;
}
for (int i = 0; i < strlen(userName); i++)
{
mod = userName[i] % 0x62;
quotient = userName[i] / 0x62;
result[k++] = ch[mod-0x1];
result[k++] = ch[mod];
}
printf("\n注册码为:");
for (int i = 0; i < strlen(result); i++)
{
printf("%c",result[i]);
}
printf("\n");
return 0;
}
PS: VS2012 编译 , 这个CrackMe 存在反调试功能,主要就是检测OD。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!