能力值:
( LV2,RANK:10 )
|
-
-
26 楼
程序一开始调用4次WriteProcessMemory恢复40103C处的机器码
并在按下check后调用ReadProcessMemory检查自身一大段机器码
动态SMC 值得学习
|
能力值:
( LV2,RANK:10 )
|
-
-
27 楼
非常详细,给初学者看再好不过了.
|
能力值:
( LV2,RANK:10 )
|
-
-
28 楼
“另:连接之后生成的可执行文件输入用户名之后看不清注册码的就马上退出了,有什么办法让它停下吗?”
加上一句:
system("PAUSE");
或:
getchar();
|
能力值:
( LV2,RANK:10 )
|
-
-
29 楼
汗。。没看到已经有人回了。不过我用的方法和他不一样,没关系。
ps:那两句要加到最后,不过你如果手快的话,在退出前按一下PAUSE键也可以,呵呵。
|
能力值:
( LV2,RANK:10 )
|
-
-
30 楼
不错~!
好文章~!
学习一下
|
能力值:
( LV2,RANK:10 )
|
-
-
31 楼
楼主很强啊,向你学习了。
|
能力值:
( LV2,RANK:10 )
|
-
-
32 楼
看了易leww的精华文章,对文中的那个CRACKME算法了解。文中对算法讲得很明白了,但对程序自身PATCH的保护没提,由于好奇,于是跟了一下其实现过程,也有几个问题想问问
00401000 >/$ 6A 00 push 0 ; /pModule = NULL
00401002 |. E8 B7060000 call <jmp.&kernel32.GetModuleHandleA> ; \GetModuleHandleA
00401007 |. A3 40304000 mov [403040], eax
0040100C |. E8 A1060000 call <jmp.&kernel32.GetCommandLineA> ; [GetCommandLineA
00401011 |. A3 44304000 mov [403044], eax
00401016 |. 6A 0A push 0A ; /Arg4 = 0000000A
00401018 |. FF35 44304000 push dword ptr [403044] ; |Arg3 = 00000000
0040101E |. 6A 00 push 0 ; |Arg2 = 00000000
00401020 |. FF35 40304000 push dword ptr [403040] ; |Arg1 = 00000000
00401026 |. E8 06000000 call 00401031 ; \crackme.00401031
0040102B |. 50 push eax ; /ExitCode
0040102C \. E8 7B060000 call <jmp.&kernel32.ExitProcess> ; \ExitProcess
将当前进程的HANDLE存入403044
将当前进程的路径存入403044
DWORD 00401031(arg1,arg2,arg3,arg4)
{
arg4=ebp+8
arg3=ebp+c
arg2=ebp+10 //进程路径
arg1=ebp+14 //进程handle
}
00401031 /$ 55 push ebp
00401032 |. 8BEC mov ebp, esp
00401034 |. 83C4 B0 add esp, -50
00401037 |. E8 3B040000 call 00401477 //自校检函数
0040103C |. 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
0040103E |. 68 35304000 push 00403035 ; |Title = "Nag"
00401043 |. 68 21304000 push 00403021 ; |Text = "Patch Me if you can"
00401048 |. 6A 00 push 0 ; |hOwner = NULL
0040104A |. E8 33060000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
VOID 00401477(VOID)
{
00401477 /$ C705 803C4000>mov dword ptr [403C80], <jmp.&kernel>
00401481 |. 832D 803C4000>sub dword ptr [403C80], 4
00401488 |. 8305 843C4000>add dword ptr [403C84], 4
0040148F |. 8105 843C4000>add dword ptr [403C84], <jmp.&kernel>
00401499 |. 8305 803C4000>add dword ptr [403C80], 4
004014A0 |. C705 883C4000>mov dword ptr [403C88], <jmp.&kernel>
004014AA |. FF05 883C4000 inc dword ptr [403C88]
//执行了以上几句后发现
// 403c80 = &GetCurrentProcessID
// 403c84 = &OpenProcess + 4
// 403c88 = &WriteProcessMemory + 1
//
004014B0 |. FF15 803C4000 call [403C80] // 调用GetCurrentProcessID
004014B6 |. 832D 843C4000>sub dword ptr [403C84], 4 //恢复OpenProcess的地址
004014BD |. 50 push eax // ProcessID
004014BE |. 6A 00 push 0 // bInheritHandle
004014C0 |. 68 FF0F1F00 push 1F0FFF // dwDesiredAccess
004014C5 |. FF15 843C4000 call [403C84] //OpenProcess
004014CB |. A3 9C3C4000 mov [403C9C], eax //返回的当前进程的句柄存在403c9c
004014D0 |. FF0D 883C4000 dec dword ptr [403C88] //恢复WriteProcessMemeory地址
004014D6 |. FF35 A03C4000 push dword ptr [403CA0] //LPDWORD lpNumberOfBytesWritten
004014DC |. 6A 02 push 2 //DWORD nSize
004014DE |. 68 83204000 push 00402083 //LPVOID lpBuffer
004014E3 |. 68 3C104000 push 0040103C //LPVOID lpBaseAddress
004014E8 |. FF35 9C3C4000 push dword ptr [403C9C] //进程HANDLE
004014EE |. FF15 883C4000 call [403C88] //WriteProcessMemeory
// 此处完成了对40103C处的写2 BYTES,要写的数据由指针402083 指定 (6A 10 -> PUSH 10)
004014F4 |. C705 A03C4000>mov dword ptr [403CA0], 0
004014FE |. FF35 A03C4000 push dword ptr [403CA0]
00401504 |. 6A 06 push 6
00401506 |. 68 86204000 push 00402086 ; ASCII "h50@"
0040150B |. 68 3E104000 push 0040103E
00401510 |. FF35 9C3C4000 push dword ptr [403C9C]
00401516 |. FF15 883C4000 call [403C88]
// 此处完成了对40103e处的写 6 BYTES,要写的数据由指针402086 指定
0040151C |. C705 A03C4000>mov dword ptr [403CA0], 0
00401526 |. FF35 A03C4000 push dword ptr [403CA0]
0040152C |. 6A 06 push 6
0040152E |. 68 8D204000 push 0040208D ; ASCII "h!0@"
00401533 |. 68 43104000 push 00401043
00401538 |. FF35 9C3C4000 push dword ptr [403C9C]
0040153E |. FF15 883C4000 call [403C88]
// 此处完成了对401043处的写 6 BYTES,要写的数据由指针40208D 指定
00401544 |. C705 A03C4000>mov dword ptr [403CA0], 0
0040154E |. FF35 A03C4000 push dword ptr [403CA0]
00401554 |. 6A 02 push 2
00401556 |. 68 94204000 push 00402094
0040155B |. 68 48104000 push 00401048
00401560 |. FF35 9C3C4000 push dword ptr [403C9C]
00401566 |. FF15 883C4000 call [403C88]
// 此处完成了对401048处的写 2 BYTES,要写的数据由指针402094 指定
0040156C |. C705 A03C4000>mov dword ptr [403CA0], 0
00401576 |. FF35 A03C4000 push dword ptr [403CA0]
0040157C |. 6A 05 push 5
0040157E |. 68 97204000 push 00402097
00401583 |. 68 4A104000 push 0040104A
00401588 |. C705 8C3C4000>mov dword ptr [403C8C], <jmp.&kernel>
00401592 |. FF35 9C3C4000 push dword ptr [403C9C]
00401598 |. FF15 883C4000 call [403C88]
// //ReadProcessMemory的地址存入403c8c ,
// 此处完成了对40104A处的写 5 BYTES,要写的数据由指针402097 指定 (EB 33 06 00 00)
0040159E |. 832D 8C3C4000>sub dword ptr [403C8C], 2
004015A5 |. FF35 9C3C4000 push dword ptr [403C9C] ; /hObject = NULL
004015AB |. E8 F6000000 call <jmp.&kernel32.CloseHandle> ; \CloseHandle
004015B0 |. 33C0 xor eax, eax
004015B2 \. C3 retn
//总结一下,WriteProcessMemory一共用了5次,分别为
地址 写入BYTE 内容
40103C 2 6A 10
40103E 6 68 35 30 40 00 00
401043 6 68 21 30 40 00 00
401048 2 6A 00
40104A 5 E8 33 06 00 00
我想问的是,程序首先把几个需要用到的API函数的地址对了一个内存空间,但不知道为什么得到API地址后,它要把这个地址+1或+2
比如
//执行了以上几句后发现
// 403c80 = &GetCurrentProcessID
// 403c84 = &OpenProcess + 4
// 403c88 = &WriteProcessMemory + 1
以上得到了3个API的地址
当程序中要用到OpenProcess的时候,会首先将403c84的值减去4
我不知道这到底有什么好处,作者的用意是什么呢
|
能力值:
( LV5,RANK:60 )
|
-
-
33 楼
Thanks
|
能力值:
( LV2,RANK:10 )
|
-
-
34 楼
先谢谢楼主分享这篇文章!
我也有和32楼兄弟同样的疑惑,该程序在将待使用的函数指针存入内存后经常会马上改变该指针的值,在使用前再改回原值。这是否可以算作一种简单的隐藏待调用函数信息以增加破解难度的措施?我实在想不出第2个合理的解释……望高手指点!
举例如下:
00401274 MOV DWORD PTR DS:[403C68],<JMP.&user32.GetWindowTextL>
0040127E INC DWORD PTR DS:[403C68]; crackme.00401670
00401284 PUSH DWORD PTR DS:[40304C]
0040128A DEC DWORD PTR DS:[403C68]; crackme.00401670
00401290 CALL DWORD PTR DS:[403C68]; <JMP.&user32.GetWindowTextLengthA>
重点是0040127E和0040128A的两条语句,没有什么实际意义嘛,中间只有一条PUSH
|
能力值:
( LV2,RANK:10 )
|
-
-
35 楼
你给我不少信心啊!!我要加紧学咯。呵呵
|
能力值:
( LV2,RANK:10 )
|
-
-
36 楼
学习一下,谢谢分享
|
能力值:
( LV2,RANK:10 )
|
-
-
37 楼
跟踪了一遍,得到注册码:
user:wsdao 必须5位到7位
SN:S-@BKY-Rbe 必须是10位
我也是新手,大家多多指教。
得到注册码后,看看大家的论述,对 shadowtear的发言表示感谢,
又学到新东西了。。
希望有这方面经验的老手,出来对nag反修改做个总结,
让我们新手能得到更深的体会,有更多的收获。
或者给各这方面的资源(文章,论坛链接等)。
|
能力值:
( LV2,RANK:10 )
|
-
-
38 楼
我有点画蛇填足啊,把注册码比较的一段也拿出来啦。
0040134B . C705 603C4000>mov dword ptr [403C60], <jmp.&user32.MessageBoxA> ; 入口地址
00401355 . 832D 603C4000>sub dword ptr [403C60], 7
0040135C . 68 54324000 push 00403254 ; ASCII "Y-Rbe"第一个字符串
00401361 . 68 54344000 push 00403454 ; ASCII "S-@BK"第二个字符串
00401366 . 8305 5C3C4000>add dword ptr [403C5C], 2 ; 算出的2个字符串合并
0040136D . FF15 5C3C4000 call [403C5C] ; crackme.004016D4
00401373 . 68 54344000 push 00403454 ; 合并后的字符串
00401378 . FF05 703C4000 inc dword ptr [403C70] ; crackme.004016DB
0040137E . FF15 703C4000 call [403C70] ; crackme.004016DB
00401384 . A3 743C4000 mov [403C74], eax
00401389 . 68 54364000 push 00403654 ; 取假的注册码
0040138E . FF15 703C4000 call [403C70] ; crackme.004016DB
00401394 . 3B05 743C4000 cmp eax, [403C74] ; 比较注册码长度,不等于10,Game over!
0040139A . 75 46 jnz short 004013E2
0040139C . FF35 543C4000 push dword ptr [403C54]
004013A2 . 68 54344000 push 00403454 ; ASCII "S-@BKY-Rbe"
004013A7 . 68 54364000 push 00403654 ; ASCII "1234567890"
004013AC . E8 9F000000 call 00401450
004013B1 . 83F8 01 cmp eax, 1
004013B4 . 74 2C je short 004013E2 ;这里可以爆破拉
004013B6 . 8305 7C3C4000>add dword ptr [403C7C], 5
004013BD . 8305 783C4000>add dword ptr [403C78], 5
004013C4 . 6A 40 push 40
004013C6 . FF35 783C4000 push dword ptr [403C78] ; crackme.0040207A
004013CC . FF35 7C3C4000 push dword ptr [403C7C] ; crackme.0040206B
004013D2 . FF75 08 push dword ptr [ebp+8]
004013D5 . 8305 603C4000>add dword ptr [403C60], 7
004013DC . FF15 603C4000 call [403C60]
004013E2 > E8 21000000 call 00401408 ; 用户名5-7 注册码10;不是的话,都跳到这里来,就Game Over
004013E7 . C9 leave
004013E8 . C2 1000 retn 10
|
能力值:
( LV2,RANK:10 )
|
-
-
39 楼
现在该好好学习了
多怪以前没学好 哭
|
能力值:
( LV2,RANK:10 )
|
-
-
40 楼
部分引用:
"......另:连接之后生成的可执行文件输入用户名之后看不清注册码的就马上退出了,有什么办法让它停下吗?......"
很简单,加一个等待按键的语句应该就能看到了!
|
能力值:
( LV4,RANK:50 )
|
-
-
41 楼
感谢大家抽出时间看本文,这增强了我的信心和继续吃老鸟并继续努力再写一篇精华的决心;谢谢20、28、40楼的答复,谢谢!也谢谢32楼的参与,只不过我要说声对不住了,(除了因为我本来就太菜一时半会儿解决不了之外)现在真得无法把再心思放在这里好好的去跟踪了--不是难以集中精力而是怕一旦跟踪起来就真真的不想放手,计算机啊,我的最爱!!!!有好多天没来看雪了--这些天忙期末,目的嘛,不挂科,并尽量考好些。只不过我要暂时放弃我所深爱的计算机,总觉不爽!!!----为什么明明不爱她还要给她陪笑脸?为什么明明很爱她却不得不放手?哦,如果上天再给我们一次转专业的机会,我发誓我会考虑的!
|