我并不是大神,所以哪里写的不对,还请各位大佬们指出来。
0x0 分析算法
OD载入,搜索字符串,发现关键函数0x004013C0,给这个函数下断点,然后随便输入一串注册码,程序成功断下。
首先,程序将字符串"ABCDEFGHIJKLMNOPQRSTUVWXYZ"拷贝到一个新的地址处
00401421 B9 06000000 mov ecx, 0x6
00401426 BE 4C304000 mov esi, 0040304C ; ABCDEFGHIJKLMNOPQRSTUVWXYZ
0040142B 8D7C24 24 lea edi, dword ptr [esp+0x24]
0040142F 8D4424 14 lea eax, dword ptr [esp+0x14]
00401433 F3:A5 rep movs dword ptr es:[edi], dword ptr [esi]
00401435 66:A5 movs word ptr es:[edi], word ptr [esi]
然后取出Code和Serial
00401437 50 push eax
00401438 68 EA030000 push 0x3EA
0040143D 8BCD mov ecx, ebp
0040143F C64424 50 04 mov byte ptr [esp+0x50], 0x4
00401444 A4 movs byte ptr es:[edi], byte ptr [esi]
00401445 E8 0A030000 call <jmp.&MFC42.#3097> ; 取出Code
0040144A 8D4C24 10 lea ecx, dword ptr [esp+0x10]
0040144E 51 push ecx
0040144F 68 E9030000 push 0x3E9
00401454 8BCD mov ecx, ebp
00401456 E8 F9020000 call <jmp.&MFC42.#3097> ; 取出Serial
然后用sscanf函数将Serial转换成整数
0040145B 8B4424 10 mov eax, dword ptr [esp+0x10]
0040145F 8D5424 18 lea edx, dword ptr [esp+0x18]
00401463 52 push edx ; Serial的整数形式
00401464 68 48304000 push 00403048 ; %d
00401469 50 push eax ; Serial
0040146A FF15 84214000 call dword ptr [<&MSVCRT.sscanf>] ; msvcrt.sscanf
然后程序用srand函数设置一个随机数种子,种子值就是Serial的整数形式。
00401470 8B4C24 24 mov ecx, dword ptr [esp+0x24] ; Serial的整数形式
00401474 51 push ecx ; Serial的整数形式
00401475 FF15 B0214000 call dword ptr [<&MSVCRT.srand>] ; msvcrt.srand
然后调用rand函数,将rand函数返回的随机数除以0x1A,用余数取出"ABCDEFGHIJKLMNOPQRSTUVWXYZ"中的一个字符,一共进行12次。
0040147B 8B3D B8214000 mov edi, dword ptr [<&MSVCRT.rand>] ; msvcrt.rand
00401481 83C4 10 add esp, 0x10
00401484 BE 0C000000 mov esi, 0xC
00401489 FFD7 call edi
0040148B 99 cdq
0040148C B9 1A000000 mov ecx, 0x1A
00401491 F7F9 idiv ecx
00401493 8D4C24 0C lea ecx, dword ptr [esp+0xC]
00401497 8A5414 24 mov dl, byte ptr [esp+edx+0x24]
0040149B 52 push edx
0040149C E8 AD020000 call <jmp.&MFC42.#940> ; 转换成字符串
004014A1 4E dec esi
004014A2 ^ 75 E5 jnz short 00401489
其中,Code所对应的每个余数如下:
int DATA[] = {0x13,0x12,0x12,0x5,0x13,0xC,0x4,0x19,0x3,0xF,0xA,0x12};
最后将转换成的字符串和Code比较,如果相等就成功,否则失败。
004014A4 8B4424 14 mov eax, dword ptr [esp+0x14]
004014A8 8B4C24 0C mov ecx, dword ptr [esp+0xC]
004014AC 50 push eax ; Code
004014AD 51 push ecx
004014AE FF15 BC214000 call dword ptr [<&MSVCRT._mbscmp>] ; msvcrt._mbscmp
004014B4 83C4 08 add esp, 0x8
004014B7 85C0 test eax, eax
004014B9 75 12 jnz short 004014CD ; 失败则转移
0x1 计算注册码
首先看一下srand函数是如何实现的:
函数取出保存随机数种子的地址,然后将参数1(即种子值)保存进去。
7404CAB0 > 8BFF mov edi, edi
7404CAB2 55 push ebp
7404CAB3 8BEC mov ebp, esp
7404CAB5 E8 AAA20000 call 74056D64
7404CABA 8B4D 08 mov ecx, dword ptr [ebp+0x8] ; 取出种子值
7404CABD 8948 14 mov dword ptr [eax+0x14], ecx ; 保存种子值
7404CAC0 5D pop ebp
7404CAC1 C3 retn
然后再看一下rand函数是如何实现的:
函数首先取出保存随机数种子的地址,然后取出种子值,进行如下运算:
Seed = Seed * 0x343FD + 0x269EC3
其中,Seed就是取出的种子值。
最后程序将Seed进行如下运算,返回结果,这个结果就是随机数。
Seed >> 0x10 & 0x7FFF
在程序中的代码如下:
7404CA80 > E8 DFA20000 call 74056D64
7404CA85 6948 14 FD43030>imul ecx, dword ptr [eax+0x14], 0x343FD
7404CA8C 81C1 C39E2600 add ecx, 0x269EC3
7404CA92 8948 14 mov dword ptr [eax+0x14], ecx
7404CA95 C1E9 10 shr ecx, 0x10
7404CA98 81E1 FF7F0000 and ecx, 0x7FFF
7404CA9E 8BC1 mov eax, ecx
7404CAA0 C3 retn
因为程序中有进行模运算(即取余数),因此无法逆向,考虑枚举。
枚举代码如下:
运行结果如图所示:
放到CM中测试一下,可以通过。
全文完。