【文章标题】: robin97's CRACKME逆向
【文章作者】: llydd
【作者邮箱】: llydd@163.com
【下载地址】: http://www.skyheart.com.cn/up/CrackME1.rar
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
发现程序要使用test文件,那么我们在CreateFile函数处断点
00403041 call dword ptr ds:[<&KERNEL32.CreateFileA>] ;F9后程序在此处断下
00403047 cmp esi,esp
00403049 call <jmp.&MSVCRTD._chkesp>
0040304E mov dword ptr ss:[ebp-14],eax
00403051 cmp dword ptr ss:[ebp-14],-1
00403055 jnz short 00403079 ;文件打开成功则跳
00403079 mov esi,esp
0040307B lea eax,dword ptr ss:[ebp-18]
0040307E push eax ; /pFileSizeHigh
0040307F mov ecx,dword ptr ss:[ebp-14] ; |
00403082 push ecx ; |hFile
00403083 call dword ptr ds:[<&KERNEL32.GetFileSize>] ; \GetFileSize
00403089 cmp esi,esp
0040308B call <jmp.&MSVCRTD._chkesp>
00403090 mov dword ptr ss:[ebp-1C],eax
00403093 mov esi,esp
00403095 push 40 ; /Protect = PAGE_EXECUTE_READWRITE
00403097 push 1000 ; |AllocationType = MEM_COMMIT
0040309C push 100000 ; |Size = 100000 (1048576.)
004030A1 push 0 ; |Address = NULL
004030A3 call dword ptr ds:[<&KERNEL32.VirtualAlloc>] ; 在处分配的存储区用来存放解密后的代码,我们称它为BUF1
004030A9 cmp esi,esp
004030AB call <jmp.&MSVCRTD._chkesp>
004030B0 mov dword ptr ss:[ebp-20],eax
004030B3 mov esi,esp
004030B5 push 4 ; /Protect = PAGE_READWRITE
004030B7 push 1000 ; |AllocationType = MEM_COMMIT
004030BC mov edx,dword ptr ss:[ebp-1C] ; |
004030BF push edx ; |Size
004030C0 push 0 ; |Address = NULL
004030C2 call dword ptr ds:[<&KERNEL32.VirtualAlloc>] ; 在此处分配的存储区用来存放解密前的代码,我们称它为BUF2
004030C8 cmp esi,esp
004030CA call <jmp.&MSVCRTD._chkesp>
004030CF mov dword ptr ss:[ebp-24],eax
004030D2 mov byte ptr ss:[ebp-44],0
004030D6 mov ecx,7
004030DB xor eax,eax
004030DD lea edi,dword ptr ss:[ebp-43]
004030E0 rep stos dword ptr es:[edi]
004030E2 stos word ptr es:[edi]
004030E4 stos byte ptr es:[edi]
004030E5 mov esi,esp
004030E7 push 0 ; /pOverlapped = NULL
004030E9 lea eax,dword ptr ss:[ebp-48] ; |
004030EC push eax ; |pBytesRead
004030ED mov ecx,dword ptr ss:[ebp-1C] ; |
004030F0 push ecx ; |BytesToRead
004030F1 mov edx,dword ptr ss:[ebp-24] ; |
004030F4 push edx ; |Buffer
004030F5 mov eax,dword ptr ss:[ebp-14] ; |
004030F8 push eax ; |hFile
004030F9 call dword ptr ds:[<&KERNEL32.ReadFile>] ; 将test读到BUF2中
004030FF cmp esi,esp
00403101 call <jmp.&MSVCRTD._chkesp>
00403106 test eax,eax
00403108 jnz short 0040312C ;读成功则跳
0040312C lea ecx,dword ptr ss:[ebp-44]
0040312F push ecx
00403130 mov edx,dword ptr ss:[ebp-1C]
00403133 push edx
00403134 mov eax,dword ptr ss:[ebp-24]
00403137 push eax
00403138 mov ecx,dword ptr ss:[ebp-20]
0040313B push ecx
0040313C call 0040114F ;此处将要解密test文件中内容
00403141 add esp,10
00403144 mov dword ptr ss:[ebp-4C],eax
00403147 push 0
00403149 lea ecx,dword ptr ss:[ebp-B0]
0040314F call 004010A0
00403154 mov dword ptr ss:[ebp-4],0
0040315B lea ecx,dword ptr ss:[ebp-B0]
00403161 call <jmp.&MFC42D.#1862>
00403166 lea ecx,dword ptr ss:[ebp-50]
00403169 call <jmp.&MFC42D.#880>
0040316E mov dword ptr ss:[ebp-B4],eax
00403174 mov eax,dword ptr ss:[ebp-4C]
00403177 push esi
00403178 push edi
00403179 mov ebx,dword ptr ss:[ebp-B4]
0040317F push ebx
00403180 call eax ; 调用解密产生的代码,用来判断是否为正确注册码
00401900 push ebp
00401901 mov ebp,esp
00401903 sub esp,4C
00401906 push ebx
00401907 push esi
00401908 push edi
00401909 lea edi,dword ptr ss:[ebp-4C]
0040190C mov ecx,13
00401911 mov eax,CCCCCCCC
00401916 rep stos dword ptr es:[edi]
00401918 mov eax,dword ptr ss:[ebp+10]
0040191B add eax,0FFF
00401920 and eax,FFFFF000
00401925 mov dword ptr ss:[ebp-4],eax
00401928 mov esi,esp
0040192A push 4 ; /Protect = PAGE_READWRITE
0040192C push 1000 ; |AllocationType = MEM_COMMIT
00401931 mov ecx,dword ptr ss:[ebp-4] ; |
00401934 push ecx ; |Size
00401935 push 0 ; |Address = NULL
00401937 call dword ptr ds:[<&KERNEL32.Virtual>; \分配一块存储区BUF3来存放BUF2的内容
0040193D cmp esi,esp
0040193F call <jmp.&MSVCRTD._chkesp>
00401944 mov dword ptr ss:[ebp-8],eax
00401947 cmp dword ptr ss:[ebp-8],0
0040194B jnz short 00401951
0040194D xor eax,eax
0040194F jmp short 004019CA
00401951 mov edx,dword ptr ss:[ebp+14]
00401954 push edx
00401955 mov eax,dword ptr ss:[ebp+10]
00401958 push eax
00401959 mov ecx,dword ptr ss:[ebp+C]
0040195C push ecx
0040195C push ecx
0040195D call <jmp.&Secret.ecret._UserDe>
00401962 mov edx,dword ptr ss:[ebp+14]
00401965 push edx
00401966 mov eax,dword ptr ss:[ebp+10]
00401969 push eax
0040196A mov ecx,dword ptr ss:[ebp+C]
0040196D push ecx
0040196E mov edx,dword ptr ss:[ebp-8]
00401971 push edx
00401972 call 00401073
00401977 add esp,10
0040197A mov eax,dword ptr ss:[ebp-8]
0040197D push eax ; BUF3地址
0040197E mov ecx,dword ptr ss:[ebp+8]
00401981 push ecx ; BUF1地址
00401982 call 004010AF ; 把BUF3内容复制到BUF1中
00401987 add esp,8
0040198A mov dword ptr ss:[ebp-C],eax ; 返回值为BUF1+1000即解密后的代码块的地址
00403310 push ebp ;此处便是具体的解密过程
00403311 mov ebp,esp
00403313 sub esp,4C
00403316 push ebx
00403317 push esi
00403318 push edi
00403319 lea edi,dword ptr ss:[ebp-4C]
0040331C mov ecx,13
00403321 mov eax,CCCCCCCC
00403326 rep stos dword ptr es:[edi]
00403328 mov eax,dword ptr ss:[ebp+C]
0040332B mov dword ptr ss:[ebp-4],eax
0040332E mov ecx,dword ptr ss:[ebp+10]
00403331 mov edx,dword ptr ss:[ebp+8]
00403334 lea eax,dword ptr ds:[edx+ecx-1]
00403338 mov dword ptr ss:[ebp-8],eax
0040333B mov dword ptr ss:[ebp-C],0
00403342 jmp short 0040334D
00403344 mov ecx,dword ptr ss:[ebp-C]
00403347 add ecx,1 ; 填充次数加一
0040334A mov dword ptr ss:[ebp-C],ecx
0040334D mov edx,dword ptr ss:[ebp-C]
00403350 cmp edx,dword ptr ss:[ebp+10] ; 判断是否到达文件尾,是则跳
00403353 jnb short 00403388
00403355 jnz short 0040335B
00403357 je short 0040335B
00403359 db E8
0040335A db 77 ; CHAR 'w'
0040335B mov eax,dword ptr ss:[ebp-4] ; 按字节取BUF2内容到ecx,然后取反送至BUF3中
0040335E movsx ecx,byte ptr ds:[eax]
00403361 not ecx
00403363 mov edx,dword ptr ss:[ebp-8] ; 从BUF2头部解密,结果存至BUF3尾部,按这个顺序进行
00403366 mov byte ptr ds:[edx],cl
00403368 jnz short 0040336E
0040336A je short 0040336E
0040336C db E8
0040336D db 77 ; CHAR 'w'
0040336E mov eax,dword ptr ss:[ebp-4]
00403371 add eax,1 ; BUF2指针后移一字节
00403374 mov dword ptr ss:[ebp-4],eax
00403377 jnz short 0040337D
00403379 je short 0040337D
0040337B db E8
0040337C db 77 ; CHAR 'w'
0040337D mov ecx,dword ptr ss:[ebp-8] ; BUF3指针前移一字节(初始时BUF3指向内容最末)
00403380 sub ecx,1
00403383 mov dword ptr ss:[ebp-8],ecx
00403386 jmp short 00403344
00403388 mov eax,dword ptr ss:[ebp+8]
0040338B pop edi
0040338C pop esi
0040338D pop ebx
0040338E add esp,4C
00403391 cmp ebp,esp
00403393 call <jmp.&MSVCRTD._chkesp>
00403398 mov esp,ebp
0040339A pop ebp
0040339B retn
00B410A6 52 push edx
00B410A7 68 6460B400 push 0B46064 ; ASCII "abcd"
00B410AC E8 3F000000 call 00B410F0 ;此处用来判断注册码是否为abcd
00B410B1 83C4 08 add esp,8
00B410B4 85C0 test eax,eax
00B410B6 74 0C jne short 00B410C4 ;修改此处为je便可完成爆破
这里便是判断是否注册码为abcd的代码
00A410F0 mov edx,dword ptr ss:[esp+4]
00A410F4 mov ecx,dword ptr ss:[esp+8]
00A410F8 test edx,3
00A410FE jnz short 00A4113C
00A41100 mov eax,dword ptr ds:[edx]
00A41102 cmp al,byte ptr ds:[ecx]
00A41104 jnz short 00A41134
00A41106 or al,al
00A41108 je short 00A41130
00A4110A cmp ah,byte ptr ds:[ecx+1]
00A4110D jnz short 00A41134
00A4110F or ah,ah
00A41111 je short 00A41130
00A41113 shr eax,10
00A41116 cmp al,byte ptr ds:[ecx+2]
00A41119 jnz short 00A41134
00A4111B or al,al
00A4111D je short 00A41130
00A4111F cmp ah,byte ptr ds:[ecx+3]
00A41122 jnz short 00A41134
00A41124 add ecx,4
00A41127 add edx,4
00A4112A or ah,ah
00A4112C jnz short 00A41100
00A4112E mov edi,edi
00A41130 xor eax,eax
00A41132 retn
00A41133 nop
00A41134 sbb eax,eax
00A41136 shl eax,1
00A41138 inc eax
00A41139 retn
总结起来就是:
程序加载后读取test后的内容,分配一块后可读可写可执行的
存储区,将test文件中的内容按字节取反,然后从后往前将取
反后的内容写到分配的存储区中,这段内容便是进行注册判断
的"程序"(它是一个完整的PE文件),最后程序跳到这分配的存
储区中执行判断操作,既然作者要求不用注册码通过注册,那
我们就把程序爆破,直接在test文件中搜索F38A3F7A,它们取
反后便是机器码
test eax,eax
jne short 00B410C4
把8A改成8B便是改jne为jn
我先上传一份修改后的test文件上来
脑壳痛的很,午觉都没有睡,就搞这个东东,^_^
--------------------------------------------------------------------------------
【经验总结】
很头痛
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年12月29日 下午 07:03:18
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
上传的附件: