首页
社区
课程
招聘
[旧帖] CrackMe分析,新人求转正~ 0.00雪花
发表于: 2013-7-10 21:07 4015

[旧帖] CrackMe分析,新人求转正~ 0.00雪花

2013-7-10 21:07
4015

CrackMe详细分析,新人求转正~

工作一年了。像我们这种新人,team里一些重要的feature都不让参与,只能修修bug,觉得进步好慢啊啊啊!以前听一个师兄说逆向是一条能让人静下心来的不归路,同时也能够让编程的功底更扎实,不过始终不敢尝试:(慢慢开始觉得工作中有些问题的解决思路和逆向真的有点像,于是试着能来学一点东西。
这个CrackMe已经有人分析过,不过总是觉得没有过程,只有结果,不利于初学者学习,于是想以自己的角度再来分析一下其中过程。
原帖戳这里:http://bbs.pediy.com/showthread.php?t=163006
只用了IDA的静态解析(没有参考F5的结果),以及使用windbg进行动态跟踪。

1. Anti-debug
习惯性地windbg载入,咦,被发现了!希望anti-debug不要太复杂。
IDA载入分析一下,看导入函数表。既然是窗口,先看CreateWindowEx。有13处调用。。。一个一个过去看一下,没有明显的迹象哪个是"U look like a reverser"。再看看MessageBox。有4处调用。也没发现哪个是anti-debug弹出的窗口。于是先判断一下到底用了哪个函数来弹出anti-debug信息。
来到CreateWindowEx和MessageBox导入表跳转地址处,都改成int 3.
MessageBox:
0001c610h: FF 25 84 B4 45 00
CreateWindowEx:
0001c650h: FF 25 58 B4 45 00
>>>
0001c610h: CC 25 84 B4 45 00
...
0001c650h: CC 25 58 B4 45 00
windbg重新载入patch过的exe,go~
INT 3断在了0041d250,即CreateWindowEx处。向上一级来到调用处:
0041949a 895c2404        mov     dword ptr [esp+4],ebx
0041949e 8954240c        mov     dword ptr [esp+0Ch],edx
004194a2 890424          mov     dword ptr [esp],eax
004194a5 e82441ffff      call    image00400000+0xd5ce (0040d5ce)
看倒数第二和第三个入栈的参数,都没看到对应的字符串,因此该CreateWindowEx不是弹出anti-debug信息的地方。
把导入表跳转地址改回原始值,等执行过后再改为CC,然后继续go。
重复几次之后,有一次断在了0x1c610,即MessageBox跳转处。上层的call长这个样子:
0040d4b6 e895fd0000      call    image00400000+0x1d250 (0041d250)
0040d4bb 83ec30          sub     esp,30h
0040d4be e829c8ffff      call    image00400000+0x9cec (00409cec)
0040d4c3 8d8578fcffff    lea     eax,[ebp-388h]
我们看一下堆栈:
0:000> dd esp
0022f274  00409e2a 00000000 004d1804 004d1804
0022f284  00000000 00000000 002c85b0 0022f314
0022f294  76587b84 002c0000 00000000 002c85b8
0022f2a4  0022f91c 00000001 00000000 0022f494
0022f2b4  00000001 0022f2dc 75cd7e1a 00000000
0022f2c4  00000000 0040dd50 0044ff54 0022f338
0022f2d4  00409e39 0022f278 0022f494 ffffffff
0022f2e4  004d1804 004d1804 0000000c 0000000e
查看一下最后几个入栈的参数:
当我们查看004d1804这个地址的时候,好像发现了些什么:
0:000> da 004d1804
004d1804  "U look like a reverser!"
但是call的地方好像有点奇怪,我们回到IDA中去看一下0040d4be这个地方,是一个对sub_409CEC的调用。继续进入sub_409CEC看一看,blabla做了一堆事,然后发现一个ExitProcess!那估计就是这里了!
恢复原始的exe,然后我们在sub_409CEC的入口处写入INT 3.重新用windbg载入,断下来之后把入口改回55,开始单步~同时结合IDA的结果进行分析。
.text:00409CEC 55                                      push    ebp
.text:00409CED 89 E5                                   mov     ebp, esp
.text:00409CEF 57                                      push    edi
.text:00409CF0 56                                      push    esi
.text:00409CF1 53                                      push    ebx
.text:00409CF2 81 EC CC 00 00 00                       sub     esp, 0CCh
.text:00409CF8 C7 85 78 FF FF FF 50 DD+                mov     [ebp+var_88], offset ___gxx_personality_sj0
.text:00409D02 C7 85 7C FF FF FF 54 FF+                mov     [ebp+var_84], offset dword_44FF54
.text:00409D0C 8D 45 80                                lea     eax, [ebp+var_80]
.text:00409D0F 8D 55 E8                                lea     edx, [ebp+var_18]
.text:00409D12 89 10                                   mov     [eax], edx
.text:00409D14 BA 39 9E 40 00                          mov     edx, offset loc_409E39
.text:00409D19 89 50 04                                mov     [eax+4], edx
.text:00409D1C 89 60 08                                mov     [eax+8], esp
.text:00409D1F 8D 85 60 FF FF FF                       lea     eax, [ebp+TlsValue]
.text:00409D25 89 04 24                                mov     [esp], eax      ; lpTlsValue
.text:00409D28 E8 43 FD 00 00                          call    __Unwind_SjLj_Register
.text:00409D2D C7 45 E4 07 00 00 00                    mov     [ebp+var_1C], 7
.text:00409D34 C7 45 E0 00 00 00 00                    mov     [ebp+var_20], 0
.text:00409D3B C7 45 D8 00 00 00 00                    mov     [ebp+var_28], 0
.text:00409D42 C7 04 24 61 30 45 00                    mov     dword ptr [esp], offset aNtdll_dll ; "ntdll.dll"
.text:00409D49 C7 85 64 FF FF FF FF FF+                mov     [ebp+var_9C], 0FFFFFFFFh
.text:00409D53 E8 18 36 01 00                          call    LoadLibraryA
.text:00409D58 83 EC 04                                sub     esp, 4
.text:00409D5B 89 45 D4                                mov     [ebp+hModule], eax
.text:00409D5E 8D 45 B8                                lea     eax, [ebp+var_48]
.text:00409D61 89 04 24                                mov     [esp], eax
.text:00409D64 E8 0D D6 FF FF                          call    sub_407376
.text:00409D69 83 EC 04                                sub     esp, 4
.text:00409D6C 8D 45 B8                                lea     eax, [ebp+var_48]
.text:00409D6F 89 04 24                                mov     [esp], eax
.text:00409D72 C7 85 64 FF FF FF 02 00+                mov     [ebp+var_9C], 2
.text:00409D7C E8 87 68 01 00                          call    unknown_libname_42 ; GCC (mingw/cygwin) v3.4 runtime
.text:00409D81 89 45 B4                                mov     [ebp+lpProcName], eax
.text:00409D84 8B 45 B4                                mov     eax, [ebp+lpProcName]
.text:00409D87 89 44 24 04                             mov     [esp+4], eax    ; lpProcName
.text:00409D8B 8B 45 D4                                mov     eax, [ebp+hModule]
.text:00409D8E 89 04 24                                mov     [esp], eax      ; hModule
.text:00409D91 E8 BA 35 01 00                          call    GetProcAddress
.text:00409D96 83 EC 08                                sub     esp, 8
.text:00409D99 89 45 E0                                mov     [ebp+var_20], eax
.text:00409D9C E8 DF 35 01 00                          call    GetCurrentProcess
.text:00409DA1 C7 44 24 10 00 00 00 00                 mov     dword ptr [esp+10h], 0
.text:00409DA9 C7 44 24 0C 04 00 00 00                 mov     dword ptr [esp+0Ch], 4
.text:00409DB1 8D 55 D8                                lea     edx, [ebp+var_28]
.text:00409DB4 89 54 24 08                             mov     [esp+8], edx
.text:00409DB8 C7 44 24 04 07 00 00 00                 mov     dword ptr [esp+4], 7
.text:00409DC0 89 04 24                                mov     [esp], eax
.text:00409DC3 8B 45 E0                                mov     eax, [ebp+var_20]
.text:00409DC6 FF D0                                   call    eax
.text:00409DC8 83 EC 14                                sub     esp, 14h
.text:00409DCB 89 45 DC                                mov     [ebp+var_24], eax
.text:00409DCE 83 7D DC 00                             cmp     [ebp+var_24], 0
.text:00409DD2 0F 85 ED 00 00 00                       jnz     loc_409EC5
.text:00409DD8 83 7D D8 00                             cmp     [ebp+var_28], 0
.text:00409DDC 0F 84 E3 00 00 00                       jz      loc_409EC5
.text:00409DE2 8D 45 98                                lea     eax, [ebp+var_68]
.text:00409DE5 89 04 24                                mov     [esp], eax
.text:00409DE8 E8 3B BF FF FF                          call    sub_405D28
.text:00409DED 83 EC 04                                sub     esp, 4
.text:00409DF0 8D 45 98                                lea     eax, [ebp+var_68]
.text:00409DF3 89 04 24                                mov     [esp], eax
.text:00409DF6 C7 85 64 FF FF FF 01 00+                mov     [ebp+var_9C], 1
.text:00409E00 E8 03 68 01 00                          call    unknown_libname_42 ; GCC (mingw/cygwin) v3.4 runtime
.text:00409E05 89 45 94                                mov     [ebp+lpCaption], eax
.text:00409E08 C7 44 24 0C 00 00 00 00                 mov     dword ptr [esp+0Ch], 0 ; uType
.text:00409E10 8B 45 94                                mov     eax, [ebp+lpCaption]
.text:00409E13 89 44 24 08                             mov     [esp+8], eax    ; lpCaption
.text:00409E17 8B 45 94                                mov     eax, [ebp+lpCaption]
.text:00409E1A 89 44 24 04                             mov     [esp+4], eax    ; lpText
.text:00409E1E C7 04 24 00 00 00 00                    mov     dword ptr [esp], 0 ; hWnd
.text:00409E25 E8 E6 33 01 00                          call    MessageBoxA
.text:00409E2A 83 EC 10                                sub     esp, 10h
.text:00409E2D C7 04 24 00 00 00 00                    mov     dword ptr [esp], 0 ; uExitCode
.text:00409E34 E8 D7 34 01 00                          call    ExitProcess
我们看到在MessageBox之后紧接着就会ExitProcess,而之前的两个跳转会跳过该段。那么这两个跳转判断了什么呢?之前的代码就是LoadLibrary载入了ntdll.dll,然后用GetProcAddress拿了某个函数指针,又用GetCurrentProcess拿了当前进程,然后一些判断。先来看看GetProcAddress取了哪个函数:
来到00409D81处时,
0:000> da eax
005e316c  "NtQueryInformationProcess"
来到00409DC6准备调用NtQueryInformationProcess时,我们再来看它的参数:
0:000> dd esp
0022f278  ffffffff 00000007 0022f328 00000004
0022f288  00000000 002985b0 0022f314 76587b84
0022f298  00290000 00000000 002985b8 0022f91c
0022f2a8  00000001 00000000 0022f494 00000002
0022f2b8  0022f2dc 75cd7e1a 00000000 00000000
0022f2c8  0040dd50 0044ff54 0022f338 00409e39
0022f2d8  0022f278 0022f494 ffffffff 0022f318
0022f2e8  0043ba18 0000000c 0000000e 002985b8
NtQueryInformationProcess函数的原型如下:
NTSTATUS WINAPI NtQueryInformationProcess(
  _In_       HANDLE ProcessHandle,
  _In_       PROCESSINFOCLASS ProcessInformationClass,
  _Out_      PVOID ProcessInformation,
  _In_       ULONG ProcessInformationLength,
  _Out_opt_  PULONG ReturnLength
);
ProcessInformationClass=7时,表示要获取的信息是ProcessDebugPort。
而0022f328就是ProcessInformation的地址了。单步执行完这个函数,再看该地址的内容:
0:000> dd 0022f328 L1
0022f328  ffffffff
ProcessDebugPort非0,表示当前进程正在被调试。
回去看该函数,判断正在被调试的条件有两个,一是NtQueryInformationProcess返回错误:
call    eax ;NtQueryInformationProcess
...
mov     [ebp+var_24], eax ;返回值
cmp     [ebp+var_24], 0
jnz     loc_409EC5

还有一个就是ProcessDebugPort非0:
lea     edx, [ebp+var_28]
mov     [esp+8], edx ;第三个参数
...
call    eax ;NtQueryInformationProcess
...
cmp     [ebp+var_28], 0
jz      loc_409EC5

把0022f328的内容该为0,go~ anti-debug窗口消失了~
只用了最简单的手段,果然适合新人╮(╯-╰)╭
后面还有一处检查调试器的地方,不过暂时不影响当前的调试,后面再谈。

2.用户名和序列号校验
能够顺利debug了之后,分析就方便多了~
先找到取用户输入的地方。查找对GetWindowText的调用,发现只有两处。断在这两个地方检查输出,果然就是这两处调用获得了输入,接下来就是漫长的校验过程。
开始一段并没有任何跳转分支,一步步往下看就好了。
首先看到几处对unknown_libname_134(sub_43CFA8)的调用,进去看看,发现用到了strlen,再往里看到了memcpy。对照sub_43CFA8的三个参数在函数执行前后的结果,看上去这像是个分配、构造、拷贝字符串相关的函数。
按类似的方法继续进行,有函数调用就进去大致看一下内容,然后在函数执行前和执行后,比较一下压入栈的参数的变化,以及函数执行的返回值,大致能猜到意思的就在边上标记一下。猜不到的也标记一下函数执行前的参数内容。
********
一直都没有跳转分支,直到来到这里:
.text:0040B414 83 BD 64 FD FF FF 03                    cmp     [ebp+var_29C], 3
.text:0040B41B 0F 8E 20 1A 00 00                       jle     loc_40CE41
往后翻到loc_40CE41处,发现很快就返回了。看来这是比较条件之一。
我们往前看看var_29C这个值是怎么来的,发现是这里来的:
.text:0040B350 8D 85 98 FD FF FF                       lea     eax, [ebp+var_268]
.text:0040B356 89 04 24                                mov     [esp], eax
.text:0040B359 C7 85 F8 FB FF FF 2B 00+                mov     [ebp+var_408], 2Bh
.text:0040B363 E8 20 54 01 00                          call    unknown_libname_43 ; GCC (mingw/cygwin) v3.4 runtime
.text:0040B368 89 85 64 FD FF FF                       mov     [ebp+var_29C], eax
继续向前找var_268,发现是一个指向第一个输入框输入内容的指针,就是从unknown_libname_134得来。
进一步分析unknown_libname_43的作用,明白了该函数是计算字符串长度。因此这里的判断是输入的用户名要大于3。
********
紧接着就来到
.text:0040B421 8D 85 68 FD FF FF                       lea     eax, [ebp+var_298]
.text:0040B427 89 04 24                                mov     [esp], eax
.text:0040B42A E8 29 F6 FF FF                          call    sub_40AA58
进入sub_40AA58查看,看到对WSAStartup和gethostname的调用,看来是要取本机信息了。执行完之后查看var_298的内容,果然,是本机名。
然后看到一组调用
.text:0040B432 C7 44 24 04 00 00 00 00                 mov     dword ptr [esp+4], 0
.text:0040B43A 8D 85 68 FD FF FF                       lea     eax, [ebp+var_298]
.text:0040B440 89 04 24                                mov     [esp], eax
.text:0040B443 C7 85 F8 FB FF FF 29 00+                mov     [ebp+var_408], 29h
.text:0040B44D E8 96 25 03 00                          call    __ZNSsixEj
.text:0040B452 0F BE 00                                movsx   eax, byte ptr [eax]
.text:0040B455 89 44 24 04                             mov     [esp+4], eax
.text:0040B459 8D 85 68 FD FF FF                       lea     eax, [ebp+var_298]
.text:0040B45F 89 04 24                                mov     [esp], eax
.text:0040B462 E8 31 25 03 00                          call    __ZNSsaSEc
这种形式后面还用到过几次,分析一下可以知道,这组函数就是取输入字符的第n个字符的。
比如这里,
mov     dword ptr [esp+4], 0
就表示去掉var_298的前0个字符,也就是取第一个字符。
然后又看到了sub_409CEC,就是前面检查有没有在调试的函数。
然后来到这里:
.text:0040B46C 8D 85 C8 FE FF FF                       lea     eax, [ebp+var_138]
.text:0040B472 89 04 24                                mov     [esp], eax      ; char *
.text:0040B475 E8 D6 1A 01 00                          call    strlen
.text:0040B47A 0F B6 84 28 C7 FE FF FF                 movzx   eax, byte ptr [eax+ebp-139h]
这里的var_138就是第二个GetWindowText得到的序列号,然后得到字符串长度,又movzx,其实就是取序列号的最后一个字符~
********
再往后一点,我们又来到一处分支。
.text:0040B506 C7 85 24 FD FF FF 02 00+                mov     [ebp+var_2DC], 2
.text:0040B510 C7 85 20 FD FF FF 14 00+                mov     [ebp+var_2E0], 14h
.text:0040B51A 8B 85 64 FD FF FF                       mov     eax, [ebp+var_29C]
.text:0040B520 3B 85 24 FD FF FF                       cmp     eax, [ebp+var_2DC]
.text:0040B526 7F 0B                                   jg      short loc_40B533
第一个判断,用户名长度是否大于2。前面已经判断大于3,这里必定大于2,继续~
.text:0040B533 83 BD 20 FD FF FF 00                    cmp     [ebp+var_2E0], 0
.text:0040B53A 75 02                                   jnz     short loc_40B53E
第二个判断,var_2E0是否等于0。前面刚mov     [ebp+var_2E0], 14h过,继续~
于是我们来到:
.text:0040B5BA 8D 85 68 FD FF FF                       lea     eax, [ebp+var_298]
.text:0040B5C0 89 44 24 04                             mov     [esp+4], eax
.text:0040B5C4 8D 85 48 FD FF FF                       lea     eax, [ebp+var_2B8]
.text:0040B5CA 89 04 24                                mov     [esp], eax
.text:0040B5CD C7 85 F8 FB FF FF 27 00+                mov     [ebp+var_408], 27h
.text:0040B5D7 E8 CC 52 01 00                          call    __ZNKSs7compareERKSs
.text:0040B5DC 85 C0                                   test    eax, eax
.text:0040B5DE 0F 85 D8 16 00 00                       jnz     loc_40CCBC
这里的var_298,就是前面分析过的,本机名的第一个字符。
而var_2B8,也是前面分析过的,序列号的最后一个字符,不过又被复制到了另一个地方而已。
如果不相等,跳去loc_40CCBC。可以看到loc_40CCBC处有一个CreateWindowExA的调用,如果我们故意输入时的序列号最后一位不等于本机名第一位,可以看到该CreateWindowExA会创建一个“incorrect!”的窗口。
.text:0040B5E4 E8 A5 E5 FF FF                          call    sub_409B8E
.text:0040B5E9 E8 FE E6 FF FF                          call    sub_409CEC
sub_409CEC我们已经分析过了,是检查debug port的函数。
如果我们去看一下sub_409B8E,发现是调用kernel32.dll中的IsDebuggerPresent函数。所以这里也会检查是不是在被调试哟~~
********
再往前,来到这里:
.text:0040B694 83 BD 64 FD FF FF 06                    cmp     [ebp+var_29C], 6
.text:0040B69B 0F 8F 26 15 00 00                       jg      loc_40CBC7
用户名长度要小于等于6.
********
然后来到sub_40A802,进去一看,又是对一些Win32API的调用,分析后知道这个函数是用来取得系统网卡的MAC地址,去除了中间的连接符-
然后就是前面提到过的一组调用,这我们看到
.text:0040B6B2 C7 44 24 04 03 00 00 00                 mov     dword ptr [esp+4], 3
.text:0040B6BA 8D 85 08 FD FF FF                       lea     eax, [ebp+var_2F8]
.text:0040B6C0 89 04 24                                mov     [esp], eax
.text:0040B6C3 C7 85 F8 FB FF FF 25 00+                mov     [ebp+var_408], 25h
.text:0040B6CD E8 16 23 03 00                          call    __ZNSsixEj
.text:0040B6D2 0F BE 00                                movsx   eax, byte ptr [eax]
.text:0040B6D5 89 44 24 04                             mov     [esp+4], eax
.text:0040B6D9 8D 85 08 FD FF FF                       lea     eax, [ebp+var_2F8]
.text:0040B6DF 89 04 24                                mov     [esp], eax
.text:0040B6E2 E8 B1 22 03 00                          call    __ZNSsaSEc
根据前面的分析,这组调用是取网卡MAC地址(去除连接符-后)第4个字符,存放于var_2F8。

.text:0040B6F5 C7 44 24 04 00 00 00 00                 mov     dword ptr [esp+4], 0
.text:0040B6FD 8D 85 88 FD FF FF                       lea     eax, [ebp+var_278]
.text:0040B703 89 04 24                                mov     [esp], eax
.text:0040B706 C7 85 F8 FB FF FF 24 00+                mov     [ebp+var_408], 24h
.text:0040B710 E8 D3 22 03 00                          call    __ZNSsixEj
.text:0040B715 0F BE 00                                movsx   eax, byte ptr [eax]
.text:0040B718 89 44 24 04                             mov     [esp+4], eax
.text:0040B71C 8D 85 28 FD FF FF                       lea     eax, [ebp+var_2D8]
.text:0040B722 89 04 24                                mov     [esp], eax
.text:0040B725 E8 6E 22 03 00                          call    __ZNSsaSEc
这里就是取序列号的第一个字符,存放于var_2D8。

.text:0040B7D1 8D 85 08 FD FF FF                       lea     eax, [ebp+var_2F8]
.text:0040B7D7 89 44 24 04                             mov     [esp+4], eax
.text:0040B7DB 8D 85 28 FD FF FF                       lea     eax, [ebp+var_2D8]
.text:0040B7E1 89 04 24                                mov     [esp], eax
.text:0040B7E4 E8 BF 50 01 00                          call    __ZNKSs7compareERKSs
.text:0040B7E9 85 C0                                   test    eax, eax
.text:0040B7EB 0F 85 49 12 00 00                       jnz     loc_40CA3A
接下来就是对二者的比较。因此我们知道了序列号的第一位要等于网卡MAC的第四位。
********
.text:0040B81E E8 C5 4D 01 00                          call    unknown_libname_40 ; GCC (mingw/cygwin) v3.4 runtime
.text:0040B823 48                                      dec     eax
.text:0040B824 89 44 24 0C                             mov     [esp+0Ch], eax
.text:0040B828 C7 44 24 08 00 00 00 00                 mov     dword ptr [esp+8], 0
.text:0040B830 8D 85 88 FD FF FF                       lea     eax, [ebp+var_278]
.text:0040B836 89 44 24 04                             mov     [esp+4], eax
.text:0040B83A 8B 95 C4 FB FF FF                       mov     edx, [ebp+var_43C]
.text:0040B840 89 14 24                                mov     [esp], edx
.text:0040B843 E8 70 4F 01 00                          call    __ZNKSs6substrEjj
.text:0040B848 83 EC 04                                sub     esp, 4
.text:0040B84B 8D 85 D8 FC FF FF                       lea     eax, [ebp+var_328]
.text:0040B851 89 44 24 04                             mov     [esp+4], eax
.text:0040B855 8D 85 F8 FC FF FF                       lea     eax, [ebp+var_308]
.text:0040B85B 89 04 24                                mov     [esp], eax
.text:0040B85E C7 85 F8 FB FF FF 21 00+                mov     [ebp+var_408], 21h
.text:0040B868 E8 FB 20 03 00                          call    __ZNSsaSERKSs
注意这里,实际是取了序列号的前n-1个字符,存放于var_308.
********
.text:0040B8BC 8D 85 88 FD FF FF                       lea     eax, [ebp+var_278]
.text:0040B8C2 89 04 24                                mov     [esp], eax
.text:0040B8C5 E8 BE 4E 01 00                          call    unknown_libname_43 ; GCC (mingw/cygwin) v3.4 runtime
.text:0040B8CA 89 85 D4 FC FF FF                       mov     [ebp+var_32C], eax
.text:0040B8D0 8D 85 D4 FC FF FF                       lea     eax, [ebp+var_32C]
.text:0040B8D6 83 28 05                                sub     dword ptr [eax], 5
.text:0040B8D9 83 BD D4 FC FF FF 0A                    cmp     [ebp+var_32C], 0Ah
.text:0040B8E0 7E 75                                   jle     short loc_40B957
之后又是CreateWindowExA,然后就PostQuitMessage退出了!
来到这里,分析得知,若序列号长度-5<=10,即<=15才不会直接退出。
********
.text:0040B957 8D 85 F8 FC FF FF                       lea     eax, [ebp+var_308]
.text:0040B95D 89 04 24                                mov     [esp], eax
.text:0040B960 C7 85 F8 FB FF FF 22 00+                mov     [ebp+var_408], 22h
.text:0040B96A E8 99 F9 02 00                          call    __ZNSs5beginEv
.text:0040B96F 89 85 D0 FC FF FF                       mov     [ebp+var_330], eax
.text:0040B975 8B 85 D0 FC FF FF                       mov     eax, [ebp+var_330]
.text:0040B97B 89 44 24 04                             mov     [esp+4], eax
.text:0040B97F 8D 85 F8 FC FF FF                       lea     eax, [ebp+var_308]
.text:0040B985 89 04 24                                mov     [esp], eax
.text:0040B988 E8 DB F9 02 00                          call    __ZNSs5eraseEN9__gnu_cxx17__normal_iteratorIPcSsEE
再去除序列号的第一个字符。现在的字符串,相当于用户输入序列号去除第一个和最后一个得到的结果。
然后又是那一组取第n个字符的调用:
.text:0040B9A0 C7 44 24 04 00 00 00 00                 mov     dword ptr [esp+4], 0
.text:0040B9A8 8D 85 F8 FC FF FF                       lea     eax, [ebp+var_308]
.text:0040B9AE 89 04 24                                mov     [esp], eax
.text:0040B9B1 C7 85 F8 FB FF FF 20 00+                mov     [ebp+var_408], 20h
.text:0040B9BB E8 28 20 03 00                          call    __ZNSsixEj
.text:0040B9C0 0F BE 00                                movsx   eax, byte ptr [eax]
.text:0040B9C3 89 44 24 04                             mov     [esp+4], eax
.text:0040B9C7 8D 85 D8 FC FF FF                       lea     eax, [ebp+var_328]
.text:0040B9CD 89 04 24                                mov     [esp], eax
.text:0040B9D0 E8 C3 1F 03 00                          call    __ZNSsaSEc
相当于取出了用户输入序列号的第二个字符,存放于var_328
********
.text:0040BA7B 8D 85 A8 FC FF FF                       lea     eax, [ebp+var_358]
.text:0040BA81 89 04 24                                mov     [esp], eax
.text:0040BA84 E8 8B F1 FF FF                          call    sub_40AC14
这里取出了本机IP地址,存放于var_358
********
.text:0040BAA4 C7 44 24 04 01 00 00 00                 mov     dword ptr [esp+4], 1
.text:0040BAAC 8D 85 A8 FC FF FF                       lea     eax, [ebp+var_358]
.text:0040BAB2 89 04 24                                mov     [esp], eax
.text:0040BAB5 C7 85 F8 FB FF FF 1D 00+                mov     [ebp+var_408], 1Dh
.text:0040BABF E8 24 1F 03 00                          call    __ZNSsixEj
.text:0040BAC4 0F BE 00                                movsx   eax, byte ptr [eax]
.text:0040BAC7 89 44 24 04                             mov     [esp+4], eax
.text:0040BACB 8D 85 B8 FC FF FF                       lea     eax, [ebp+var_348]
.text:0040BAD1 89 04 24                                mov     [esp], eax
.text:0040BAD4 E8 BF 1E 03 00                          call    __ZNSsaSEc
出现多次了,取IP地址的第2个字符。
********
.text:0040BAD9 8D 85 D8 FC FF FF                       lea     eax, [ebp+var_328]
.text:0040BADF 89 44 24 04                             mov     [esp+4], eax
.text:0040BAE3 8D 85 B8 FC FF FF                       lea     eax, [ebp+var_348]
.text:0040BAE9 89 04 24                                mov     [esp], eax
.text:0040BAEC E8 B7 4D 01 00                          call    __ZNKSs7compareERKSs
.text:0040BAF1 85 C0                                   test    eax, eax
.text:0040BAF3 0F 85 1C 0D 00 00                       jnz     loc_40C815
比较序列号的第2个字符和IP地址的第2个字符
********
.text:0040BB25 8B 85 1C FD FF FF                       mov     eax, [ebp+var_2E4]
.text:0040BB2B 89 04 24                                mov     [esp], eax      ; char *
.text:0040BB2E E8 8D 14 01 00                          call    atoi
序列号第1位由ASCII转化为数字
********
.text:0040BB5D 8D 85 78 FC FF FF                       lea     eax, [ebp+var_388]
.text:0040BB63 89 44 24 04                             mov     [esp+4], eax
.text:0040BB67 8B 95 B4 FB FF FF                       mov     edx, [ebp+var_44C]
.text:0040BB6D 89 14 24                                mov     [esp], edx
.text:0040BB70 C7 85 F8 FB FF FF 1C 00+                mov     [ebp+var_408], 1Ch
.text:0040BB7A E8 9B D3 FF FF                          call    sub_408F1A
这里很有意思,把用户名字符串依次直接转化为十六进制字符串了~
********
然后来到这里:
.text:0040BBFF 8D 95 68 FC FF FF                       lea     edx, [ebp+var_398]
.text:0040BC05 8B 85 A0 FC FF FF                       mov     eax, [ebp+var_360]
.text:0040BC0B 89 44 24 08                             mov     [esp+8], eax
.text:0040BC0F 89 54 24 04                             mov     [esp+4], edx
.text:0040BC13 8B 95 AC FB FF FF                       mov     edx, [ebp+var_454]
.text:0040BC19 89 14 24                                mov     [esp], edx
.text:0040BC1C C7 85 F8 FB FF FF 1A 00+                mov     [ebp+var_408], 1Ah
.text:0040BC26 E8 CD D5 FF FF                          call    sub_4091F8
开始没有太在意这里,只知道sub_4091F8执行之后得到了一个奇怪的数字,存放在var_454表示的地址上了。
********
然后就来到了这里:
.text:0040BC65                         loc_40BC65:                             ; CODE XREF: sub_40AFA0+C8Ej
.text:0040BC65 8D 85 68 FC FF FF                       lea     eax, [ebp+var_398]
.text:0040BC6B 89 04 24                                mov     [esp], eax
.text:0040BC6E C7 85 F8 FB FF FF 1B 00+                mov     [ebp+var_408], 1Bh
.text:0040BC78 E8 4B 1B 03 00                          call    unknown_libname_154 ; GCC (mingw/cygwin) v3.4 runtime
.text:0040BC7D C7 85 64 FC FF FF 00 00+                mov     [ebp+var_39C], 0
.text:0040BC87
.text:0040BC87                         loc_40BC87:                             ; CODE XREF: sub_40AFA0+17D2j
.text:0040BC87 81 BD 64 FC FF FF C7 00+                cmp     [ebp+var_39C], 0C7h
.text:0040BC91 0F 8F 12 0B 00 00                       jg      loc_40C7A9
觉得奇怪吧?先
mov     [ebp+var_39C], 0
再和0xC7比较。意味着循环正式开始啦!

3.不要被循环迷惑
遇到循环总是很头疼的事,不过这里偶并没有直接开始跟踪,而是先找到循环体,再看看如何切入。
循环变量var_39C从这里开始:
.text:0040BC7D C7 85 64 FC FF FF 00 00+                mov     [ebp+var_39C], 0
往后翻翻,其实分支并不是很多,看完之后简写一下,大约长这个样子:
for(var_39C = 0;var_39C <= 0xC7; var_39C++)
{
    if(var_39C <= 4)
    {
        loc_40BCA4:
        ...
    }
    if(var_39C > 0xB4)
    {
        loc_40BD69:
        ...
    }
    if(var_39C == 0x8E)
    {
        loc_40BE02:
        ...
    }
    if(var_39C == 0x78)
    {
        loc_40BEC4:
        ...
    }
    if(var_39C == 0xC7)
    {
        loc_40C04B:
        ...
        if(__ZNKSs7compareERKSs == 0)
        {
            loc_40C084:
            for(var_3BC = 1; var_3BC <= 0x423;var_3BC++)
            {
                if(var_3BC <= 4)
                {
                    loc_40C0A1:
                    ...
                }
                if(var_3BC == 0x17)
                {
                    loc_40C1C0:
                    ...
                }
                if(var_3BC == 0x308)
                {
                    loc_40C2DD:
                    ...
                }
                if(var_3BC == 0x307)
                {
                    loc_40C39E:
                    ...
                }
                if(var_3BC == 0x309)
                {
                    loc_40C551:
                    ...
                    if(__ZNKSs7compareERKSs == 0)
                    {
                        loc_40C580:
                        ...
                        CreateWindowExA
                        ...
                    }
                }
            }
        }
        else
        {
            loc_40C67D:
            ...
            CreateWindowExA
            ...
        }
    }
}
loc_40C7A9:
...
return;
这样写出来这个循环就很简单了,两个循环变量都是在迷惑你的!
我们把断点放在两个比较和两个CreateWindowExA处。
先看这里:
.text:0040C05A 8D 85 F8 FC FF FF                       lea     eax, [ebp+var_308]
.text:0040C060 89 44 24 04                             mov     [esp+4], eax
.text:0040C064 8D 85 78 FC FF FF                       lea     eax, [ebp+var_388]
.text:0040C06A 89 04 24                                mov     [esp], eax
.text:0040C06D E8 36 48 01 00                          call    __ZNKSs7compareERKSs
.text:0040C072 85 C0                                   test    eax, eax
.text:0040C074 0F 85 03 06 00 00                       jnz     loc_40C67D
两个比较对象分别是,序列号去掉第1、2和最后一个字符的结果,以及我们在前面sub_4091F8得到的奇怪数字。继续跟踪,如果比较结果不相等,调用CreateWindowExA,创建“incorrect!”窗口。
感觉这个奇怪数字就是正确序列号的一部分嘛!我们把这个数字拼上第1、2以及最后一个字符,测试一下?果然正确了!看来我们只要继续分析sub_4091F8就能得到序列号的正确算法了!

4. 序列号算法
接下来具体分析sub_4091F8的行为。
.text:0040BBFF 8D 95 68 FC FF FF                       lea     edx, [ebp+var_398]
.text:0040BC05 8B 85 A0 FC FF FF                       mov     eax, [ebp+var_360]
.text:0040BC0B 89 44 24 08                             mov     [esp+8], eax
.text:0040BC0F 89 54 24 04                             mov     [esp+4], edx
.text:0040BC13 8B 95 AC FB FF FF                       mov     edx, [ebp+var_454]
.text:0040BC19 89 14 24                                mov     [esp], edx
.text:0040BC1C C7 85 F8 FB FF FF 1A 00+                mov     [ebp+var_408], 1Ah
.text:0040BC26 E8 CD D5 FF FF                          call    sub_4091F8
从这里我们可以看到,sub_4091F8有三个参数,分别是:
用于保存结果的指针,转化为十六进制序列的用户名,序列号的第一位(数字)。

从这里开始分析,为了方便,就把结果写在后面了:
.text:0040923C 8B 4D 0C                                mov     ecx, [ebp+arg_4]
.text:0040923F 89 0C 24                                mov     [esp], ecx
.text:00409242 C7 85 C8 FE FF FF FF FF+                mov     [ebp+var_138], 0FFFFFFFFh
.text:0040924C E8 B7 73 01 00                          call    unknown_libname_42 ; GCC (mingw/cygwin) v3.4 runtime
.text:00409251 89 04 24                                mov     [esp], eax      ; char *
.text:00409254 E8 67 3D 01 00                          call    atoi
.text:00409259 89 45 E4                                mov     [ebp+var_1C], eax
;var_1c: 十六进制字符序列表示的用户名转换为数字

.text:0040925C C7 45 E0 AB 00 00 00                    mov     [ebp+var_20], 0ABh
.text:00409263 8B 55 E4                                mov     edx, [ebp+var_1C]
.text:00409266 8D 45 E0                                lea     eax, [ebp+var_20]
.text:00409269 01 10                                   add     [eax], edx      
; var_20 =  var_1c + 0xAB

.text:0040926B C7 45 DC EE EE EE 00                    mov     [ebp+var_24], 0EEEEEEh
.text:00409272 8B 55 E4                                mov     edx, [ebp+var_1C]
.text:00409275 8D 45 DC                                lea     eax, [ebp+var_24]
.text:00409278 01 10                                   add     [eax], edx      
; var_24 = var_1c + 0xEEEEEE

.text:0040927A 8B 55 E4                                mov     edx, [ebp+var_1C]
.text:0040927D 8D 45 E0                                lea     eax, [ebp+var_20]
.text:00409280 89 85 A4 FE FF FF                       mov     [ebp+var_15C], eax
; var_15c = var_20地址

.text:00409286 89 D0                                   mov     eax, edx
.text:00409288 8B 8D A4 FE FF FF                       mov     ecx, [ebp+var_15C]
.text:0040928E 99                                      cdq
.text:0040928F F7 39                                   idiv    dword ptr [ecx]
.text:00409291 89 85 A4 FE FF FF                       mov     [ebp+var_15C], eax
; var_15C = var_1c/var_20的商

.text:00409297 8B 85 A4 FE FF FF                       mov     eax, [ebp+var_15C]
.text:0040929D 89 45 D8                                mov     [ebp+var_28], eax
; var_28 = var_15c

.text:004092A0 8B 55 10                                mov     edx, [ebp+arg_8]
; 序列号第一位

.text:004092A3 8D 45 D8                                lea     eax, [ebp+var_28]
.text:004092A6 01 10                                   add     [eax], edx      
; var_28 = var_28 + 序列号第一位

.text:004092A8 8B 45 10                                mov     eax, [ebp+arg_8]
.text:004092AB 33 45 D8                                xor     eax, [ebp+var_28]
.text:004092AE 89 45 D4                                mov     [ebp+var_2C], eax
; var_2c = 序列号第一位 xor var_28

.text:004092B1 8B 45 D4                                mov     eax, [ebp+var_2C]
.text:004092B4 0F AF 45 DC                             imul    eax, [ebp+var_24]
.text:004092B8 89 45 D4                                mov     [ebp+var_2C], eax
; var_2c = var_2c * var_24

.text:004092BB 8B 55 D8                                mov     edx, [ebp+var_28]
.text:004092BE 83 F2 23                                xor     edx, 23h
.text:004092C1 8D 45 D4                                lea     eax, [ebp+var_2C]
.text:004092C4 01 10                                   add     [eax], edx      
; var_2c = var_2c + (var28 xor 23)

.text:004092C6 8B 45 DC                                mov     eax, [ebp+var_24]
.text:004092C9 03 45 10                                add     eax, [ebp+arg_8]
.text:004092CC 35 8D 83 33 00                          xor     eax, 33838Dh
.text:004092D1 89 45 D0                                mov     [ebp+var_30], eax
; var_30 = (var_24 + 序列号第一位) xor 0x33838D

.text:004092D4 8B 45 E0                                mov     eax, [ebp+var_20]
.text:004092D7 8B 55 10                                mov     edx, [ebp+arg_8]
.text:004092DA 31 C2                                   xor     edx, eax
.text:004092DC 8D 45 D0                                lea     eax, [ebp+var_30]
.text:004092DF 01 10                                   add     [eax], edx      
; var_30 = var_30 +(var_20 xor 序列号第一位)

.text:004092E1 8B 45 10                                mov     eax, [ebp+arg_8]
.text:004092E4 69 C0 EE EE 0E 00                       imul    eax, 0EEEEEh
.text:004092EA 89 85 C0 FE FF FF                       mov     [ebp+var_140], eax
; var_140 = 序列号第一位 * EEEEE

.text:004092F0 8B 55 0C                                mov     edx, [ebp+arg_4]
.text:004092F3 89 14 24                                mov     [esp], edx
.text:004092F6 E8 0D 73 01 00                          call    unknown_libname_42 ; GCC (mingw/cygwin) v3.4 runtime
.text:004092FB 89 04 24                                mov     [esp], eax      ; char *
.text:004092FE E8 BD 3C 01 00                          call    atoi
.text:00409303 03 85 C0 FE FF FF                       add     eax, [ebp+var_140]
.text:00409309 03 45 D0                                add     eax, [ebp+var_30]
.text:0040930C 89 45 CC                                mov     [ebp+var_34], eax
; var_34 = var_1c + var_140 + var_30

.text:0040930F 81 7D D0 A1 14 06 00                    cmp     [ebp+var_30], 614A1h
.text:00409316 7E 23                                   jle     short loc_40933B
; jump if var_30 <= 614a1

.text:00409318 8D 45 D0                                lea     eax, [ebp+var_30]
.text:0040931B 81 00 88 07 00 00                       add     dword ptr [eax], 788h
; var_30 = var_30 + 788

.text:00409321 8B 4D D8                                mov     ecx, [ebp+var_28]
.text:00409324 B8 39 8E E3 38                          mov     eax, 38E38E39h
.text:00409329 F7 E9                                   imul    ecx            
; EDX:EAX = var_28 * 38E38E39

.text:0040932B D1 FA                                   sar     edx, 1         
; EDX/2

.text:0040932D 89 C8                                   mov     eax, ecx
.text:0040932F C1 F8 1F                                sar     eax, 1Fh        
; eax = var_28/2 (重复1F次)

.text:00409332 29 C2                                   sub     edx, eax        
; edx = edx - eax

.text:00409334 8D 45 D0                                lea     eax, [ebp+var_30]
.text:00409337 01 10                                   add     [eax], edx      
; var_30 = var_30 + edx

.text:00409339 EB 22                                   jmp     short loc_40935D
.text:0040933B                         ; ---------------------------------------------------------------------------
.text:0040933B
.text:0040933B                         loc_40933B:                             ; CODE XREF: sub_4091F8+11Ej
.text:0040933B 8B 4D D4                                mov     ecx, [ebp+var_2C]
.text:0040933E B8 01 A0 00 A0                          mov     eax, 0A000A001h
.text:00409343 F7 E9                                   imul    ecx            
.text:00409345 8D 04 0A                                lea     eax, [edx+ecx]
.text:00409348 89 C2                                   mov     edx, eax
.text:0040934A C1 FA 0D                                sar     edx, 0Dh
.text:0040934D 89 C8                                   mov     eax, ecx
.text:0040934F C1 F8 1F                                sar     eax, 1Fh
.text:00409352 29 C2                                   sub     edx, eax
.text:00409354 8B 45 DC                                mov     eax, [ebp+var_24]
.text:00409357 0F AF C2                                imul    eax, edx
.text:0040935A 89 45 DC                                mov     [ebp+var_24], eax
;这里的运算对后面的结果没有影响

.text:0040935D
.text:0040935D                         loc_40935D:                             ; CODE XREF: sub_4091F8+141j
.text:0040935D 8B 4D 08                                mov     ecx, [ebp+arg_0]
.text:00409360 89 0C 24                                mov     [esp], ecx
.text:00409363 C7 85 C8 FE FF FF FF FF+                mov     [ebp+var_138], 0FFFFFFFFh
.text:0040936D E8 96 3F 03 00                          call    unknown_libname_140 ; GCC (mingw/cygwin) v3.4 runtime

经过这些运算,又来到一段代码,看上去是用了一些库函数的:
.text:00409372 C7 44 24 04 08 00 00 00                 mov     dword ptr [esp+4], 8
.text:0040937A C7 04 24 10 00 00 00                    mov     dword ptr [esp], 10h
.text:00409381 E8 CE 57 04 00                          call    sub_44EB54      ; OR
.text:00409386 89 44 24 04                             mov     [esp+4], eax    ; 18h
.text:0040938A 8D 85 08 FF FF FF                       lea     eax, [ebp+var_F8]
.text:00409390 89 04 24                                mov     [esp], eax
.text:00409393 C7 85 C8 FE FF FF 03 00+                mov     [ebp+var_138], 3
.text:0040939D E8 5A F2 03 00                          call    __ZNSt18basic_stringstreamIcSt11char_traitsIcESaIcEEC1ESt13_Ios_Openmode
.text:004093A2 8B 45 CC                                mov     eax, [ebp+var_34]
.text:004093A5 89 44 24 04                             mov     [esp+4], eax
.text:004093A9 8D 85 08 FF FF FF                       lea     eax, [ebp+var_F8] ; var_F8, 每个字符四byte
.text:004093AF 83 C0 08                                add     eax, 8
.text:004093B2 89 04 24                                mov     [esp], eax
.text:004093B5 C7 85 C8 FE FF FF 02 00+                mov     [ebp+var_138], 2
.text:004093BF E8 44 07 03 00                          call    __ZNSolsEl
.text:004093C4 8D 95 F8 FE FF FF                       lea     edx, [ebp+var_108]
.text:004093CA 8D 85 08 FF FF FF                       lea     eax, [ebp+var_F8]
.text:004093D0 89 44 24 04                             mov     [esp+4], eax
.text:004093D4 89 14 24                                mov     [esp], edx
.text:004093D7 E8 1C 87 01 00                          call    __ZNKSt18basic_stringstreamIcSt11char_traitsIcESaIcEE3strEv

先不要跟进去,我们发现在执行完4093D7这里的函数后,var_108就已经指向了结果,因此关键在于这四个call。我们倒过来分析。
可以发现在执行4093D7之前,var_F8+0x10的偏移处的DWORD,就已经指向了最终结果。因此估计var_F8是指向某个结构的指针。
跟进去看4093BF处的call    __ZNSolsEl。
继续深入,来到409DA7,跟进去,来到42AD98:
.text:0042AD98 55                                      push    ebp
.text:0042AD99 89 E5                                   mov     ebp, esp
.text:0042AD9B 83 EC 18                                sub     esp, 18h
.text:0042AD9E 0F BE 45 18                             movsx   eax, [ebp+arg_10]
.text:0042ADA2 8B 55 1C                                mov     edx, [ebp+arg_14]
.text:0042ADA5 89 44 24 10                             mov     [esp+10h], eax
.text:0042ADA9 8B 45 14                                mov     eax, [ebp+arg_C]
.text:0042ADAC 89 54 24 14                             mov     [esp+14h], edx
.text:0042ADB0 8B 55 10                                mov     edx, [ebp+arg_8]
.text:0042ADB3 89 44 24 0C                             mov     [esp+0Ch], eax
.text:0042ADB7 8B 45 0C                                mov     eax, [ebp+arg_4]
.text:0042ADBA 89 54 24 08                             mov     [esp+8], edx
.text:0042ADBE 89 44 24 04                             mov     [esp+4], eax
.text:0042ADC2 8B 45 08                                mov     eax, [ebp+arg_0]
.text:0042ADC5 89 04 24                                mov     [esp], eax
.text:0042ADC8 E8 7B EB FF FF                          call    __ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intIlEES3_S3_RSt8ios_basecT_
.text:0042ADCD C9                                      leave
.text:0042ADCE C3                                      retn
注意看42ADC8的几个参数,其中包括我们前面计算得到的var_34。

继续跟进42ADC8:
.text:00429973 E8 F0 7C FF FF                          call    __ZNKSt11__use_cacheISt16__numpunct_cacheIcEEclERKSt6locale
.text:00429978 8D 50 26                                lea     edx, [eax+26h]
执行完之后,我们发现edx指向了这样一个字符串:
0045A7E6  2D 2B 78 58 30 31 32 33 34 35 36 37 38 39 61 62  -+xX0123456789ab
0045A7F6  63 64 65 66 30 31 32 33 34 35 36 37 38 39 41 42  cdef0123456789AB
0045A806  43 44 45 46 2D 2B 78 58 30 31 32 33 34 35 36 37  CDEF-+xX01234567
0045A816  38 39 61 62 63 64 65 66 41 42 43 44 45 46        89abcdefABCDEF

.text:004299A0 89 1C 24                                mov     [esp], ebx
.text:004299A3 0F B6 C0                                movzx   eax, al
.text:004299A6 89 44 24 10                             mov     [esp+10h], eax
.text:004299AA 8B 45 D0                                mov     eax, [ebp+var_30]
.text:004299AD 89 4C 24 0C                             mov     [esp+0Ch], ecx
.text:004299B1 89 54 24 04                             mov     [esp+4], edx
.text:004299B5 89 44 24 08                             mov     [esp+8], eax
.text:004299B9 E8 7A 2C 02 00                          call    __ZSt13__int_to_charIcmEiPT_T0_PKS0_St13_Ios_Fmtflagsb
.text:004299BE 89 45 E8                                mov     [ebp+var_18], eax
.text:004299C1 89 C3                                   mov     ebx, eax
.text:004299C3 89 F0                                   mov     eax, esi
.text:004299C5 29 D8                                   sub     eax, ebx
.text:004299C7 8D 70 10                                lea     esi, [eax+10h]
在执行完4299B9的函数后,我们发现已经得到了结果,存放在(esi - 长度 + 0x10)的位置, 同时长度保存在var_18的地方。
IDA自动解析的函数名给了很好的提示,就是int转char的函数啦~其实就算没有提示也不复杂,__ZSt13__int_to_charIcmEiPT_T0_PKS0_St13_Ios_Fmtflagsb只有一些运算,没有更多的调用了,仔细分析一下就能得到结果了。

.text:00429A33 89 54 24 08                             mov     [esp+8], edx    ; int
.text:00429A37 8D 45 E8                                lea     eax, [ebp+var_18]
.text:00429A3A 8B 55 DC                                mov     edx, [ebp+var_24]
.text:00429A3D 89 44 24 18                             mov     [esp+18h], eax  ; int
.text:00429A41 8B 45 D8                                mov     eax, [ebp+var_28]
.text:00429A44 8D 5C 24 2F                             lea     ebx, [esp+2Fh]
.text:00429A48 89 74 24 14                             mov     [esp+14h], esi  ; void *
.text:00429A4C 83 E3 F0                                and     ebx, 0FFFFFFF0h
.text:00429A4F 89 DE                                   mov     esi, ebx
.text:00429A51 89 44 24 0C                             mov     [esp+0Ch], eax  ; int
.text:00429A55 0F BE 45 D7                             movsx   eax, [ebp+var_29]
.text:00429A59 89 5C 24 10                             mov     [esp+10h], ebx  ; void *
.text:00429A5D 89 14 24                                mov     [esp], edx      ; int
.text:00429A60 89 44 24 04                             mov     [esp+4], eax    ; char
.text:00429A64 E8 7F 10 00 00                          call    __ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE6_M_padEciRSt8ios_basePcPKcRi
.text:00429A69 8B 5D E8                                mov     ebx, [ebp+var_18]
.text:00429A6C E9 6D FF FF FF                          jmp     loc_4299DE
然后这里,就是把得到的结果复制到输出缓存中。

至此,序列号的计算方法已经分析出来了,就是:
char_mac = 网卡MAC地址去除连接符号后的第4位
char_IP = IP地址第2位
char_hostname = 主机名第1位

arg_8 = atoi(序列号第一位)
var_1c = atoi(用户名十六进制字符串)
var_140 = arg_8 * 0xEEEEE
var_24 = var_1c + 0xEEEEEE
var_20 = var_1c + 0xAB
var_30 = (var_24 + arg_8) xor 0x33838D
var_30 += var_20 xor arg_8
key_int = var_1c + var_140 + var_30

key = char_mac + char_IP + key_int转字符串 + char_hostname

分析完毕~ 好累!具体计算的部分不算复杂,但是干扰的地方好多!


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 5
支持
分享
最新回复 (5)
雪    币: 47147
活跃值: (20445)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
邀请码己短消息你了。
2013-7-10 21:22
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
3
谢谢楼主的分享 邀请码已发
2013-7-10 21:22
0
雪    币: 119
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
你们是不是发了两条邀请码啊...
2013-7-11 04:20
0
雪    币: 3277
活跃值: (1992)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
这个 crack me 原版怎么没有提供下载?
2013-7-11 08:56
0
雪    币: 28
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
一开始提到的原帖里有的
2013-7-11 11:03
0
游客
登录 | 注册 方可回帖
返回
//