KeyMe2 是在crackmes.de上找到的一个CrackMe,没有加过壳。这个CrackMe的破解难度不大,但各种判断比较多,有些语句末尾以“//”起
始的说明文字,是我添加的注释。
用OllyICE打开,F9运行,却自动退出,包括OllyICE也被关闭了。只好一步步进行,首先运行的是下面这段语句(1):
00401000 >/$/EB 0F jmp short 00401011
00401002 |. |4C 65 74 27 7> ascii "Let's start :)",0
00401011 |> \E8 02080000 call <jmp.&kernel32.GetCurrentProcess>; [GetCurrentProcessId
00401016 |. A3 D0324000 mov dword ptr [4032D0], eax
0040101B |. 6A 00 push 0 ; /ProcessID = 0
0040101D |. 6A 02 push 2 ; |Flags = TH32CS_SNAPPROCESS
0040101F |. E8 E8070000 call <jmp.&kernel32.CreateToolhelp32S>; \CreateToolhelp32Snapshot
00401024 |. 83F8 00 cmp eax, 0
00401027 |. 75 07 jnz short 00401030
00401029 |. 6A 00 push 0 ; /ExitCode = 0
0040102B |. E8 E2070000 call <jmp.&kernel32.ExitProcess> ; \ExitProcess
00401030 |> A3 D4324000 mov dword ptr [4032D4], eax
00401035 |. C705 D8324000> mov dword ptr [4032D8], 200
0040103F |. 68 D8324000 push 004032D8 ; /pProcessentry = 复件_Key.004032D8
00401044 |. FF35 D4324000 push dword ptr [4032D4] ; |hSnapshot = NULL
0040104A |. E8 FF070000 call <jmp.&kernel32.Process32First> ; \Process32First
0040104F |. 83F8 00 cmp eax, 0
00401052 |. 75 07 jnz short 0040105B
00401054 |. 6A 00 push 0 ; /ExitCode = 0
00401056 |. E8 B7070000 call <jmp.&kernel32.ExitProcess> ; \ExitProcess
0040105B |> A1 E0324000 mov eax, dword ptr [4032E0]
00401060 |. 3B05 D0324000 cmp eax, dword ptr [4032D0]
00401066 |. 74 35 je short 0040109D
00401068 |> 68 D8324000 /push 004032D8 ; /pProcessentry = 复件_Key.004032D8
0040106D |. FF35 D4324000 |push dword ptr [4032D4] ; |hSnapshot = NULL
00401073 |. E8 DC070000 |call <jmp.&kernel32.Process32Next> ; \Process32Next
00401078 |. 83F8 00 |cmp eax, 0
0040107B |. 75 11 |jnz short 0040108E
0040107D |. E8 A2070000 |call <jmp.&kernel32.GetLastError> ; [GetLastError
00401082 |. 83F8 0C |cmp eax, 0C
00401085 |. 74 07 |je short 0040108E
00401087 |. 6A 00 |push 0 ; /ExitCode = 0
00401089 |. E8 84070000 |call <jmp.&kernel32.ExitProcess> ; \ExitProcess
0040108E |> A1 E0324000 |mov eax, dword ptr [4032E0]
00401093 |. 3B05 D0324000 |cmp eax, dword ptr [4032D0]
00401099 |. 74 02 |je short 0040109D
0040109B |.^ EB CB \jmp short 00401068
0040109D |> FF35 D4324000 push dword ptr [4032D4] ; /hObject = NULL
004010A3 |. E8 58070000 call <jmp.&kernel32.CloseHandle> ; \CloseHandle
004010A8 |. A1 F0324000 mov eax, dword ptr [4032F0]
004010AD |. A3 E0344000 mov dword ptr [4034E0], eax
004010B2 |. 6A 00 push 0 ; /ProcessID = 0
004010B4 |. 6A 02 push 2 ; |Flags = TH32CS_SNAPPROCESS
004010B6 |. E8 51070000 call <jmp.&kernel32.CreateToolhelp32S> ; \CreateToolhelp32Snapshot
004010BB |. 83F8 00 cmp eax, 0
004010BE |. 75 07 jnz short 004010C7
004010C0 |. 6A 00 push 0 ; /ExitCode = 0
004010C2 |. E8 4B070000 call <jmp.&kernel32.ExitProcess> ; \ExitProcess
004010C7 |> A3 D4324000 mov dword ptr [4032D4], eax
004010CC |. C705 D8324000> mov dword ptr [4032D8], 200
004010D6 |. 68 D8324000 push 004032D8 ; /pProcessentry = 复件_Key.004032D8
004010DB |. FF35 D4324000 push dword ptr [4032D4] ; |hSnapshot = NULL
004010E1 |. E8 68070000 call <jmp.&kernel32.Process32First> ; \Process32First
004010E6 |. 83F8 00 cmp eax, 0
004010E9 |. 75 07 jnz short 004010F2
004010EB |. 6A 00 push 0 ; /ExitCode = 0
004010ED |. E8 20070000 call <jmp.&kernel32.ExitProcess> ; \ExitProcess
004010F2 |> A1 E0324000 mov eax, dword ptr [4032E0]
004010F7 |. 3B05 E0344000 cmp eax, dword ptr [4034E0]
004010FD |. 74 35 je short 00401134
004010FF |> 68 D8324000 /push 004032D8 ; /pProcessentry = 复件_Key.004032D8
00401104 |. FF35 D4324000 |push dword ptr [4032D4] ; |hSnapshot = NULL
0040110A |. E8 45070000 |call <jmp.&kernel32.Process32Next> ; \Process32Next
0040110F |. 83F8 00 |cmp eax, 0
00401112 |. 75 11 |jnz short 00401125
00401114 |. E8 0B070000 |call <jmp.&kernel32.GetLastError> ; [GetLastError
00401119 |. 83F8 0C |cmp eax, 0C
0040111C |. 74 07 |je short 00401125
0040111E |. 6A 00 |push 0 ; /ExitCode = 0
00401120 |. E8 ED060000 |call <jmp.&kernel32.ExitProcess> ; \ExitProcess
00401125 |> A1 E0324000 |mov eax, dword ptr [4032E0]
0040112A |. 3B05 E0344000 |cmp eax, dword ptr [4034E0]
00401130 |. 74 02 |je short 00401134
00401132 |.^ EB CB \jmp short 004010FF
00401134 |> FF35 D4324000 push dword ptr [4032D4] ; /hObject = NULL
0040113A |. E8 C1060000 call <jmp.&kernel32.CloseHandle> ; \CloseHandle
0040113F |. 8D05 FC324000 lea eax, dword ptr [4032FC]
00401145 |. 50 push eax ; /StringOrChar => ""
00401146 |. E8 79060000 call <jmp.&user32.CharLowerA> ; \CharLowerA
0040114B |. 813D FC324000> cmp dword ptr [4032FC], 6C707865
00401155 |. 75 23 jnz short 0040117A
00401157 |. 813D 00334000> cmp dword ptr [403300], 7265726F
00401161 |. 75 17 jnz short 0040117A
00401163 |. 813D 04334000> cmp dword ptr [403304], 6578652E
0040116D |. 75 0B jnz short 0040117A
0040116F |. 803D 08334000> cmp byte ptr [403308], 0
00401176 |. 75 02 jnz short 0040117A
00401178 |. EB 1A jmp short 00401194
0040117A |> FF35 E0344000 push dword ptr [4034E0] ; /ProcessId = 0
00401180 |. 6A 01 push 1 ; |Inheritable = TRUE
00401182 |. 68 FF0F1F00 push 1F0FFF ; |Access = PROCESS_ALL_ACCESS
00401187 |. E8 BC060000 call <jmp.&kernel32.OpenProcess> ; \OpenProcess
0040118C |. 6A 00 push 0 ; /ExitCode = 0
0040118E |. 50 push eax ; |hProcess
0040118F |. E8 CC060000 call <jmp.&kernel32.TerminateProcess> ; \TerminateProcess
00401194 |> 6A 00 push 0 ; /pModule = NULL
00401196 |. E8 95060000 call <jmp.&kernel32.GetModuleHandleA> ; \GetModuleHandleA
0040119B |. A3 4C324000 mov dword ptr [40324C], eax
004011A0 |. 6A 00 push 0 ; /lParam = NULL
004011A2 |. 68 BF114000 push 004011BF ; |DlgProc = 复件_Key.004011BF
004011A7 |. 6A 00 push 0 ; |hOwner = NULL
004011A9 |. 68 E9030000 push 3E9 ; |pTemplate = 3E9
004011AE |. FF35 4C324000 push dword ptr [40324C] ; |hInst = NULL
004011B4 |. E8 11060000 call <jmp.&user32.DialogBoxParamA> ; \DialogBoxParamA
004011B9 |. 50 push eax ; /ExitCode
004011BA \. E8 53060000 call <jmp.&kernel32.ExitProcess> ; \ExitProcess
单步跟踪后,会发现执行到下面这段语句,就会关闭OllyICE:
0040118C |. 6A 00 push 0 ; /ExitCode = 0
0040118E |. 50 push eax ; |hProcess
0040118F |. E8 CC060000 call <jmp.&kernel32.TerminateProcess> ; \TerminateProcess // 到这段语句就关闭OllyICE
而且是从下面这里跳转的:
0040114B |. 813D FC324000> cmp dword ptr [4032FC], 6C707865
00401155 |. 75 23 jnz short 0040117A
00401157 |. 813D 00334000> cmp dword ptr [403300], 7265726F
00401161 |. 75 17 jnz short 0040117A
00401163 |. 813D 04334000> cmp dword ptr [403304], 6578652E
0040116D |. 75 0B jnz short 0040117A
0040116F |. 803D 08334000> cmp byte ptr [403308], 0
00401176 |. 75 02 jnz short 0040117A // 本段各比较中,有一个不匹配,即跳转至关闭语句,退出OllyICE
其实,“6C707865”,“7265726F”及“6578652E”每个字节值转换成对应的字符,并各自逆序排列联接起来,就是“explorer.exe”。由
于我对上述大段语句(1)中调用的API函数不是十分了解,只简单推断了一下,语句段(1)中判断调用KeyMe2的进程是不是“explorer.exe”,
如果不是,则终止相应进程。因此,上述最后一段进行比较语句当中,所有“jnz short 0040117A”都改为用“NOP”填充,OllyICE就不会
再被关闭了。接下来就可以进行调试。
随便输入serial(下面为了叙述及说明方便,把serial看作字符串,则serial[0]表示所输入serial的第一位,serial[X]为所输入serial的
第X+1位。),点击“Check serial”后,出来的错误提示大多是“Serial format is incorrect! Try again.”,再查找所有参考文本字符
串,发现有很多同样的提示,首先可以看到的是下面这段语句(2):
004012F7 /$ 83F8 00 cmp eax, 0
004012FA |. 75 01 jnz short 004012FD
004012FC |. C3 retn
004012FD |> 33C0 xor eax, eax
004012FF |. 33DB xor ebx, ebx
00401301 |. 33C9 xor ecx, ecx
00401303 |. B8 04000000 mov eax, 4
00401308 |> 81B8 50324000> /cmp dword ptr [eax+403250], 3D6F6E2> // serial存放在以[403250]为起始地址的地方
00401312 |. 75 03 |jnz short 00401317 // “3D6F6E2”各字节值对应字符并逆序排列就是“.no=”
00401314 |. 43 |inc ebx
00401315 |. 8BC8 |mov ecx, eax // ecx储存的是serial中“.no=”起始的位置,设为X
00401317 |> 40 |inc eax
00401318 |. 83F8 09 |cmp eax, 9 // 4 <= eax < 9
0040131B |.^ 75 EB \jnz short 00401308
0040131D |. 83FB 01 cmp ebx, 1 // 本段判断,以serial[4]-[8]为起始位,serial中包含且仅包含一个“.no=”
00401320 |. 74 14 je short 00401336
00401322 |. 6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401324 |. 68 DE314000 push 004031DE ; |Title = "Input error"
00401329 |. 68 EA314000 push 004031EA ; |Text = "Serial format is incorrect! Try again."
0040132E |. 6A 00 push 0 ; |hOwner = NULL
00401330 |. E8 B9040000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00401335 |. C3 retn
00401336 |> E8 24000000 call 0040135F // 从这里起,调用若干函数来操作数据或判断serial的正确性
0040133B |. E8 74000000 call 004013B4
00401340 |. E8 D7000000 call 0040141C
00401345 |. E8 1D010000 call 00401467
0040134A |. E8 AD010000 call 004014FC
0040134F |. E8 E5010000 call 00401539
00401354 |. E8 F9010000 call 00401552
00401359 |. E8 45020000 call 004015A3
0040135E \. C3 retn
接下来看语句段(2)中所调用函数中的第一个,语句段(3):
0040135F /$ C781 50324000> mov dword ptr [ecx+403250], 0 // 操作类型是dword,所以输入的serial[X]-[X+3],即“.no=”
00401369 |. 33DB xor ebx, ebx // 对应的位置被置空,''
0040136B |. EB 24 jmp short 00401391
0040136D |. 47 6F 20 61 7> ascii "Go away!",0
00401376 |. 49 27 6D 20 6> ascii "I'm just",0
0040137F |. 63 68 61 6E 6> ascii "changing",0
00401388 |. 62 75 66 66 6> ascii "buffers.",0
00401391 |> 8B1D 50324000 mov ebx, dword ptr [403250]
00401397 |. 891D 80324000 mov dword ptr [403280], ebx
0040139D |. 8B1D 54324000 mov ebx, dword ptr [403254] // 四个mov语句,将serial[0]-[7]
004013A3 |. 891D 84324000 mov dword ptr [403284], ebx // 移入[403280]为起始地址的地方
004013A9 |. C781 80324000> mov dword ptr [ecx+403280], 0 // 将[403280+X]起始的地方置空,即[403280]为起始地址的地方
004013B3 \. C3 retn // 保存的是serial[0]-[X-1]
下面看语句段(4):
004013B4 /$ 80B9 5C324000> cmp byte ptr [ecx+40325C], 3A // 判断serial[12+X]是否为“:”(3A),不是则出错
004013BB |. 74 17 je short 004013D4
004013BD |. 6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013BF |. 68 DE314000 push 004031DE ; |Title = "Input error"
004013C4 |. 68 EA314000 push 004031EA ; |Text = "Serial format is incorrect! Try again."
004013C9 |. 6A 00 push 0 ; |hOwner = NULL
004013CB |. E8 1E040000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
004013D0 |. 83C4 04 add esp, 4
004013D3 |. C3 retn
004013D4 |> 80B9 65324000> cmp byte ptr [ecx+403265], 3A // 判断serial[21+X]是否为“:”(3A),不是则出错
004013DB |. 74 17 je short 004013F4
004013DD |. 6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013DF |. 68 DE314000 push 004031DE ; |Title = "Input error"
004013E4 |. 68 EA314000 push 004031EA ; |Text = "Serial format is incorrect! Try again."
004013E9 |. 6A 00 push 0 ; |hOwner = NULL
004013EB |. E8 FE030000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
004013F0 |. 83C4 04 add esp, 4
004013F3 |. C3 retn
004013F4 |> 80B9 6E324000> cmp byte ptr [ecx+40326E], 0 // 判断serial[30+X]是否为空(0),不是则出错
004013FB |. 74 17 je short 00401414
004013FD |. 6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013FF |. 68 DE314000 push 004031DE ; |Title = "Input error"
00401404 |. 68 EA314000 push 004031EA ; |Text = "Serial format is incorrect! Try again."
00401409 |. 6A 00 push 0 ; |hOwner = NULL
0040140B |. E8 DE030000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00401410 |. 83C4 04 add esp, 4
00401413 |. C3 retn
00401414 |> C681 6E324000> mov byte ptr [ecx+40326E], 0
0040141B \. C3 retn
语句段(4)说明了serial对格式的一些要求,以及其长度最长为X+30,即在第二个“:”后的长度最多为8位(serial[22+X]-[29+X])。通过
后面的语句还可以看到,其实应该是正好8位。注意,serial[0]-[X-1]即“.no=”之前的部分,serial[X+4]-[X+11],是在“.no=”和
“:”之间的部分,serial[X+13]-[X+20]为两个“:”之间的部分,而serial[22+X]-[29+X]则是最后的部分。
下面是语句段(5),没有什么特别的,主要是注意到serial[X+4]-[X+11]及serial[X+13]-[X+20]被移入了以[403290]为起始地址的地方,而
serial[X+22]-[X+29]被移入了以[4032A0]为起始地址的地方。
0040141C /$ 33DB xor ebx, ebx
0040141E |. 8B99 54324000 mov ebx, dword ptr [ecx+403254]
00401424 |. 891D 90324000 mov dword ptr [403290], ebx
0040142A |. 8B99 58324000 mov ebx, dword ptr [ecx+403258]
00401430 |. 891D 94324000 mov dword ptr [403294], ebx
00401436 |. 8B99 5D324000 mov ebx, dword ptr [ecx+40325D]
0040143C |. 891D 98324000 mov dword ptr [403298], ebx
00401442 |. 8B99 61324000 mov ebx, dword ptr [ecx+403261]
00401448 |. 891D 9C324000 mov dword ptr [40329C], ebx
0040144E |. 8B99 66324000 mov ebx, dword ptr [ecx+403266]
00401454 |. 891D A0324000 mov dword ptr [4032A0], ebx
0040145A |. 8B99 6A324000 mov ebx, dword ptr [ecx+40326A]
00401460 |. 891D A4324000 mov dword ptr [4032A4], ebx
00401466 \. C3 retn
语句段(6) ,就是将原来储存输入的serial的地方(以[403250]为起始地址)全部清空。
00401467 /$ EB 1A jmp short 00401483
00401469 |. 4E 6F 74 68 6> ascii "Nothing",0
00401471 |. 69 6E 74 65 7> ascii "interesting",0
0040147D |. 68 65 72 65 2> ascii "here.",0
00401483 |> C705 50324000> mov dword ptr [403250], 0
0040148D |. C705 54324000> mov dword ptr [403254], 0
00401497 |. C705 58324000> mov dword ptr [403258], 0
004014A1 |. C705 5C324000> mov dword ptr [40325C], 0
004014AB |. C705 60324000> mov dword ptr [403260], 0
004014B5 |. C705 64324000> mov dword ptr [403264], 0
004014BF |. C705 68324000> mov dword ptr [403268], 0
004014C9 |. C705 6C324000> mov dword ptr [40326C], 0
004014D3 |. C705 70324000> mov dword ptr [403270], 0
004014DD |. C705 74324000> mov dword ptr [403274], 0
004014E7 |. C705 78324000> mov dword ptr [403278], 0
004014F1 |. C705 7C324000> mov dword ptr [40327C], 0
004014FB \. C3 retn
下面是语句段(7),在语句段(3)中已经看到,以[00403280]起始,储存的就是serial[0]-[X-1]这个字符串,lstrlenA就是获得字符串的长度
X,然后的IsCharAlphaA循环进行判断,是否serial[0]-[X-1]每个都是字母,如果不是,则出错。
004014FC /$ 68 80324000 push 00403280 ; /String = ""
00401501 |. E8 6C030000 call <jmp.&kernel32.lstrlenA> ; \lstrlenA
00401506 |. 33DB xor ebx, ebx
00401508 |. 33C9 xor ecx, ecx
0040150A |. 8BD8 mov ebx, eax
0040150C |> 0FB68B 7F3240> /movzx ecx, byte ptr [ebx+40327F]
00401513 |. 51 |push ecx ; /Char
00401514 |. E8 C9020000 |call <jmp.&user32.IsCharAlphaA> ; \IsCharAlphaA
00401519 |. 83F8 00 |cmp eax, 0
0040151C |. 75 17 |jnz short 00401535
0040151E |. 6A 30 |push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401520 |. 68 DE314000 |push 004031DE ; |Title = "Input error"
00401525 |. 68 EA314000 |push 004031EA ; |Text = "Serial format is incorrect! Try again."
0040152A |. 6A 00 |push 0 ; |hOwner = NULL
0040152C |. E8 BD020000 |call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00401531 |. 83C4 04 |add esp, 4
00401534 |. C3 |retn
00401535 |> 4B |dec ebx
00401536 |.^ 75 D4 \jnz short 0040150C
00401538 \. C3 retn
语句段(8),没有什么特别的,就是调用GetLogicalDrives和GetVersion,返回值分别保存在以[4032B0]和[4032B4]起始的地方。
00401539 /$ E8 EC020000 call <jmp.&kernel32.GetLogicalDrives> ; [GetLogicalDrives
0040153E |. A3 B0324000 mov dword ptr [4032B0], eax
00401543 |. 33C0 xor eax, eax
00401545 |. E8 F2020000 call <jmp.&kernel32.GetVersion>
0040154A |. A3 B4324000 mov dword ptr [4032B4], eax
0040154F |. 33C0 xor eax, eax
00401551 \. C3 retn
语句段(9),两个嵌套循环,分别将GetLogicalDrives和GetVersion的值与serial[0]-[X-1]及serial[X+4]-[X+11]、serial[X+13]-[X+20]进
行异或和移位运算,并存储在以[4032B0]开始的地址中。
00401552 /$ 33C0 xor eax, eax
00401554 |. 33DB xor ebx, ebx
00401556 |. 33C9 xor ecx, ecx
00401558 |> 0FB683 803240> /movzx eax, byte ptr [ebx+403280]
0040155F |. 83F8 00 |cmp eax, 0
00401562 |. 74 17 |je short 0040157B
00401564 |> 3081 B0324000 |/xor byte ptr [ecx+4032B0], al
0040156A |. 41 ||inc ecx
0040156B |. D289 B0324000 ||ror byte ptr [ecx+4032B0], cl
00401571 |. 83F9 08 ||cmp ecx, 8
00401574 |.^ 75 EE |\jnz short 00401564
00401576 |. 33C9 |xor ecx, ecx
00401578 |. 43 |inc ebx
00401579 |.^ EB DD \jmp short 00401558
0040157B |> 33C0 xor eax, eax
0040157D |. 33DB xor ebx, ebx
0040157F |. 33C9 xor ecx, ecx
00401581 |> 0FB683 903240> /movzx eax, byte ptr [ebx+403290]
00401588 |> 3081 B0324000 |xor byte ptr [ecx+4032B0], al
0040158E |. 41 |inc ecx
0040158F |. D289 B0324000 |ror byte ptr [ecx+4032B0], cl
00401595 |. 83F9 08 |cmp ecx, 8
00401598 |.^ 75 EE |jnz short 00401588
0040159A |. 33C9 |xor ecx, ecx
0040159C |. 43 |inc ebx
0040159D |. 83FB 10 |cmp ebx, 10
004015A0 |.^ 75 DF \jnz short 00401581
004015A2 \. C3 retn
语句段(10),最后的判断。将(9)中运算的值,再分为两个dword值相加后,存入eax。调用msvcrt.dll中的sprintf函数,将eax中的值以十六
进制形式转换为字符串(比如dword值3CDED7CD即转为字符串"3CDED7CD"),存入[004032C0]。将这个字符串与serial在第二个“:”后面的
部分对比,即与serial[X+22]-[X+29]比较,如果相等,则判断serial为正确。
004015A3 /$ A1 B0324000 mov eax, dword ptr [4032B0]
004015A8 |. 0305 B4324000 add eax, dword ptr [4032B4]
004015AE |. 50 push eax
004015AF |. 68 22324000 push 00403222 ; /ProcNameOrOrdinal = "sprintf"
004015B4 |. 68 17324000 push 00403217 ; |/FileName = "msvcrt.dll"
004015B9 |. E8 84020000 call <jmp.&kernel32.LoadLibraryA> ; |\LoadLibraryA
004015BE |. 50 push eax ; |hModule
004015BF |. E8 72020000 call <jmp.&kernel32.GetProcAddress> ; \GetProcAddress
004015C4 |. 68 11324000 push 00403211 ; ASCII "%.8X"
004015C9 |. 68 C0324000 push 004032C0
004015CE |. FFD0 call eax
004015D0 |. 83C4 0C add esp, 0C
004015D3 |. 8D05 A0324000 lea eax, dword ptr [4032A0] // serial最后部分,即serial[X+22]-[X+29]
004015D9 |. 50 push eax ; /String2 => "" // serial[X+22]-[X+29]
004015DA |. 68 C0324000 push 004032C0 ; |String1 = "" // serial[X+22]-[X+29]的正确值
004015DF |. E8 88020000 call <jmp.&kernel32.lstrcmpA> ; \lstrcmpA
004015E4 |. 83F8 00 cmp eax, 0
004015E7 |. 74 14 je short 004015FD
004015E9 |. 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004015EB |. 68 A0314000 push 004031A0 ; |Title = "Serial not valid"
004015F0 |. 68 B1314000 push 004031B1 ; |Text = "Serial number is not valid for this machine!"
004015F5 |. 6A 00 push 0 ; |hOwner = NULL
004015F7 |. E8 F2010000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
004015FC |. C3 retn
004015FD |> 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004015FF |. 68 5C314000 push 0040315C ; |Title = "Registered!"
00401604 |. 68 68314000 push 00403168 ; |Text = "Serial number is accepted! Now write small tutorial :)!"
00401609 |. 6A 00 push 0 ; |hOwner = NULL
0040160B |. E8 DE010000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00401610 \. C3 retn
本来应该写出注册机,但是因为X值是不固定的,而且serial[0]-[X]、serial[X+4]-[X+11]和serial[X+13]-[X+20]都不确定,要根据给出的
值来计算最后的serial[X+22]-[X+29],实在有点儿麻烦,就不写了。另外,这篇破文好长,恐怕难免有我没有考虑周到或说清楚的地方,请
大家见谅并指正。
谢谢!
(附:
KeyMe2)
曹华 2007年8月22日
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课