【本人闭关修炼多时,今日出关,自己写个CrackME,求破解】
原帖地址:
http://bbs.pediy.com/showthread.php?t=100666
CrackMe下载来之后,解压运行,弹出窗口,胡乱输入用户名和密码,点”OK”,结果没有反映,一看就是不想给破解者任何线索,给MessageBox下断看样子是不行了。
楼主说没有加壳,还是用PEID查了一下,真没壳,应该是用MFC写的。
OD载入,F9运行,程序一闪而过,OD也关闭了,再看程序自我删除了,毫无疑问,有反跟踪,于是用HideOD插件隐藏OD,一试还是不行,难道是专门针对OD的?结果在程序的数据中发现了如下的字符串:DBG.OLLY
这下可以肯定是查找窗口。原因是找到了,但是我却不会解决,于是就只能学着回帖的那些高手把OD附加到CM的进程上,给GetDlgItemA下断,慢慢跟着程序走:
00401AEB . 33C9 xor ecx, ecx
00401AED . 33C0 xor eax, eax
00401AEF > 0FBEB40C 4001>movsx esi, byte ptr [esp+ecx+140]
00401AF7 . 33D2 xor edx, edx
00401AF9 . 8A9404 980000>mov dl, byte ptr [esp+eax+98]
00401B00 . 3BD6 cmp edx, esi
00401B02 . 75 2A jnz short 00401B2E //关键跳转
00401B04 . 33D2 xor edx, edx
00401B06 . 8A5404 50 mov dl, byte ptr [esp+eax+50]
00401B0A . 03CA add ecx, edx
00401B0C . 40 inc eax
00401B0D . 83F8 20 cmp eax, 20
00401B10 .^ 7C DD jl short 00401AEF
00401B12 . A1 AC404000 mov eax, dword ptr [4040AC]
00401B17 . 8B5424 10 mov edx, dword ptr [esp+10]
00401B1B . 8B0D A8404000 mov ecx, dword ptr [4040A8] ; CrackMe.004040C4
00401B21 . 53 push ebx ; /Style
00401B22 . 50 push eax ; |Title => "恭?,B2,""
00401B23 . 8B42 20 mov eax, dword ptr [edx+20] ; |
00401B26 . 51 push ecx ; |Text => "哇?,AC,"?,AB,"帅了?,AC,"过?,B4,"让我?,D7,"?,BB,"",B8,"觯",A1,""
00401B27 . 50 push eax ; |hOwner
00401B28 . FF15 48324000 call dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
00401B02为关键跳转,改为JZ,保存到可执行文件,关闭OD,运行,还是删除了。(内牛满面…
)可以肯定是有自校验。后头看看那些高手的回帖,人家直接就爆破了,自己就跟着别人的步骤,也发现了程序的密码是明码比较,不过保存的方式和以前学习中的那些程序有所不同,至于MD5算法,吾菜鸟一个,看不明白。
这个24K的程序,反跟踪加上自校验让我一点办法都没有,24k啊,果然纯度很高。由于代码不是很长,就用OD载入,静态的在那里分析,找到CreatFileA后的条件跳转,改为无条件跳转JMP,结果还是一样的悲剧。遂在原帖中问这个自校验怎么破,没有高手愿意教我这个菜鸟。于是这个问题一直困扰着我,我却毫无办法。
昨天看新手区突然你看见有人破这个CM,赶紧进去看看,咦!PhantOM?什么东西?自己在OD里面弄开一看,震惊的发现里面有个“change Olly caption”,立马选中,保存。载入CM,OD的窗口标题果然变了,F9运行,顺利弹出窗口,心情激动啊!结果死机了,没办法,重启再试,还是死了,难道是系统的问题?(我用的window 7,不要喷我~)就换到同学的XP上面运行,OK!一切顺利。这里感谢ID为青风的这位同学,让我又学会了OD的一个重要的插件的使用。
原帖地址:
http://bbs.pediy.com/showthread.php?t=100925
载入CM,“Ctrl+G”找到CreatFileA,F2下断,F9运行,Alt+F9回到程序领空:
00401295 |. 8D8424 140100>lea eax, dword ptr [esp+114]
0040129C |. 68 00010000 push 100 ; /BufSize = 100 (256.)
004012A1 |. 50 push eax ; |PathBuffer
004012A2 |. 6A 00 push 0 ; |hModule = NULL
004012A4 |. FF15 14304000 call dword ptr [<&KERNEL32.GetModuleF>; \GetModuleFileNameA
004012AA |. 6A 00 push 0 ; /hTemplateFile = NULL
004012AC |. 68 80000000 push 80 ; |Attributes = NORMAL
004012B1 |. 6A 03 push 3 ; |Mode = OPEN_EXISTING
004012B3 |. 6A 00 push 0 ; |pSecurity = NULL
004012B5 |. 6A 01 push 1 ; |ShareMode = FILE_SHARE_READ
004012B7 |. 8D8C24 280100>lea ecx, dword ptr [esp+128] ; |
004012BE |. 68 00000080 push 80000000 ; |Access = GENERIC_READ
004012C3 |. 51 push ecx ; |FileName
004012C4 |. FF15 20304000 call dword ptr [<&KERNEL32.CreateFile>; \CreateFileA
004012CA |. 8BF0 mov esi, eax //回到这里
004012CC |. 83FE FF cmp esi, -1
004012CF |. 75 0D jnz short 004012DE //跳转实现,跳到004012DE
004012D1 |. 5F pop edi
004012D2 |. 5E pop esi
004012D3 |. 5D pop ebp
004012D4 |. 33C0 xor eax, eax
004012D6 |. 5B pop ebx
004012D7 |. 81C4 1C030000 add esp, 31C
004012DD |. C3 retn
004012DE |> \8D5424 10 lea edx, dword ptr [esp+10] //跳转来自004012CF
004012E2 |. 52 push edx ; /pFileSizeHigh
004012E3 |. 56 push esi ; |hFile
004012E4 |. FF15 1C304000 call dword ptr [<&KERNEL32.GetFileSiz>; \GetFileSize
004012EA |. 56 push esi ; /hObject
004012EB |. 8BF8 mov edi, eax ; |
004012ED |. FF15 18304000 call dword ptr [<&KERNEL32.CloseHandl>; \CloseHandle
004012F3 |. 81FF 00600000 cmp edi, 6000
004012F9 |. 74 12 je short 0040130D
004012FB |. E8 B0FDFFFF call 004010B0 //执行的话关自己关OD并自我删除
00401300 |. 5F pop edi
00401301 |. 5E pop esi
00401302 |. 5D pop ebp
00401303 |. 33C0 xor eax, eax
00401305 |. 5B pop ebx
00401306 |. 81C4 1C030000 add esp, 31C
0040130C |. C3 retn
发现004012F9 |. 74 12 je short 0040130D为关键跳转,不跳的话,下一条的call 004010B0就是我们Cracker的悲剧,je改为jmp无条件跳转,保存,运行,结果还是不行,看来自校验不止这一处。将改过的程序再保存,OD载入,现在就开始了两个程序的比较了。结果上面004012F9处的跳转一样,应该不用改成jmp。继续F8:
0040130D |> \8D8424 140200>lea eax, dword ptr [esp+214]
00401314 |. 8D8C24 140100>lea ecx, dword ptr [esp+114]
0040131B |. 50 push eax
0040131C |. 51 push ecx
0040131D |. E8 0E180000 call <jmp.&MFC42.#3790_CFile::GetStat>
00401322 |. 85C0 test eax, eax
00401324 |. 0F84 A6000000 je 004013D0
0040132A |. 6A 00 push 0
0040132C |. 8D8C24 1C0200>lea ecx, dword ptr [esp+21C]
00401333 |. E8 F2170000 call <jmp.&MFC42.#3337_CTime::GetLoca>
00401338 |. 8B50 14 mov edx, dword ptr [eax+14]
0040133B |. 81C2 6C070000 add edx, 76C
00401341 |. 81FA D9070000 cmp edx, 7D9
00401347 |. 74 12 je short 0040135B //此处跳转依旧一样,跳转实现
00401349 |. E8 62FDFFFF call 004010B0
0040134E |. 5F pop edi
0040134F |. 5E pop esi
00401350 |. 5D pop ebp
00401351 |. 33C0 xor eax, eax
00401353 |. 5B pop ebx
00401354 |. 81C4 1C030000 add esp, 31C
0040135A |. C3 retn
0040135B |> \6A 00 push 0 //跳转来自00401347
0040135D |. 8D8C24 1C0200>lea ecx, dword ptr [esp+21C]
00401364 |. E8 C1170000 call <jmp.&MFC42.#3337_CTime::GetLoca>
00401369 |. 8B40 10 mov eax, dword ptr [eax+10]
0040136C |. 40 inc eax
0040136D |. 83F8 0B cmp eax, 0B
00401370 |. 74 12 je short 00401384 //跳转相同
00401372 |. E8 39FDFFFF call 004010B0
00401377 |. 5F pop edi
00401378 |. 5E pop esi
00401379 |. 5D pop ebp
0040137A |. 33C0 xor eax, eax
0040137C |. 5B pop ebx
0040137D |. 81C4 1C030000 add esp, 31C
00401383 |. C3 retn
00401384 |> \6A 00 push 0
00401386 |. 8D8C24 1C0200>lea ecx, dword ptr [esp+21C]
0040138D |. E8 98170000 call <jmp.&MFC42.#3337_CTime::GetLocalTm>
00401392 |. 8378 0C 04 cmp dword ptr [eax+C], 4
00401396 74 12 je short 004013AA //不同的跳转出现
00401398 |. E8 13FDFFFF call 004010B0
0040139D |. 5F pop edi
0040139E |. 5E pop esi
0040139F |. 5D pop ebp
004013A0 |. 33C0 xor eax, eax
004013A2 |. 5B pop ebx
004013A3 |. 81C4 1C030000 add esp, 31C
004013A9 |. C3 retn
00401396处终于发现了不同的跳转,赶紧改为jmp,一想到可能还有别的校验地方,先记下这个地址,重新载入改过的CM继续比较:
004013AA |> 6A 00 push 0
004013AC |. 8D8C24 1C0200>lea ecx, dword ptr [esp+21C]
004013B3 |. E8 72170000 call <jmp.&MFC42.#3337_CTime::GetLocalTm>
004013B8 |. 8378 08 17 cmp dword ptr [eax+8], 17
004013BC |. 74 12 je short 004013D0 //跳转不同,跳到GetWindow
004013BE |. E8 EDFCFFFF call 004010B0
004013C3 |. 5F pop edi
004013C4 |. 5E pop esi
004013C5 |. 5D pop ebp
004013C6 |. 33C0 xor eax, eax
004013C8 |. 5B pop ebx
004013C9 |. 81C4 1C030000 add esp, 31C
004013CF |. C3 retn
004013BC改为jmp short 004013D0,保存,运行,还是不行,继续看:
004013D0 |> \FF15 54324000 call dword ptr [<&USER32.GetDesktopWindow>] ; [GetDesktopWindow
004013D6 |. 6A 05 push 5 ; /Relation = GW_CHILD
004013D8 |. 50 push eax ; |hWnd
004013D9 |. FF15 58324000 call dword ptr [<&USER32.GetWindow>] ; \GetWindow
004013DF |. 8BE8 mov ebp, eax
004013E1 |. B9 3F000000 mov ecx, 3F
004013E6 |. 33C0 xor eax, eax
004013E8 |. 8D7C24 15 lea edi, dword ptr [esp+15]
004013EC |. C64424 14 00 mov byte ptr [esp+14], 0
004013F1 |. F3:AB rep stos dword ptr es:[edi]
004013F3 |. 66:AB stos word ptr es:[edi]
004013F5 |. 85ED test ebp, ebp
004013F7 |. AA stos byte ptr es:[edi]
004013F8 |. 0F84 81000000 je 0040147F
004013FE |. 8B1D 0C324000 mov ebx, dword ptr [<&MSVCRT.toupper>] ; msvcrt.toupper
00401404 |> 8D4C24 14 /lea ecx, dword ptr [esp+14]
00401408 |. 68 00010000 |push 100 ; /Count = 100 (256.)
0040140D |. 51 |push ecx ; |Buffer
0040140E |. 55 |push ebp ; |hWnd
0040140F |. FF15 64324000 |call dword ptr [<&USER32.GetWindowTextA>] ; \GetWindowTextA
00401415 |. 8D7C24 14 |lea edi, dword ptr [esp+14]
00401419 |. 83C9 FF |or ecx, FFFFFFFF
0040141C |. 33C0 |xor eax, eax
0040141E |. F2:AE |repne scas byte ptr es:[edi]
00401420 |. F7D1 |not ecx
00401422 |. 49 |dec ecx
00401423 |. 8BF9 |mov edi, ecx
00401425 |. 74 49 |je short 00401470
00401427 |. 33F6 |xor esi, esi
00401429 |. 85FF |test edi, edi
0040142B |. 7E 14 |jle short 00401441
0040142D |> 0FBE5434 14 |/movsx edx, byte ptr [esp+esi+14]
00401432 |. 52 ||push edx
00401433 |. FFD3 ||call ebx
00401435 |. 83C4 04 ||add esp, 4
00401438 |. 884434 14 ||mov byte ptr [esp+esi+14], al
0040143C |. 46 ||inc esi
0040143D |. 3BF7 ||cmp esi, edi
0040143F |.^ 7C EC |\jl short 0040142D
00401441 |> A1 20404000 |mov eax, dword ptr [404020]
00401446 |. 8B35 10324000 |mov esi, dword ptr [<&MSVCRT.strstr>] ; msvcrt.strstr
0040144C |. 8D4C24 14 |lea ecx, dword ptr [esp+14]
00401450 |. 50 |push eax ; /s2 => "OLLY"
00401451 |. 51 |push ecx ; |s1
00401452 |. FFD6 |call esi ; \strstr
00401454 |. 83C4 08 |add esp, 8
00401457 |. 85C0 |test eax, eax
00401459 75 34 jnz short 0040148F
0040145B |. 8B15 24404000 |mov edx, dword ptr [404024] ; CrackMe.00404028
00401461 |. 8D4424 14 |lea eax, dword ptr [esp+14]
00401465 |. 52 |push edx
00401466 |. 50 |push eax
00401467 |. FFD6 |call esi
00401469 |. 83C4 08 |add esp, 8
0040146C |. 85C0 |test eax, eax
0040146E 75 1F jnz short 0040148F
00401470 |> 6A 02 |push 2 ; /Relation = GW_HWNDNEXT
00401472 |. 55 |push ebp ; |hWnd
00401473 |. FF15 58324000 |call dword ptr [<&USER32.GetWindow>] ; \GetWindow
00401479 |. 8BE8 |mov ebp, eax
0040147B |. 85ED |test ebp, ebp
0040147D |.^ 75 85 \jnz short 00401404
0040147F |> 5F pop edi
00401480 |. 5E pop esi
00401481 |. 5D pop ebp
00401482 |. B8 01000000 mov eax, 1
00401487 |. 5B pop ebx
00401488 |. 81C4 1C030000 add esp, 31C
0040148E |. C3 retn
0040148F |> E8 1CFCFFFF call 004010B0
00401494 |. 6A 00 push 0 ; /lParam = 0
00401496 |. 6A 00 push 0 ; |wParam = 0
00401498 |. 6A 10 push 10 ; |Message = WM_CLOSE
0040149A |. 55 push ebp ; |hWnd
0040149B |. FF15 60324000 call dword ptr [<&USER32.PostMessageA>] ; \PostMessageA
004014A1 |. 5F pop edi
004014A2 |. 5E pop esi
004014A3 |. 5D pop ebp
004014A4 |. 33C0 xor eax, eax
004014A6 |. 5B pop ebx
004014A7 |. 81C4 1C030000 add esp, 31C
004014AD \. C3 retn
现在来到了OD的查找代码区了,不过这个和自校验貌似没有什么关系,应该还在别的地方校验,不急,先把这里面的改了再说,00401459 和0040146E处的jnz short 0040148F都改为jmp short 0040148F,后面的一直跟着没有发现不同之处。可是为什么会出问题呢?先保存。这次把OD关闭了,试着运行了一下,居然成功了,又试了下那个只改了00401396和004013BC处跳转的程序,也成功了,看样子调试中的CM貌似对这个有影响。具体在哪里?目前菜鸟的我还发现不了。
跟着最后的004014AD \. C3 retn 返回到:
004014CB E8 A0FDFFFF call 00401270
004014D0 . 85C0 test eax, eax //返回在此处
004014D2 75 17 jnz short 004014EB
004014D4 . E8 D7FBFFFF call 004010B0
根据004014A4 |. 33C0 xor eax, eax处,eax清零,故test eax, eax的ZF=1,现在回到上面看到:
0040147F |> \5F pop edi
00401480 |. 5E pop esi
00401481 |. 5D pop ebp
00401482 |. B8 01000000 mov eax, 1
00401487 |. 5B pop ebx
00401488 |. 81C4 1C030000 add esp, 31C
0040148E |. C3 retn
难道是00401482 |. B8 01000000 mov eax, 1在影响,改为mov eax, 0保存试试。开着OD还是悲剧了,怒了!
这样一处一处的改不是办法,得从根源上把问题给解决了:
004014CB E8 A0FDFFFF call 00401270
004014D0 . 85C0 test eax, eax //返回在此处
004014D2 75 17 jnz short 004014EB
004014D4 . E8 D7FBFFFF call 004010B0
此时从头看我们不难发现,自校验和查找OD都从call 00401270开始的,这下happy了,直接nop掉,再把jnz short 004014EB 改为jmp short 004014EB,保存,运行,成功!oh YEAH!!~
到这里,这个CM的自校验和反跟踪算是破掉了。(不容易啊,还是自己水平太低了。)剩下的密码的爆破就简单了很多了,00401B02 . 75 2A jnz short 00401B2E处的jnz改为jz就行了。
至于要写出注册机,还是得等自己把加密算法研究了以后再练习吧。至于密码验证的过程,请参考青云同学的帖子。
至此,这个CM的爆破算是基本完成了,作者设计的自校验是针对于文件大小和系统时间,不过文件由于没有加壳,此处的文件大小比较貌似没有起到什么作用。
自己第一次写破文,不足之处还希望大家多多指正。好了,再次感谢CM作者和青云同学,是你们让我又学会了一些东西,也感谢看雪给了我这样一个学习的平台。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
上传的附件: