【文章标题】: 看雪CTF 2016 第一题分析
【文章作者】: xietao
【下载地址】: 自己搜索下载
【使用工具】: OllyDBG v2.01
【操作平台】: Windows 10 专业版
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【备注】: 本贴内容已备份在附件txt中。
--------------------------------------------------------------------------------
【详细过程】
首先通过反复输入错误的注册码可以得出以下几个结论:
1. 弹出的错误对话框来自于WM_COMMAND消息, 其中WPARAM参数一定为0x40F:
CPU Disasm
Address Hex dump Command Comments
0084241C |> \6A 00 push 0 ; /Type = MB_OK|MB_DEFBUTTON1|MB_APPLMODAL,
0084241E |. 68 68DA8500 push offset 0085DA68 ; |Caption = "Failed"
00842423 |. 68 38DB8500 push offset 0085DB38 ; |Text = "something you lost!"
00842428 |. 6A 00 push 0 ; |hOwner = NULL
0084242A |. FF15 48818500 call dword ptr [<&USER32.Messag ; \USER32.MessageBoxW
00842430 |. E9 40030000 jmp 00842775
此时栈的情况:
CPU Stack
Address Value Comments
$ ==> |010FF670
$+4 \7519D2B3 ; RETURN to USER32.7519D2B3
$+8 /000505E4
$+C |00000111 ; WM_COMMAND消息
$+10 |0000040F ; WPARAM参数, 反复对比后发现40F对应于错误提示
$+14 |00000000
$+18 |0000040F
2. 通过鼠标向下翻滚或字符串搜索可以很快定位到显示正确注册码对话框处, 可以知道注册成功时的WPARAM参数应该是0x40B:
CPU Disasm
Address Hex dump Command Comments
00842290 |> \8B4D 10 mov ecx, dword ptr [arg.3] ; Case 111 (WM_COMMAND) of switch Crack_Me.
00842293 |. 0FB7C1 movzx eax, cx ; 参数三为WPARAM参数
00842296 |. 3D 0A040000 cmp eax, 40A ; Switch (cases 68..40F, 8 exits)
0084229B |. 0F87 45010000 ja 008423E6
……
008423E6 |> \2D 0B040000 sub eax, 40B
008423EB |. 0F84 0D010000 jz 008424FE
……
008424FE |> \0F1005 98DB8500 movups xmm0, dqword ptr [85DB98] ; 如果WPARAM等于40B, 则显示注册成功对话框!, case 40B of s
00842505 |. 66:A1 C8DB8500 mov ax, word ptr [85DBC8]
0084250B |. 68 96000000 push 96 ; /Arg3 = 96
00842510 |. 0F1185 E4FEFFFF movups dqword ptr [local.71], xmm ; |
00842517 |. 66:8985 14FFFFFF mov word ptr [local.59], ax ; |
0084251E |. 8D85 16FFFFFF lea eax, [local.59+2] ; |
00842524 |. 0F1005 A8DB8500 movups xmm0, dqword ptr [85DBA8] ; |float 1.074492e-38, 8.908203e-39, 9.4592
0084252B |. 6A 00 push 0 ; |Arg2 = 0
0084252D |. 50 push eax ; |Arg1
0084252E |. 0F1185 F4FEFFFF movups dqword ptr [local.67], xmm ; |
00842535 |. 0F1005 B8DB8500 movups xmm0, dqword ptr [85DBB8] ; |float 3.030733e-39, 1.010206e-38, 9.6428
0084253C |. 0F1185 04FFFFFF movups dqword ptr [local.63], xmm ; |
00842543 |. E8 88140000 call 008439D0 ; \Crack_Me.008439D0
00842548 |. 83C4 0C add esp, 0C
0084254B |. 8D85 E4FEFFFF lea eax, [local.71]
00842551 |. 6A 00 push 0 ; /Type = MB_OK|MB_DEFBUTTON1|MB_APPLMODAL
00842553 |. 68 CCDB8500 push offset 0085DBCC ; |Caption = "Successed"
00842558 |. 50 push eax ; |Text => offset LOCAL.71
00842559 |. 53 push ebx ; |hOwner => [ARG.1]
0084255A |. FF15 48818500 call dword ptr [<&USER32.Messag ; \USER32.MessageBoxW
3. 点击OK对话框会创建一个线程, 然后主线程返回, 由子线程对比输入的注册码, 可以得到校验子线程线程入口为Crack_Me.008420E0.
CPU Disasm
Address Hex dump Command Comments
0084276B |> \6A 00 push 0 ; |StackSize = 0
0084276D |. 6A 00 push 0 ; |pSecurity = NULL
0084276F |. FF15 74808500 call dword ptr [<&KERNEL32.Crea ; \KERNEL32.CreateThread
00842775 |> 8B4D FC mov ecx, dword ptr [local.1] ; Case 68 of switch Crack_Me.842296
创建线程处栈的情况:
CPU Stack
Address Value Comments
$-3D4 [00842775 ; /RETURN from KERNEL32.CreateThread to Crack_Me.00842775
$-3D0 /00000000 ; |pSecurity = NULL
$-3CC |00000000 ; |StackSize = 0
$-3C8 |008420E0 ; |StartAddress = Crack_Me.8420E0 ; 线程入口地址
$-3C4 |038D3A00 ; |Parameter = 038D3A00 ; 线程参数
$-3C0 |00000000 ; |CreationFlags = 0
$-3BC |00000000 ; \pThreadId = NULL
4. 在主模块中查找所有SendMessageW函数的引用参考, 对比多个SendMessageW函数的WPARAM参数入栈传参均是由68指令完成(如下所示):
CPU Disasm
Address Hex dump Command Comments
00841D33 |> \6A 00 push 0 ; /hControl = NULL
00841D35 |. 68 0F040000 push 40F ; |wParam = (由上面分析得知,40F代表注册失败)
00841D3A |. 68 11010000 push 111 ; |Msg = WM_COMMAND
00841D3F |. FF77 04 push dword ptr [edi+4] ; |hWnd => [ARG.ECX+4]
00841D42 |. FF15 50818500 call dword ptr [<&USER32.SendMe ; \USER32.SendMessageW
所以我们可以对应的搜索push 40B指令, 应该是此处发出了注册成功的消息,很快我们就搜到了唯一一处(如下所示):
CPU Disasm
Address Hex dump Command Comments
00841870 $ 55 push ebp ; 此函数尾部发送注册成功或失败的消息(重要)
00841871 . 8BEC mov ebp, esp ; 要想注册成功必调用了此函数
00841873 . 83EC 54 sub esp, 54
00841876 . A1 14F08500 mov eax, dword ptr [85F014]
0084187B . 33C5 xor eax, ebp
0084187D . 8945 FC mov dword ptr [ebp-4], eax
……
00841A32 |. 68 0B040000 push 40B ; 此处PUSH了代表注册成功的40B(也是唯一一处)
00841A37 |. EB 07 jmp short 00841A40
00841A39 |> 6A 00 push 0
00841A3B |> 68 0A040000 push 40A ; 此处PUSH了代表注册失败的40A
00841A40 |> 68 11010000 push 111 ; |Msg = WM_COMMAND
00841A45 |. FF73 04 push dword ptr [ebx+4] ; |hWnd
00841A48 |. FF15 54818500 call dword ptr [<&USER32.PostMe ; \USER32.PostMessageW
5. 通过第4步我们找到了一个00841870的重要函数,然后Ctrl+F查找call 00841870指令, 我们能找到唯一一处结果(如下所示):
CPU Disasm
Address Hex dump Command Comments
00841A60 /$ 55 push ebp ; 判断了注册码, 并调用了最终显示结果的函数(重要)
00841A61 |. 8BEC mov ebp, esp
00841A63 |. 81EC 9C010000 sub esp, 19C
00841A69 |. A1 14F08500 mov eax, dword ptr [85F014]
00841A6E |. 33C5 xor eax, ebp
00841A70 |. 8945 FC mov dword ptr [local.1], eax
……
00841BCA |> \53 push ebx ; /Arg1 => ARG.EDX
00841BCB |. E8 0F110000 call 00842CDF ; \Crack_Me.0084C93D
00841BD0 |. 8B8D 68FEFFFF mov ecx, dword ptr [local.102]
00841BD6 |. 83C4 04 add esp, 4
00841BD9 |. 8BD6 mov edx, esi
00841BDB |. E8 90FCFFFF call 00841870 ; <<==调用了00841870的重要函数
00841BE0 |. 8B4D FC mov ecx, dword ptr [local.1]
00841BE3 |. 5F pop edi
00841BE4 |. 5E pop esi
我们向上翻滚到该函数的函数头00841A60处, 重复上一步骤, 继续搜索call 00841A60, 几番循环我们便来到了步骤3种找到的那个检测注册码线程的入口函数处(如下所示):
CPU Disasm
Address Hex dump Command Comments
008420E0 /. 55 push ebp ; 检测注册码线程入口函数
008420E1 |. 8BEC mov ebp, esp
008420E3 |. 8B4D 08 mov ecx, dword ptr [arg.1]
008420E6 |. 33D2 xor edx, edx
008420E8 |. E8 C3FBFFFF call 00841CB0 ; <<==判断注册码
008420ED |. 6A 14 push 14
008420EF |. FF75 08 push dword ptr [arg.1]
008420F2 |. E8 ED0B0000 call 00842CE4 ; 释放内存
008420F7 |. 83C4 08 add esp, 8
008420FA |. 33C0 xor eax, eax
008420FC |. 5D pop ebp
008420FD \. C2 0400 ret 4
到此处我们便从注册成功处(分析之旅的终点)向回溯到了线程入口函数处(分析之旅的起点), 所以我们总结出了追溯正确注册码的逻辑流程图应该是:
=======================================================================================================================
以上图为基础开始分别分析三个注册函数代码中的重点之处:
一. 注册码判断函数1: 0x00841CB0
CPU Disasm
Address Hex dump Command Comments
00841CB0 /$ 55 push ebp ; 注册码判断函数1
00841CB1 |. 8BEC mov ebp, esp
00841CB3 |. 81EC D0000000 sub esp, 0D0
00841CB9 |. A1 14F08500 mov eax, dword ptr [85F014]
00841CBE |. 33C5 xor eax, ebp
00841CC0 |. 8945 FC mov dword ptr [local.1], eax
00841CC3 |. 57 push edi
00841CC4 |. 8BF9 mov edi, ecx
00841CC6 |. 85FF test edi, edi
00841CC8 |. 0F84 61010000 jz 00841E2F
00841CCE |. 85D2 test edx, edx ; 线程入口调用时edx为0, 本函数递归调用时为1
00841CD0 |. 0F85 81000000 jnz 00841D57 ; 递归调用时跳转条件成立
00841CD6 |. E8 25FFFFFF call 00841C00 ; <<==判断输入的注册码中是否存在小写字母b
00841CDB |. 85C0 test eax, eax ; 不存在小写字母b则跳到发送注册失败处
00841CDD |. 74 54 jz short 00841D33
00841CDF |. 68 C8000000 push 0C8 ; /Arg3 = 0C8
00841CE4 |. 8D85 34FFFFFF lea eax, [local.51] ; |
00841CEA |. 6A 00 push 0 ; |Arg2 = 0
00841CEC |. 50 push eax ; |Arg1 => offset LOCAL.51
00841CED |. E8 DE1C0000 call memset ; \Crack_Me.memset
00841CF2 |. 83C4 0C add esp, 0C
00841CF5 |. 8D85 34FFFFFF lea eax, [local.51]
00841CFB |. 6A 64 push 64 ; /MaxCount = 100.
00841CFD |. 50 push eax ; |String => offset LOCAL.51
00841CFE |. FF77 0C push dword ptr [edi+0C] ; |hWnd => [ARG.ECX+0C]
00841D01 |. FF15 4C818500 call dword ptr [<&USER32.GetWind ; \USER32.GetWindowTextW
00841D07 |. 6A 70 push 70 ; /Arg1 = 70
00841D09 |. 8D95 34FFFFFF lea edx, [local.51] ; |
00841D0F |. E8 3C0D0000 call 00842A50 ; \Crack_Me.00842A50, <<==判断注册码中是否存在小写字母p
00841D14 |. 85C0 test eax, eax
00841D16 |. 74 1B jz short 00841D33
00841D18 |. BA 01000000 mov edx, 1 ; 成功分支, 参数二传入1, 然后递归调用本函数
00841D1D |. 8BCF mov ecx, edi
00841D1F |. E8 8CFFFFFF call 00841CB0
00841D24 |. 5F pop edi
00841D25 |. 8B4D FC mov ecx, dword ptr [local.1]
00841D28 |. 33CD xor ecx, ebp
00841D2A |. E8 960F0000 call 00842CC5
00841D2F |. 8BE5 mov esp, ebp
00841D31 |. 5D pop ebp
00841D32 |. C3 ret
00841D33 |> 6A 00 push 0 ; /hControl = NULL
00841D35 |. 68 0F040000 push 40F ; |wParam = NotifyCode = MENU/BN_CLICKED..., ID = 10
00841D3A |. 68 11010000 push 111 ; |Msg = WM_COMMAND
00841D3F |. FF77 04 push dword ptr [edi+4] ; |hWnd => [ARG.ECX+4]
00841D42 |. FF15 50818500 call dword ptr [<&USER32.SendMes ; \USER32.SendMessageW
00841D48 |. 5F pop edi
00841D49 |. 8B4D FC mov ecx, dword ptr [local.1]
00841D4C |. 33CD xor ecx, ebp
00841D4E |. E8 720F0000 call 00842CC5
00841D53 |. 8BE5 mov esp, ebp
00841D55 |. 5D pop ebp
00841D56 |. C3 ret
00841D57 |> 56 push esi
00841D58 |. E8 812B0000 call 008448DE ; [Crack_Me.008448DE, [反调试]读取时间
00841D5D |. 68 C8000000 push 0C8 ; /Arg3 = 0C8
00841D62 |. 8985 30FFFFFF mov dword ptr [local.52], eax ; |
00841D68 |. 8D85 34FFFFFF lea eax, [local.51] ; |
00841D6E |. 6A 00 push 0 ; |Arg2 = 0
00841D70 |. 50 push eax ; |Arg1 => offset LOCAL.51
00841D71 |. E8 5A1C0000 call memset ; \Crack_Me.memset
00841D76 |. 83C4 0C add esp, 0C
00841D79 |. 8D85 34FFFFFF lea eax, [local.51]
00841D7F |. 68 C8000000 push 0C8 ; /MaxCount = 200.
00841D84 |. 50 push eax ; |String => offset LOCAL.51
00841D85 |. FF77 0C push dword ptr [edi+0C] ; |hWnd => [ARG.ECX+0C]
00841D88 |. FF15 4C818500 call dword ptr [<&USER32.GetWind ; \USER32.GetWindowTextW
00841D8E |. 33F6 xor esi, esi
00841D90 |. 8D85 34FFFFFF lea eax, [local.51]
00841D96 |. 66:39B5 34FFFFFF cmp word ptr [local.51], si
00841D9D |. 74 0B je short 00841DAA
00841D9F |. 90 nop
00841DA0 |> 8D40 02 /lea eax, [eax+2]
00841DA3 |. 46 |inc esi
00841DA4 |. 66:8338 00 |cmp word ptr [eax], 0
00841DA8 |.^ 75 F6 \jne short 00841DA0
00841DAA |> 33C9 xor ecx, ecx
00841DAC |. 8D46 01 lea eax, [esi+1]
00841DAF |. BA 02000000 mov edx, 2
00841DB4 |. F7E2 mul edx
00841DB6 |. 53 push ebx
00841DB7 |. 0F90C1 seto cl
00841DBA |. F7D9 neg ecx
00841DBC |. 0BC8 or ecx, eax
00841DBE |. 51 push ecx ; /Arg1
00841DBF |. E8 120F0000 call 分配内存 ; \Crack_Me.分配内存
00841DC4 |. 83C4 04 add esp, 4
00841DC7 |. 8BD8 mov ebx, eax
00841DC9 |. E8 102B0000 call 008448DE ; [Crack_Me.008448DE, [反调试]再次读取时间
00841DCE |. 2B85 30FFFFFF sub eax, dword ptr [local.52]
00841DD4 |. 83F8 02 cmp eax, 2 ; [反调试]判断时间差
00841DD7 |. 7F 65 jg short 00841E3E ; 此处跳转代码nop掉
00841DD9 |. 8D85 34FFFFFF lea eax, [local.51]
00841DDF |. 50 push eax ; /Arg2 => offset LOCAL.51
00841DE0 |. 53 push ebx ; |Arg1
00841DE1 |. E8 8A0A0000 call 00842870 ; \Crack_Me.00842870, 将注册码复制到新申请的内存
00841DE6 |. 83FE 07 cmp esi, 7 ; 判断注册码长度是否为7, cascaded IF (cases 0..7, 3 exits)
00841DE9 |. 73 0B jae short 00841DF6
00841DEB |. 6A 00 push 0
00841DED |. 6A 00 push 0
00841DEF |. 68 0E040000 push 40E
00841DF4 |. EB 0B jmp short 00841E01
00841DF6 |> 76 2C jbe short 00841E24
00841DF8 |. 6A 00 push 0 ; Default case of cascaded IF Crack_Me.841DE6
00841DFA |. 6A 00 push 0
00841DFC |. 68 0D040000 push 40D
00841E01 |> FF77 04 push dword ptr [edi+4] ; |hWnd => [ARG.ECX+4], cases 0, 1, 2, 3, 4, 5, 6 of
00841E04 |. FF15 50818500 call dword ptr [<&USER32.SendMes ; \USER32.SendMessageW
00841E0A |. 53 push ebx ; /Arg1
00841E0B |. E8 CF0E0000 call 00842CDF ; \Crack_Me.0084C93D
00841E10 |. 83C4 04 add esp, 4
00841E13 |. 5B pop ebx
00841E14 |. 5E pop esi
00841E15 |. 5F pop edi
00841E16 |. 8B4D FC mov ecx, dword ptr [local.1]
00841E19 |. 33CD xor ecx, ebp
00841E1B |. E8 A50E0000 call 00842CC5
00841E20 |. 8BE5 mov esp, ebp
00841E22 |. 5D pop ebp
00841E23 |. C3 ret
00841E24 |> 8BD3 mov edx, ebx ; 注册码长度等于7表示正确, 否则发送注册失败消息, case 7 of cascaded IF Cr
00841E26 |. 8BCF mov ecx, edi
00841E28 |. E8 33FCFFFF call 00841A60 ; <<==进入注册码判断函数2
00841E2D |. 5B pop ebx
00841E2E |. 5E pop esi
00841E2F |> 8B4D FC mov ecx, dword ptr [local.1]
00841E32 |. 33CD xor ecx, ebp
00841E34 |. 5F pop edi
00841E35 |. E8 8B0E0000 call 00842CC5
00841E3A |. 8BE5 mov esp, ebp
00841E3C |. 5D pop ebp
00841E3D |. C3 ret
二. 注册码判断函数2: 0x00841A60, 此函数没有对注册码进行判断, 只进行了干扰操作和注册码的简单加密.
CPU Disasm
Address Hex dump Command Comments
00841A60 /$ 55 push ebp ; 注册码判断函数2
00841A61 |. 8BEC mov ebp, esp
00841A63 |. 81EC 9C010000 sub esp, 19C
00841A69 |. A1 14F08500 mov eax, dword ptr [85F014]
00841A6E |. 33C5 xor eax, ebp
00841A70 |. 8945 FC mov dword ptr [local.1], eax
00841A73 |. 53 push ebx
00841A74 |. 56 push esi
00841A75 |. 57 push edi
……
00841B4C |> 8D41 01 lea eax, [ecx+1]
00841B4F |. BA 02000000 mov edx, 2
00841B54 |. 33C9 xor ecx, ecx
00841B56 |. F7E2 mul edx
00841B58 |. 0F90C1 seto cl
00841B5B |. F7D9 neg ecx
00841B5D |. 0BC8 or ecx, eax
00841B5F |. 51 push ecx ; /Arg1
00841B60 |. E8 71110000 call 分配内存 ; \Crack_Me.分配内存
00841B65 |. 8BF0 mov esi, eax
00841B67 |. 83C4 04 add esp, 4
00841B6A |. 33C0 xor eax, eax
00841B6C |. 66:3903 cmp word ptr [ebx], ax
00841B6F |. 74 16 je short 00841B87
00841B71 |. 0FB70B movzx ecx, word ptr [ebx]
00841B74 |. 33D2 xor edx, edx
00841B76 |> 40 /inc eax
00841B77 |. 66:890C32 |mov word ptr [esi+edx], cx ; 复制注册码到新申请的缓冲区
00841B7B |. 8D1400 |lea edx, [eax+eax]
00841B7E |. 0FB70C1A |movzx ecx, word ptr [ebx+edx]
00841B82 |. 66:85C9 |test cx, cx
00841B85 |.^ 75 EF \jnz short 00841B76
00841B87 |> 33C9 xor ecx, ecx
00841B89 |. 66:890C46 mov word ptr [eax*2+esi], cx
00841B8D |. 8BC6 mov eax, esi
00841B8F |. 85F6 test esi, esi
00841B91 |. 74 37 jz short 00841BCA
00841B93 |. 66:390E cmp word ptr [esi], cx
00841B96 |. 74 0A je short 00841BA2
00841B98 |> 8D40 02 /lea eax, [eax+2]
00841B9B |. 41 |inc ecx
00841B9C |. 66:8338 00 |cmp word ptr [eax], 0
00841BA0 |.^ 75 F6 \jne short 00841B98
00841BA2 |> 33C0 xor eax, eax
00841BA4 |. 85C9 test ecx, ecx
00841BA6 |. 74 22 jz short 00841BCA
00841BA8 |> 83F8 02 /cmp eax, 2
00841BAB |. 73 07 |jae short 00841BB4
00841BAD |. 66:833446 0F |xor word ptr [eax*2+esi], 000F
00841BB2 |. EB 11 |jmp short 00841BC5
00841BB4 |> 83F8 04 |cmp eax, 4
00841BB7 |. 73 07 |jae short 00841BC0
00841BB9 |. 66:833446 50 |xor word ptr [eax*2+esi], 0050
00841BBE |. EB 05 |jmp short 00841BC5
00841BC0 |> 66:833446 42 |xor word ptr [eax*2+esi], 0042
00841BC5 |> 40 |inc eax
00841BC6 |. 3BC1 |cmp eax, ecx
00841BC8 |.^ 72 DE \jb short 00841BA8 ; 此循环对字符串进行加密
00841BCA |> 53 push ebx ; /Arg1 => ARG.EDX
00841BCB |. E8 0F110000 call 释放内存 ; \Crack_Me.0084C93D, 释放内存
00841BD0 |. 8B8D 68FEFFFF mov ecx, dword ptr [local.102]
00841BD6 |. 83C4 04 add esp, 4
00841BD9 |. 8BD6 mov edx, esi
00841BDB |. E8 90FCFFFF call 00841870 ; <<==调用注册码判断函数3
00841BE0 |. 8B4D FC mov ecx, dword ptr [local.1]
00841BE3 |. 5F pop edi
00841BE4 |. 5E pop esi
00841BE5 |. 33CD xor ecx, ebp
00841BE7 |. 5B pop ebx
00841BE8 |. E8 D8100000 call 00842CC5
00841BED |. 8BE5 mov esp, ebp
00841BEF |. 5D pop ebp
00841BF0 \. C3 ret
三. 注册码判断函数3: 0x00841870, 在发送注册成功之前有一个重要的函数, 此函数的返回值直接影响到了注册的结果
CPU Disasm
Address Hex dump Command Comments
00841870 $ 55 push ebp ; 注册码判断函数3
00841871 . 8BEC mov ebp, esp
00841873 . 83EC 54 sub esp, 54
00841876 . A1 14F08500 mov eax, dword ptr [85F014]
0084187B . 33C5 xor eax, ebp
0084187D . 8945 FC mov dword ptr [ebp-4], eax
00841880 . 53 push ebx
00841881 . 56 push esi
00841882 . 57 push edi
00841883 . 6A 36 push 36 ; /Arg3 = 36
00841885 . 8D45 B0 lea eax, [ebp-50] ; |
00841888 . 8BD9 mov ebx, ecx ; |
0084188A . 6A 00 push 0 ; |Arg2 = 0
0084188C . 50 push eax ; |Arg1
0084188D . 8BFA mov edi, edx ; |
0084188F . 895D AC mov dword ptr [ebp-54], ebx ; |
00841892 . E8 39210000 call memset ; \Crack_Me.memset
00841897 . 83C4 0C add esp, 0C
0084189A . 8D4D E8 lea ecx, [ebp-18]
0084189D . B8 30000000 mov eax, 30
008418A2 > 66:8901 mov word ptr [ecx], ax
008418A5 . 8D49 02 lea ecx, [ecx+2]
008418A8 . 40 inc eax
008418A9 . 83F8 39 cmp eax, 39
008418AC .^ 7E F4 jle short 008418A2 ; 初始化字符串0-9
008418AE . B8 61000000 mov eax, 61
008418B3 . 8D4D B0 lea ecx, [ebp-50]
008418B6 > 66:8901 mov word ptr [ecx], ax
008418B9 . 8D49 02 lea ecx, [ecx+2]
008418BC . 40 inc eax
008418BD . 83F8 7A cmp eax, 7A
008418C0 .^ 7E F4 jle short 008418B6 ; 初始化字符串a-z
008418C2 . 33D2 xor edx, edx
008418C4 . 8D45 B0 lea eax, [ebp-50]
008418C7 . 66:3955 B0 cmp word ptr [ebp-50], dx
008418CB . 74 0D je short 008418DA
008418CD . 0F1F00 nop dword ptr [eax]
008418D0 > 8D40 02 lea eax, [eax+2]
008418D3 . 42 inc edx
008418D4 . 66:8338 00 cmp word ptr [eax], 0
008418D8 .^ 75 F6 jne short 008418D0
008418DA > 33C9 xor ecx, ecx
008418DC . 85D2 test edx, edx
008418DE . 74 1C je short 008418FC
008418E0 > 0FB7444D B0 movzx eax, word ptr [ecx*2+ebp-50]
008418E5 . 83F8 61 cmp eax, 61 ; Switch (cases 61..7A, 2 exits)
008418E8 . 72 0D jb short 008418F7
008418EA . 83F8 7A cmp eax, 7A
008418ED . 77 08 ja short 008418F7
008418EF . 83C0 E0 add eax, -20 ; Cases 61 ('a'), 62 ('b'), 63 ('c'), 64 ('d'), 65 (
008418F2 . 66:89444D B0 mov word ptr [ecx*2+ebp-50], ax
008418F7 > 41 inc ecx ; Default case of switch Crack_Me.8418E5
008418F8 . 3BCA cmp ecx, edx
008418FA .^ 72 E4 jb short 008418E0 ; 此循环将上面初始化的字符串进行小写转大写操作
008418FC > 33C9 xor ecx, ecx
008418FE . 8BC7 mov eax, edi
00841900 . 85FF test edi, edi ; 取出已加密的注册码
00841902 . 74 76 je short 0084197A
00841904 . 66:390F cmp word ptr [edi], cx
00841907 . 74 11 je short 0084191A
00841909 . 0F1F80 00000000 nop dword ptr [eax]
00841910 > 8D40 02 lea eax, [eax+2]
00841913 . 41 inc ecx
00841914 . 66:8338 00 cmp word ptr [eax], 0
00841918 .^ 75 F6 jne short 00841910
0084191A > 33C0 xor eax, eax
0084191C . 85C9 test ecx, ecx
0084191E . 74 22 je short 00841942
00841920 > 83F8 02 cmp eax, 2
00841923 . 73 07 jae short 0084192C
00841925 . 66:833447 0F xor word ptr [eax*2+edi], 000F
0084192A . EB 11 jmp short 0084193D
0084192C > 83F8 04 cmp eax, 4
0084192F . 73 07 jae short 00841938
00841931 . 66:833447 50 xor word ptr [eax*2+edi], 0050
00841936 . EB 05 jmp short 0084193D
00841938 > 66:833447 42 xor word ptr [eax*2+edi], 0042
0084193D > 40 inc eax
0084193E . 3BC1 cmp eax, ecx
00841940 .^ 72 DE jb short 00841920 ; 对已加密的注册码进行解密操作
00841942 > 33D2 xor edx, edx
00841944 . 8BC7 mov eax, edi
00841946 . 66:3917 cmp word ptr [edi], dx
00841949 . 74 0F je short 0084195A
0084194B 0F1F4400 00 nop dword ptr [eax+eax]
00841950 > 8D40 02 lea eax, [eax+2]
00841953 . 42 inc edx
00841954 . 66:8338 00 cmp word ptr [eax], 0
00841958 .^ 75 F6 jne short 00841950
0084195A > 33C9 xor ecx, ecx
0084195C . 85D2 test edx, edx
0084195E . 74 1A je short 0084197A
00841960 > 0FB7044F movzx eax, word ptr [ecx*2+edi]
00841964 . 83F8 61 cmp eax, 61 ; Switch (cases 61..7A, 2 exits)
00841967 . 72 0C jb short 00841975
00841969 . 83F8 7A cmp eax, 7A
0084196C . 77 07 ja short 00841975
0084196E . 83C0 E0 add eax, -20 ; Cases 61 ('a'), 62 ('b'), 63 ('c'), 64 ('d'), 65 (
00841971 . 66:89044F mov word ptr [ecx*2+edi], ax
00841975 > 41 inc ecx ; Default case of switch Crack_Me.841964
00841976 . 3BCA cmp ecx, edx
00841978 .^ 72 E6 jb short 00841960 ; 对注册码中的字母进行小写转大写操作
0084197A > 33F6 xor esi, esi
0084197C . 0F57C0 xorps xmm0, xmm0
0084197F . 660FD645 F0 movq qword ptr [ebp-10], xmm0
00841984 . 66:8975 F8 mov word ptr [ebp-8], si
00841988 . 66:3937 cmp word ptr [edi], si
0084198B . 74 48 je short 008419D5
0084198D . 66:8B4D B0 mov cx, word ptr [ebp-50]
00841991 . 8D5D F0 lea ebx, [ebp-10]
00841994 . 8BC7 mov eax, edi
00841996 > 66:85C9 test cx, cx
00841999 . 74 2C je short 008419C7
0084199B . 0FB710 movzx edx, word ptr [eax]
0084199E . 8D4D B0 lea ecx, [ebp-50]
008419A1 . 33C0 xor eax, eax
008419A3 > 66:3B11 cmp dx, word ptr [ecx]
008419A6 . 74 10 je short 008419B8
008419A8 . 40 inc eax
008419A9 . 8D4D B0 lea ecx, [ebp-50]
008419AC . 66:833C41 00 cmp word ptr [eax*2+ecx], 0
008419B1 . 8D0C41 lea ecx, [eax*2+ecx]
008419B4 .^ 75 ED jne short 008419A3
008419B6 . EB 0B jmp short 008419C3
008419B8 > 66:8B4445 B0 mov ax, word ptr [eax*2+ebp-50]
008419BD . 66:8903 mov word ptr [ebx], ax
008419C0 . 83C3 02 add ebx, 2
008419C3 > 66:8B4D B0 mov cx, word ptr [ebp-50]
008419C7 > 46 inc esi
008419C8 . 66:833C77 00 cmp word ptr [esi*2+edi], 0
008419CD . 8D0477 lea eax, [esi*2+edi]
008419D0 .^ 75 C4 jne short 00841996 ; 此循环取出注册码中的字母部分
008419D2 . 8B5D AC mov ebx, dword ptr [ebp-54]
008419D5 > 33C9 xor ecx, ecx
008419D7 . 8D45 F0 lea eax, [ebp-10]
008419DA . 66:394D F0 cmp word ptr [ebp-10], cx ; 判断注册码中是否存在字母
008419DE . 74 59 je short 00841A39 ; 注册码中不存在字母则发送注册失败消息
008419E0 > 8D40 02 lea eax, [eax+2]
008419E3 . 41 inc ecx
008419E4 . 66:8338 00 cmp word ptr [eax], 0
008419E8 .^ 75 F6 jne short 008419E0
008419EA . 83F9 02 cmp ecx, 2 ; 判断注册码中的字母个数是否等于2
008419ED . 75 4A jne short 00841A39 ; 不相等则发送注册失败消息
008419EF . 33C0 xor eax, eax
008419F1 . C745 F0 31003500 mov dword ptr [ebp-10], 350031
008419F8 . C745 F4 50004200 mov dword ptr [ebp-0C], 420050
008419FF . 8D77 04 lea esi, [edi+4]
00841A02 . 66:8945 F8 mov word ptr [ebp-8], ax
00841A06 . 33C9 xor ecx, ecx
00841A08 0F1F8400 00000000 nop dword ptr [eax+eax]
00841A10 /> 66:8B444D F0 /mov ax, word ptr [ecx*2+ebp-10]
00841A15 |. 66:3B06 |cmp ax, word ptr [esi]
00841A18 |. 75 1F |jne short 00841A39
00841A1A |. 41 |inc ecx
00841A1B |. 83C6 02 |add esi, 2
00841A1E |. 83F9 04 |cmp ecx, 4
00841A21 |.^ 72 ED \jb short 00841A10 ; 判断注册码中的3-6位是否依次为"15PB"
00841A23 |. 8BD7 mov edx, edi
00841A25 |. 8BCB mov ecx, ebx
00841A27 |. E8 14FDFFFF call 00841740 ; <<==调用注册码判断函数4(重要)
00841A2C |. 6A 00 push 0 ; 返回1注册成功
00841A2E |. 85C0 test eax, eax
00841A30 |. 74 09 jz short 00841A3B
00841A32 |. 68 0B040000 push 40B ; 设置注册成功标志
00841A37 |. EB 07 jmp short 00841A40
00841A39 |> 6A 00 push 0
00841A3B |> 68 0A040000 push 40A ; 设置注册失败标志
00841A40 |> 68 11010000 push 111 ; |Msg = WM_COMMAND
00841A45 |. FF73 04 push dword ptr [ebx+4] ; |hWnd
00841A48 |. FF15 54818500 call dword ptr [<&USER32.PostMess ; \USER32.PostMessageW
00841A4E |. 8B4D FC mov ecx, dword ptr [ebp-4]
00841A51 |. 5F pop edi
00841A52 |. 5E pop esi
00841A53 |. 33CD xor ecx, ebp
00841A55 |. 5B pop ebx
00841A56 |. E8 6A120000 call 00842CC5
00841A5B |. 8BE5 mov esp, ebp
00841A5D |. 5D pop ebp
00841A5E \. C3 ret
四. 注册码判断函数4: 0x00841740, 只有此函数返回1才能注册成功, edx中为待判断的注册码
CPU Disasm
Address Hex dump Command Comments
00841740 $ 55 push ebp ; 注册码判断函数4
00841741 . 8BEC mov ebp, esp
00841743 . 83EC 50 sub esp, 50
00841746 . A1 14F08500 mov eax, dword ptr [85F014]
0084174B . 33C5 xor eax, ebp
0084174D . 8945 FC mov dword ptr [ebp-4], eax
00841750 . 53 push ebx
00841751 . 8BDA mov ebx, edx ; 注册码
00841753 . C745 F4 00000000 mov dword ptr [ebp-0C], 0
0084175A . 8BD1 mov edx, ecx
0084175C . 66:C745 F8 0000 mov word ptr [ebp-8], 0
00841762 . 0F57C0 xorps xmm0, xmm0
00841765 . 8955 B4 mov dword ptr [ebp-4C], edx
00841768 . 56 push esi
00841769 . 57 push edi
0084176A . 0F1145 DC movups dqword ptr [ebp-24], xmm0
0084176E . 8D4D DC lea ecx, [ebp-24]
00841771 . B8 31000000 mov eax, 31
00841776 . 660FD645 EC movq qword ptr [ebp-14], xmm0
0084177B 0F1F4400 00 nop dword ptr [eax+eax]
00841780 /> 66:8901 /mov word ptr [ecx], ax
00841783 |. 8D49 02 |lea ecx, [ecx+2]
00841786 |. 40 |inc eax
00841787 |. 83F8 39 |cmp eax, 39
0084178A |.^ 7E F4 \jle short 00841780
0084178C |. 8B02 mov eax, dword ptr [edx] ; 初始化字符串1-9
0084178E |. 33F6 xor esi, esi
00841790 |. 8D0C43 lea ecx, [eax*2+ebx]
00841793 |. 8BC3 mov eax, ebx
00841795 |. 85DB test ebx, ebx
00841797 |. 74 11 jz short 008417AA
00841799 |. 66:3933 cmp word ptr [ebx], si
0084179C |. 74 0C je short 008417AA
0084179E |. 66:90 nop
008417A0 |> 8D40 02 /lea eax, [eax+2]
008417A3 |. 46 |inc esi
008417A4 |. 66:8338 00 |cmp word ptr [eax], 0
008417A8 |.^ 75 F6 \jne short 008417A0
008417AA |> 51 push ecx ; /Arg2, 字符串 注册码的后6位
008417AB |. 8D45 DC lea eax, [ebp-24] ; |
008417AE |. 50 push eax ; |Arg1, 字符串1-9
008417AF |. E8 1C110000 call 008428D0 ; \Crack_Me.008428D0, 连接两个字符串
008417B4 |. 8D76 FF lea esi, [esi-1]
008417B7 |. 8BF8 mov edi, eax
008417B9 |. 8D0473 lea eax, [esi*2+ebx] ; 算出注册码最后一个字符的指针
008417BC |. 897D B8 mov dword ptr [ebp-48], edi
008417BF |. 33F6 xor esi, esi
008417C1 |. 8945 B0 mov dword ptr [ebp-50], eax
008417C4 |. 66:3975 DC cmp word ptr [ebp-24], si
008417C8 |. 74 31 je short 008417FB
008417CA |. 0FB738 movzx edi, word ptr [eax]
008417CD |. 8D4D DC lea ecx, [ebp-24]
008417D0 |. 83E7 01 and edi, 00000001
008417D3 |> 66:8B01 /mov ax, word ptr [ecx]
008417D6 |. 66:C1E8 02 |shr ax, 2
008417DA |. 66:03C7 |add ax, di
008417DD |. 66:83F8 32 |cmp ax, 32
008417E1 |. 74 78 |je short 0084185B
008417E3 |. 66:83F8 64 |cmp ax, 64
008417E7 |. 74 0F |je short 008417F8
008417E9 |. 46 |inc esi
008417EA |. 8D4D DC |lea ecx, [ebp-24]
008417ED |. 8D1436 |lea edx, [esi+esi]
008417F0 |. 03CA |add ecx, edx
008417F2 |. 66:8339 00 |cmp word ptr [ecx], 0
008417F6 |.^ 75 DB \jne short 008417D3 ; [冗余操作]1-9字符串必然符合条件
008417F8 |> 8B7D B8 mov edi, dword ptr [ebp-48]
008417FB |> 8D4D DC lea ecx, [ebp-24]
008417FE |. 8BF3 mov esi, ebx ; 注册码
00841800 |. 8BC1 mov eax, ecx
00841802 |. BA 31000000 mov edx, 31
00841807 |. 2BF0 sub esi, eax
00841809 |. 0F1F80 00000000 nop dword ptr [eax]
00841810 |> 66:8B01 /mov ax, word ptr [ecx]
00841813 |. 66:3B040E |cmp ax, word ptr [ecx+esi]
00841817 |. 75 42 |jne short 0084185B ; 不相等返回0, 注册失败
00841819 |. 83C2 06 |add edx, 6
0084181C |. 83C1 02 |add ecx, 2
0084181F |. 83FA 39 |cmp edx, 39
00841822 |.^ 7E EC \jle short 00841810 ; 循环两次,分别判断注册码的前两个字符是否分别为1和2
00841824 |. 0FB74F 12 movzx ecx, word ptr [edi+12] ; 取出注册码的第二个字符
00841828 |. 0FB703 movzx eax, word ptr [ebx] ; 取出注册码的第一个字符
0084182B |. 03C8 add ecx, eax
0084182D |. 83F9 63 cmp ecx, 63 ; 两个字符相加是否等于0x63
00841830 |. 75 29 jne short 0084185B ; 不相等返回0, 注册失败
00841832 |. 8B45 B4 mov eax, dword ptr [ebp-4C]
00841835 |. 0FB74F 0C movzx ecx, word ptr [edi+0C] ; 取出常量字符串中的第七个字符0x37
00841839 |. 0308 add ecx, dword ptr [eax] ; 加上点击ok按钮的次数(本次启动验证注册码的次数)
0084183B |. 8B45 B0 mov eax, dword ptr [ebp-50] ; 相加等于ascii码0x38
0084183E |. 0FB700 movzx eax, word ptr [eax]
00841841 |. 3BC1 cmp eax, ecx ; 判断与注册码最后一位是否相等
00841843 |. 75 16 jne short 0084185B ; 不相等返回0, 注册失败
00841845 |. 5F pop edi ; UNICODE "1215PB8"
00841846 |. 5E pop esi
00841847 |. B8 01000000 mov eax, 1 ; 返回1, 注册成功分支
0084184C |. 5B pop ebx
0084184D |. 8B4D FC mov ecx, dword ptr [ebp-4]
00841850 |. 33CD xor ecx, ebp
00841852 |. E8 6E140000 call 00842CC5
00841857 |. 8BE5 mov esp, ebp
00841859 |. 5D pop ebp
0084185A |. C3 ret
0084185B |> 8B4D FC mov ecx, dword ptr [ebp-4] ; 返回0, 注册失败分支
0084185E |. 33C0 xor eax, eax
00841860 |. 5F pop edi
00841861 |. 5E pop esi
00841862 |. 33CD xor ecx, ebp
00841864 |. 5B pop ebx
00841865 |. E8 5B140000 call 00842CC5
0084186A |. 8BE5 mov esp, ebp
0084186C |. 5D pop ebp
0084186D \. C3 ret
--------------------------------------------------------------------------------
【版权声明】: 本文原创于xietao, 转载请注明作者并保持文章的完整, 谢谢!
2016年11月02日 0:02:07
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课