昨天发的一个CM的分析过程
本帖最后由 zbnysjwsnd8 于 2016-9-20 20:24 编辑链接:http://www.52pojie.cn/thread-538580-1-1.html
只有@蚯蚓翔龙大神一个人破了,虽然他玩过一次。嘿嘿不过这个CM不是我写的。
有许多人都掉进坑里了,这个CM的密码不是1234124234dlslckel 不过这个CM要想注册成功,有一个前提条件。
打开CM,随便输入一串假的注册码:
失败。我们用OD载入,找到main入口。
程序首先用memset给一些变量赋值:
0040101C|.8DBD A0F7FFFF lea edi, dword ptr
00401022|.B9 18020000 mov ecx, 218
00401027|.B8 CCCCCCCC mov eax, CCCCCCCC
0040102C|.F3:AB rep stosd
0040102E|.C685 00FCFFFF>mov byte ptr , 0
00401035|.B9 FF000000 mov ecx, 0FF
0040103A|.33C0 xor eax, eax
0040103C|.8DBD 01FCFFFF lea edi, dword ptr
00401042|.F3:AB rep stosd
00401044|.66:AB stosw
00401046|.AA stosb
00401047|.C785 FCFBFFFF>mov dword ptr , 0
然后获取kernel32.dll的地址
00401053|.68 C8704200 push 004270C8 ; /FileName = "kernel32.dll"
00401058|.FF15 C0F14200 call dword ptr [<&KERNEL32.LoadLibraryA>>; \LoadLibraryA
继续初始化变量
00401065|.8985 F8FBFFFF mov dword ptr , eax
0040106B|.C685 F8F7FFFF>mov byte ptr , 0
00401072|.B9 FF000000 mov ecx, 0FF
00401077|.33C0 xor eax, eax
00401079|.8DBD F9F7FFFF lea edi, dword ptr
0040107F|.F3:AB rep stosd
00401081|.66:AB stosw
00401083|.AA stosb
00401084|.C785 F4F7FFFF>mov dword ptr , 0
0040108E|.A1 B0704200 mov eax, dword ptr
00401093|.8985 E0F7FFFF mov dword ptr , eax
00401099|.8B0D B4704200 mov ecx, dword ptr
0040109F|.898D E4F7FFFF mov dword ptr , ecx
004010A5|.8B15 B8704200 mov edx, dword ptr
004010AB|.8995 E8F7FFFF mov dword ptr , edx
004010B1|.A1 BC704200 mov eax, dword ptr
004010B6|.8985 ECF7FFFF mov dword ptr , eax
004010BC|.66:8B0D C0704>mov cx, word ptr
004010C3|.66:898D F0F7F>mov word ptr , cx
004010CA|.8A15 C2704200 mov dl, byte ptr
004010D0|.8895 F2F7FFFF mov byte ptr , dl
然后获取IsDebuggerPresent的地址并调用之。
004010E3|.8BF4 mov esi, esp
004010E5|.68 98704200 push 00427098 ; /ProcNameOrOrdinal = "IsDebuggerPresent"
004010EA|.8B85 F8FBFFFF mov eax, dword ptr ; |
004010F0|.50 push eax ; |hModule
004010F1|.FF15 BCF14200 call dword ptr [<&KERNEL32.GetProcAddres>; \GetProcAddress
004010F7|.3BF4 cmp esi, esp ;检查堆栈
004010F9|.E8 92040000 call 00401590
004010FE|.8985 FCFBFFFF mov dword ptr , eax
00401104|.83BD FCFBFFFF>cmp dword ptr , 0
0040110B|.74 7C je short 00401189
0040110D|.8BF4 mov esi, esp
0040110F|.FF95 FCFBFFFF call dword ptr
00401115|.3BF4 cmp esi, esp
00401117|.E8 74040000 call 00401590
如果IsDebuggerPresent的返回值非0,则弹出一个信息框,然后提示输入key
00401122|.6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
00401124|.68 94704200 push 00427094 ; |Title = "哼"
00401129|.68 70704200 push 00427070 ; |Text = "对不起,我怕调试器,萌萌哒!"
0040112E|.6A 00 push 0 ; |hOwner = NULL
00401130|.FF15 04F34200 call dword ptr [<&USER32.MessageBoxA>] ; \MessageBoxA
00401136|.3BF4 cmp esi, esp
00401138|.E8 53040000 call 00401590
0040113D|.68 60704200 push 00427060 ;ASCII "请输入key:
"
00401142|.E8 C9030000 call 00401510
00401147|.83C4 04 add esp, 4
0040114A|.8D8D 00FCFFFF lea ecx, dword ptr
00401150|.51 push ecx
00401151|.68 5C704200 push 0042705C ;ASCII "%s"
00401156|.E8 55030000 call 004014B0
0040115B|.83C4 08 add esp, 8
0040115E|.E9 AC010000 jmp 0040130F
调试器如果不存在,则执行下面的代码:
00401163|> \68 60704200 push 00427060 ;ASCII "请输入key:
"
00401168|.E8 A3030000 call 00401510
0040116D|.83C4 04 add esp, 4
00401170|.8D85 00FCFFFF lea eax, dword ptr
00401176|.50 push eax
00401177|.68 5C704200 push 0042705C ;ASCII "%s"
0040117C|.E8 2F030000 call 004014B0
00401181|.83C4 08 add esp, 8
00401184|.E9 81010000 jmp 0040130A
00401189|>C785 F4F7FFFF>mov dword ptr , 0
00401193|.EB 0F jmp short 004011A4
00401195|>8B95 F4F7FFFF /mov edx, dword ptr
0040119B|.83C2 01 |add edx, 1
0040119E|.8995 F4F7FFFF |mov dword ptr , edx
004011A4|>8B85 F4F7FFFFmov eax, dword ptr
004011AA|.0FBE8C05 E0F7>|movsx ecx, byte ptr
004011B2|.85C9 |test ecx, ecx
004011B4|.74 20 |je short 004011D6
004011B6|.8B95 F4F7FFFF |mov edx, dword ptr
004011BC|.0FBE8415 E0F7>|movsx eax, byte ptr
004011C4|.83E8 02 |sub eax, 2
004011C7|.8B8D F4F7FFFF |mov ecx, dword ptr
004011CD|.88840D F8F7FF>|mov byte ptr , al
004011D4|.^ EB BF \jmp short 00401195
004011D6|>8BF4 mov esi, esp
004011D8|.8D95 F8F7FFFF lea edx, dword ptr
004011DE|.52 push edx ; /String2
004011DF|.8D85 00FCFFFF lea eax, dword ptr ; |
004011E5|.50 push eax ; |String1
004011E6|.FF15 B8F14200 call dword ptr [<&KERNEL32.lstrcmpA>] ; \lstrcmpA
004011EC|.3BF4 cmp esi, esp
004011EE|.E8 9D030000 call 00401590
004011F3|.85C0 test eax, eax
004011F5|.75 63 jnz short 0040125A
004011F7|.C785 F4F7FFFF>mov dword ptr , 0
00401201|.EB 0F jmp short 00401212
00401203|>8B8D F4F7FFFF /mov ecx, dword ptr
00401209|.83C1 01 |add ecx, 1
0040120C|.898D F4F7FFFF |mov dword ptr , ecx
00401212|>8B95 F4F7FFFFmov edx, dword ptr
00401218|.0FBE82 649E42>|movsx eax, byte ptr
0040121F|.85C0 |test eax, eax
00401221|.74 1E |je short 00401241
00401223|.8B8D F4F7FFFF |mov ecx, dword ptr
00401229|.0FBE91 649E42>|movsx edx, byte ptr
00401230|.83EA 02 |sub edx, 2
00401233|.8B85 F4F7FFFF |mov eax, dword ptr
00401239|.8890 649E4200 |mov byte ptr , dl
0040123F|.^ EB C2 \jmp short 00401203
00401241|>68 649E4200 push 00429E64 ;ASCII ""ku"mg{"
00401246|.8D8D 00FCFFFF lea ecx, dword ptr
0040124C|.51 push ecx
0040124D|.68 54704200 push 00427054 ;ASCII "%s%s!
"
00401252|.E8 B9020000 call 00401510
00401257|.83C4 0C add esp, 0C
0040125A|>E9 A9000000 jmp 00401308
0040125F|>C785 F4F7FFFF>mov dword ptr , 0
00401269|.EB 0F jmp short 0040127A
0040126B|>8B95 F4F7FFFF /mov edx, dword ptr
00401271|.83C2 01 |add edx, 1
00401274|.8995 F4F7FFFF |mov dword ptr , edx
0040127A|>8B85 F4F7FFFFmov eax, dword ptr
00401280|.0FBE8C05 E0F7>|movsx ecx, byte ptr
00401288|.85C9 |test ecx, ecx
0040128A|.74 20 |je short 004012AC
0040128C|.8B95 F4F7FFFF |mov edx, dword ptr
00401292|.0FBE8415 E0F7>|movsx eax, byte ptr
0040129A|.83E8 01 |sub eax, 1
0040129D|.8B8D F4F7FFFF |mov ecx, dword ptr
004012A3|.88840D F8F7FF>|mov byte ptr , al
004012AA|.^ EB BF \jmp short 0040126B
004012AC|>8BF4 mov esi, esp
004012AE|.8D95 F8F7FFFF lea edx, dword ptr
004012B4|.52 push edx ; /String2
004012B5|.8D85 00FCFFFF lea eax, dword ptr ; |
004012BB|.50 push eax ; |String1
004012BC|.FF15 B8F14200 call dword ptr [<&KERNEL32.lstrcmpA>] ; \lstrcmpA
004012C2|.3BF4 cmp esi, esp
004012C4|.E8 C7020000 call 00401590
004012C9|.85C0 test eax, eax
004012CB|.74 1F je short 004012EC
004012CD|.8BF4 mov esi, esp
004012CF|.68 40704200 push 00427040 ; /String2 = "1234124234dlslckel"
004012D4|.8D8D 00FCFFFF lea ecx, dword ptr ; |
004012DA|.51 push ecx ; |String1
004012DB|.FF15 B8F14200 call dword ptr [<&KERNEL32.lstrcmpA>] ; \lstrcmpA
004012E1|.3BF4 cmp esi, esp
004012E3|.E8 A8020000 call 00401590
004012E8|.85C0 test eax, eax
004012EA|.74 0D je short 004012F9
004012EC|>68 24704200 push 00427024
004012F1|.E8 1A020000 call 00401510
004012F6|.83C4 04 add esp, 4
我们在00401163处下断点,F9运行。
单步到输入key
00401170|.8D85 00FCFFFF lea eax, dword ptr
00401176|.50 push eax
00401177|.68 5C704200 push 0042705C ;ASCII "%s"
0040117C|.E8 2F030000 call 004014B0
00401181|.83C4 08 add esp, 8
计算错误的注册码并和用户输入的注册码比较,如果想等则提示失败。
00401189|>C785 F4F7FFFF>mov dword ptr , 0
00401193|. |EB 0F jmp short 004011A4
00401195|> |8B95 F4F7FFFF /mov edx, dword ptr
0040119B|. |83C2 01 |add edx, 1
0040119E|. |8995 F4F7FFFF |mov dword ptr , edx
004011A4|> |8B85 F4F7FFFFmov eax, dword ptr
004011AA|. |0FBE8C05 E0F7>|movsx ecx, byte ptr
004011B2|. |85C9 |test ecx, ecx
004011B4|. |74 20 |je short 004011D6
004011B6|. |8B95 F4F7FFFF |mov edx, dword ptr
004011BC|. |0FBE8415 E0F7>|movsx eax, byte ptr
004011C4|. |83E8 02 |sub eax, 2
004011C7|. |8B8D F4F7FFFF |mov ecx, dword ptr
004011CD|. |88840D F8F7FF>|mov byte ptr , al
004011D4|.^|EB BF \jmp short 00401195
004011D6|> |8BF4 mov esi, esp
004011D8|. |8D95 F8F7FFFF lea edx, dword ptr
004011DE|. |52 push edx ; /String2
004011DF|. |8D85 00FCFFFF lea eax, dword ptr ; |
004011E5|. |50 push eax ; |String1
004011E6|. |FF15 B8F14200 call dword ptr [<&KERNEL32.lstrcmpA>] ; \lstrcmpA
004011EC|. |3BF4 cmp esi, esp
004011EE|. |E8 9D030000 call 00401590
004011F3|. |85C0 test eax, eax
004011F5|. |75 63 jnz short 0040125A
004011F7|. |C785 F4F7FFFF>mov dword ptr , 0
00401201|. |EB 0F jmp short 00401212
00401203|> |8B8D F4F7FFFF /mov ecx, dword ptr
00401209|. |83C1 01 |add ecx, 1
0040120C|. |898D F4F7FFFF |mov dword ptr , ecx
00401212|> |8B95 F4F7FFFFmov edx, dword ptr
00401218|. |0FBE82 649E42>|movsx eax, byte ptr
0040121F|. |85C0 |test eax, eax
00401221|. |74 1E |je short 00401241
00401223|. |8B8D F4F7FFFF |mov ecx, dword ptr
00401229|. |0FBE91 649E42>|movsx edx, byte ptr
00401230|. |83EA 02 |sub edx, 2
00401233|. |8B85 F4F7FFFF |mov eax, dword ptr
00401239|. |8890 649E4200 |mov byte ptr , dl
0040123F|.^|EB C2 \jmp short 00401203
00401241|> |68 649E4200 push 00429E64 ;ASCII ""ku"mg{"
00401246|. |8D8D 00FCFFFF lea ecx, dword ptr
0040124C|. |51 push ecx
0040124D|. |68 54704200 push 00427054 ;ASCII "%s%s!
"
00401252|. |E8 B9020000 call 00401510
00401257|. |83C4 0C add esp, 0C
0040125A|> |E9 A9000000 jmp 00401308
0040125F|> |C785 F4F7FFFF>mov dword ptr , 0
00401269|. |EB 0F jmp short 0040127A
0040126B|> |8B95 F4F7FFFF /mov edx, dword ptr
00401271|. |83C2 01 |add edx, 1
00401274|. |8995 F4F7FFFF |mov dword ptr , edx
0040127A|> |8B85 F4F7FFFFmov eax, dword ptr
00401280|. |0FBE8C05 E0F7>|movsx ecx, byte ptr
00401288|. |85C9 |test ecx, ecx
0040128A|. |74 20 |je short 004012AC
0040128C|. |8B95 F4F7FFFF |mov edx, dword ptr
00401292|. |0FBE8415 E0F7>|movsx eax, byte ptr
0040129A|. |83E8 01 |sub eax, 1
0040129D|. |8B8D F4F7FFFF |mov ecx, dword ptr
004012A3|. |88840D F8F7FF>|mov byte ptr , al
004012AA|.^|EB BF \jmp short 0040126B
004012AC|> |8BF4 mov esi, esp
004012AE|. |8D95 F8F7FFFF lea edx, dword ptr
004012B4|. |52 push edx ; /String2
004012B5|. |8D85 00FCFFFF lea eax, dword ptr ; |
004012BB|. |50 push eax ; |String1
004012BC|. |FF15 B8F14200 call dword ptr [<&KERNEL32.lstrcmpA>] ; \lstrcmpA
004012C2|. |3BF4 cmp esi, esp
004012C4|. |E8 C7020000 call 00401590
004012C9|. |85C0 test eax, eax
004012CB|. |74 1F je short 004012EC
004012CD|. |8BF4 mov esi, esp
004012CF|. |68 40704200 push 00427040 ; /String2 = "1234124234dlslckel"
004012D4|. |8D8D 00FCFFFF lea ecx, dword ptr ; |
004012DA|. |51 push ecx ; |String1
004012DB|. |FF15 B8F14200 call dword ptr [<&KERNEL32.lstrcmpA>] ; \lstrcmpA
计算并用用户输入的注册码比较一个错误的注册码:
0040125F|> /C785 F4F7FFFF>mov dword ptr , 0
00401269|. |EB 0F jmp short 0040127A
0040126B|> |8B95 F4F7FFFF /mov edx, dword ptr
00401271|. |83C2 01 |add edx, 1
00401274|. |8995 F4F7FFFF |mov dword ptr , edx
0040127A|> |8B85 F4F7FFFFmov eax, dword ptr
00401280|. |0FBE8C05 E0F7>|movsx ecx, byte ptr ;获取一个固定的字符串
00401288|. |85C9 |test ecx, ecx ;获取出的字符是否是0
0040128A|. |74 20 |je short 004012AC ;是则跳转
0040128C|. |8B95 F4F7FFFF |mov edx, dword ptr
00401292|. |0FBE8415 E0F7>|movsx eax, byte ptr ;获取一个固定的字符串
0040129A|. |83E8 01 |sub eax, 1 ;ASCII码减1
0040129D|. |8B8D F4F7FFFF |mov ecx, dword ptr
004012A3|. |88840D F8F7FF>|mov byte ptr , al ;保存
004012AA|.^|EB BF \jmp short 0040126B
004012AC|> |8BF4 mov esi, esp
004012AE|. |8D95 F8F7FFFF lea edx, dword ptr
004012B4|. |52 push edx ; /String2
004012B5|. |8D85 00FCFFFF lea eax, dword ptr ; |
004012BB|. |50 push eax ; |String1
004012BC|. |FF15 B8F14200 call dword ptr [<&KERNEL32.lstrcmpA>] ; \lstrcmpA
004012C2|. |3BF4 cmp esi, esp
004012C4|. |E8 C7020000 call 00401590
004012C9|. |85C0 test eax, eax ;如果用户输入的注册码和计算出来的注册码相等
004012CB|. |74 1F je short 004012EC ;失败
004012EC|> \68 24704200 push 00427024
004012F1|.E8 1A020000 call 00401510
004012F6|.83C4 04 add esp, 4
004012F9|>68 1C704200 push 0042701C ;ASCII "pause"
004012FE|.E8 9D000000 call 004013A0
00401303|.83C4 04 add esp, 4
用一个看似正确的注册码和用户输入的注册码比较,如果成功则什么都不提示。(还是失败)
004012CF|.68 40704200 push 00427040 ; /String2 = "1234124234dlslckel"
004012D4|.8D8D 00FCFFFF lea ecx, dword ptr ; |
004012DA|.51 push ecx ; |String1
004012DB|.FF15 B8F14200 call dword ptr [<&KERNEL32.lstrcmpA>] ; \lstrcmpA
004012E1|.3BF4 cmp esi, esp
004012E3|.E8 A8020000 call 00401590
004012E8|.85C0 test eax, eax ;用一个看似正确的注册码和用户输入的注册码比较
004012EA|.74 0D je short 004012F9
004012F9|>68 1C704200 push 0042701C ;ASCII "pause"
004012FE|. |E8 9D000000 call 004013A0
00401303|. |83C4 04 add esp, 4
这样,我们就知道了。第一个IsDebuggerPresent不能让他跳走,否则就不会有正确的注册码。
0040111E 90 nop
0040111F 90 nop
00401120|.8BF4 mov esi, esp
00401122|.6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
00401124|.68 94704200 push 00427094 ; |Title = "哼"
00401129|.68 70704200 push 00427070 ; |Text = "对不起,我怕调试器,萌萌哒!"
0040112E|.6A 00 push 0 ; |hOwner = NULL
00401130|.FF15 04F34200 call dword ptr [<&USER32.MessageBoxA>] ; \MessageBoxA
如果不想弹出信息框,可以这样:
00401120 .8BF4 mov esi, esp
00401122 .6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
00401124 .68 94704200 push 00427094 ; |Title = "哼"
00401129 .68 70704200 push 00427070 ; |Text = "对不起,我怕调试器,萌萌哒!"
0040112E .6A 01 push 1 ; |hOwner = 00000001
00401130 .FF15 04F34200 call dword ptr [<&USER32.MessageBoxA>] ; \MessageBoxA
输入key的前面已经说过了,这里不再陈述。
计算正确的注册码:
00401189 >C785 F4F7FFFF>mov dword ptr , 0
00401193 . |EB 0F jmp short 004011A4
00401195 > |8B95 F4F7FFFF mov edx, dword ptr ;和之前的计算假,码的算法差不多
0040119B . |83C2 01 add edx, 1
0040119E . |8995 F4F7FFFF mov dword ptr , edx
004011A4 > |8B85 F4F7FFFF mov eax, dword ptr
004011AA . |0FBE8C05 E0F7>movsx ecx, byte ptr
004011B2 . |85C9 test ecx, ecx
004011B4 . |74 20 je short 004011D6
004011B6 . |8B95 F4F7FFFF mov edx, dword ptr
004011BC . |0FBE8415 E0F7>movsx eax, byte ptr
004011C4 . |83E8 02 sub eax, 2 ;这里不是减1而是减2了
004011C7 . |8B8D F4F7FFFF mov ecx, dword ptr
004011CD . |88840D F8F7FF>mov byte ptr , al ;存放结果
004011D4 .^|EB BF jmp short 00401195
用用户输入的注册码和计算出来的正确注册码比较:
004011D8 .8D95 F8F7FFFF lea edx, dword ptr
004011DE .52 push edx ; /String2
004011DF .8D85 00FCFFFF lea eax, dword ptr ; |
004011E5 .50 push eax ; |String1
004011E6 .FF15 B8F14200 call dword ptr [<&KERNEL32.lstrcmpA>] ; \lstrcmpA
我这里输入的注册码是123,堆栈中出现正确的注册码了:
0012F708 004011EC/CALL 到 lstrcmpA 来自 360CM.004011E6
0012F70C 0012FB80|String1 = "123"
0012F710 0012F778\String2 = "jiongmeiissolovely"
输出信息:
004011F5 . /75 63 jnz short 0040125A
004011F7 . |C785 F4F7FFFF>mov dword ptr , 0
00401201 . |EB 0F jmp short 00401212
00401203 > |8B8D F4F7FFFF mov ecx, dword ptr
00401209 . |83C1 01 add ecx, 1
0040120C . |898D F4F7FFFF mov dword ptr , ecx
00401212 > |8B95 F4F7FFFF mov edx, dword ptr
00401218 . |0FBE82 649E42>movsx eax, byte ptr
0040121F . |85C0 test eax, eax
00401221 . |74 1E je short 00401241
00401223 . |8B8D F4F7FFFF mov ecx, dword ptr
00401229 . |0FBE91 649E42>movsx edx, byte ptr
00401230 . |83EA 02 sub edx, 2
00401233 . |8B85 F4F7FFFF mov eax, dword ptr
00401239 . |8890 649E4200 mov byte ptr , dl
0040123F .^|EB C2 jmp short 00401203
00401241 > |68 649E4200 push 00429E64 ;ASCII ""ku"mg{"
00401246 . |8D8D 00FCFFFF lea ecx, dword ptr
0040124C . |51 push ecx
0040124D . |68 54704200 push 00427054 ;ASCII "%s%s!
"
00401252 . |E8 B9020000 call 00401510
00401257 . |83C4 0C add esp, 0C
这个输出信息的算法和之前的也是差不多的,这里就不再分析了。
这回先把修改的代码保存,然后输入得到的注册码:
成功!
附:函数尾
00401306|. /EB 0C jmp short 00401314
00401308|>^|EB EF jmp short 004012F9
0040130A|>^|E9 50FFFFFF jmp 0040125F
0040130F|>^|E9 75FEFFFF jmp 00401189
00401314|> \5F pop edi
00401315|.5E pop esi
00401316|.5B pop ebx
00401317|.81C4 60080000 add esp, 860
0040131D|.3BEC cmp ebp, esp
0040131F|.E8 6C020000 call 00401590
00401324|.8BE5 mov esp, ebp
00401326|.5D pop ebp
00401327\.C3 retn
贴图就好了就生动了 感谢楼主的分析,有时间下载下来学习下。 看一看 瞧一瞧 感谢 分享!最近刚好在学这方面的东西! 谢谢分享 学习算法分析中..谢谢非常有用! 牛X的楼主, 还可以这样挖地坑, 学习了! 可以 分析的很详细,赞! Sound 发表于 2016-9-24 00:29
可以 分析的很详细,赞!
谢谢大大的鼓励
页:
[1]
2