PEDIY 之 打造你自己的游戏秘技(一)
是男人就下100层
目的程序下载地址: http://diy.xinxing.org/lihai/down100.rar
这个小游戏本来是原来LB论坛上有人提出来请求破解的,于是我下了一个玩玩,结果玩得昏天黑地,差点荒废了Crack大业 ^_^.这个东东的确不错:上面满是钉子的房顶不停地向下压,你必须控制小人踩着托板快速向下跑,有的托板会翻转,有的装着弹簧,有的是钉板,如果碰到钉子生命就会减少.如果血减为零或者直接跳了下去就OVER了.它号称"是男人就下100层",想下100层真的很不容易,尤其到了后面,几乎全是钉板,根本找不到落脚的地方.中等难度我还勉强做了一回男人*_*,高级难度的根本不可能下到100层了.怎么办?这次我们的CRACK技术要用上了,让我们来一个GameDIY ! (建议各位先玩几次)
首先,这个东东还要求注册,不过它的注册判断简直是专门写给Cracker看的,我这样的菜鸟只用十几分钟连注册机都搞定了,对各位高手来说更是不成问题了,破解过程省略.
好了,现在我们想办法找到它让我们"减血"的地方.
运行"金山游侠",或者FPE,GameMaster之类的游戏修改器(别吃惊,慢慢往下看),数数一开始我们有多少血:12格,在"金山游侠"里输入12,查找,找到一堆内存地址.跳上钉板费一些血,再数数还有多少格,进行第二次查找,直到找出唯一的一个地址:4E11E8.好了,现在在游侠里双击它,修改为12,怎么样,又成满血了!呵呵,激动吗?
您说什么,不激动?这样的小把戏N年以前就会玩了,用不着我在这里废话?当然了,这只是一些初级玩家的玩法.我们CRACKER怎么能满足于此呢?好了,我们继续.
还记得上面找到的那个地址吗?现在用Symbol Lorder载入游戏,在SOFTICE里下内存断点BPM 4E11E8 W,也就是当程序向这个地址写入内容时就中断.(在破解软件时我们可以利用各种API函数迅速中断在关键的代码处,但现在用API中断就不行了,我想来想去还是先用游戏修改软件找到内存地址再用内存断点比较简单,当然你也可以在SOFTICE里用S手工搜,只要你有耐心把成百上千个内存地址记下来一一对比*_*....)
断点下好没有?现在回到游戏,勇敢地跳上一块钉板,轰! SOFTICE出来了,中断在下面:
:00406988 8B45F4 mov eax, dword ptr [ebp-0C]
:0040698B C1E005 shl eax, 05
:0040698E 8B4D08 mov ecx, dword ptr [ebp+08]
:00406991 83AC087011000006 sub dword ptr [eax+ecx+00001170], 00000006 <--HEHE,就是这里了
:00406999 E97D000000 jmp 00406A1B <--我们会停在这一句
很明显,在406991这一句上我们被减掉了六格血,现在我们把它改为sub dword ptr [eax+ecx+1170],0 也就是机器码改为83AC087011000000,再回到游戏往钉板上跳一跳,怎么样?爽吧?
这样只是把钉板上的减血去掉了,可是如果被顶上的钉子压住还是会减血,用同样的方法可以找到下面:
:00406308 8B45F4 mov eax, dword ptr [ebp-0C]
:0040630B C1E005 shl eax, 05
:0040630E 8B4D08 mov ecx, dword ptr [ebp+08]
:00406311 83AC087011000005 sub dword ptr [eax+ecx+00001170], 00000005 <--把这里改掉
:00406319 8B45F4 mov eax, dword ptr [ebp-0C] <--我们会停在这里
:0040631C C1E005 shl eax, 05
:0040631F 8B4D08 mov ecx, dword ptr [ebp+08]
还有一处是当小人在弹簧板上向上弹时头顶碰到钉子时减血,同样的方法找到下面:
:00406615 8B45F4 mov eax, dword ptr [ebp-0C]
:00406618 C1E005 shl eax, 05
:0040661B 8B4D08 mov ecx, dword ptr [ebp+08]
:0040661E 83AC087011000005 sub dword ptr [eax+ecx+00001170], 00000005 <--把这里改掉
:00406626 8B45F4 mov eax, dword ptr [ebp-0C] <--停在这一句
:00406629 C1E005 shl eax, 05
:0040662C 8B4D08 mov ecx, dword ptr [ebp+08]
这三处都改好以后,你就成了金刚不坏之身了,再想当男人就容易多了吧?
(未完待续)
PEDIY 之 打造你自己的游戏秘技(二)
上一次我们用修改减血的数值使自己变成了"无敌",但本文的题目是"打造你自己的游戏秘技",真正的游戏往往是按某些特殊的键以后才会有满血,无敌等功能,而不知道秘技的玩家是无法享受这种特殊服务的.现在我们就在游戏中加入自己的秘技:只要按一个键就会变成满血.
大致确定一个思路:我们先要加入一个"快捷键"(有时也叫"加速键","加速器"等),每次按下中触发一个消息,在窗口处理的函数中加入对这条消息的处理过程.
先确定WndProc窗口消息处理过程的位置.这里用一种我认为比较简单的方法:一个典型的WINDOWS程序往往是先定义一个WndClass结构,(这个结构中包含WndProc的指针,窗口使用的图标光标等)然后用RegisterClass注册这个窗口类.我们现在关心的是WndProc的地址,它在WndClass结构的第二项.所以我们只要先找到RegisterClass函数,然后向上查找对WndClass的定义就可以了.(我的编程很烂,有些术语说得不准确,具体请参考关于WINDOWS编程的书.)
用W32DASM反汇编(用IDA当然最好了,不过这个东东比较简单,用W32DASM完全可以搞定)
在"输入函数"里双击RegisterClassA函数,就来到这里:
:00401BA5 55 push ebp
:00401BA6 8BEC mov ebp, esp
:00401BA8 83EC28 sub esp, 00000028
:00401BAB 53 push ebx
:00401BAC 56 push esi
:00401BAD 57 push edi
:00401BAE 8B4508 mov eax, dword ptr [ebp+08]
:00401BB1 A300E24000 mov dword ptr [0040E200], eax
:00401BB6 C745D820200000 mov [ebp-28], 00002020
:00401BBD C745DC961C4000 mov [ebp-24], 00401C96 <--这个就是我们要找的
:00401BC4 C745E000000000 mov [ebp-20], 00000000
* Possible Reference to String Resource ID=00004: "鑼?
|
:00401BCB C745E404000000 mov [ebp-1C], 00000004
:00401BD2 8B4508 mov eax, dword ptr [ebp+08]
:00401BD5 8945E8 mov dword ptr [ebp-18], eax
:00401BD8 6A76 push 00000076
:00401BDA 8B4508 mov eax, dword ptr [ebp+08]
:00401BDD 50 push eax
* Reference To: USER32.LoadIconA, Ord:017Ah
|
:00401BDE FF1538044100 Call dword ptr [00410438]
:00401BE4 8945EC mov dword ptr [ebp-14], eax
:00401BE7 68007F0000 push 00007F00
:00401BEC 6A00 push 00000000
* Reference To: USER32.LoadCursorA, Ord:0176h
|
:00401BEE FF1540044100 Call dword ptr [00410440]
:00401BF4 8945F0 mov dword ptr [ebp-10], eax
* Possible Reference to String Resource ID=00004: "鑼?
|
:00401BF7 6A04 push 00000004
* Reference To: GDI32.GetStockObject, Ord:00F6h
|
:00401BF9 FF1580024100 Call dword ptr [00410280]
:00401BFF 8945F4 mov dword ptr [ebp-0C], eax
* Possible Reference to Menu: MenuID_0074
|
:00401C02 C745F874000000 mov [ebp-08], 00000074
* Possible StringData Ref from Data Obj ->"NsShaftClass"
|
:00401C09 C745FC14D24000 mov [ebp-04], 0040D214
:00401C10 8D45D8 lea eax, dword ptr [ebp-28]
:00401C13 50 push eax
* Reference To: USER32.RegisterClassA, Ord:01BAh
|
:00401C14 FF15E0034100 Call dword ptr [004103E0] <--光条停在这里,向上找
:00401C1A 0FB7C0 movzx eax, ax
:00401C1D E900000000 jmp 00401C22
401C96处就是WndProc了,我们转到这里:
:00401C96 55 push ebp
:00401C97 8BEC mov ebp, esp
:00401C99 83EC08 sub esp, 00000008
:00401C9C 53 push ebx
:00401C9D 56 push esi
:00401C9E 57 push edi
:00401C9F 6A00 push 00000000
:00401CA1 8B4508 mov eax, dword ptr [ebp+08]
:00401CA4 50 push eax
* Reference To: USER32.GetWindowLongA, Ord:0132h
|
:00401CA5 FF1578034100 Call dword ptr [00410378]
..........(省略一部分)
:00401D4F 6A00 push 00000000
:00401D51 6A00 push 00000000
:00401D53 8B4508 mov eax, dword ptr [ebp+08]
:00401D56 50 push eax
* Reference To: USER32.SetWindowLongA, Ord:0215h
|
:00401D57 FF1588034100 Call dword ptr [00410388]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401D25(C)
|
:00401D5D 8B450C mov eax, dword ptr [ebp+0C]
:00401D60 8945F8 mov dword ptr [ebp-08], eax
:00401D63 E90A020000 jmp 00401F72 <--跳转过去
JMP后在这里:(HEHE,很明显了,[ebp-8]中是各种消息的代号,其中我们要找的是0x111即WM_COMMAND消息,当点击菜单或快捷键时都会产生这条消息)
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401D63(U)
|
:00401F72 837DF806 cmp dword ptr [ebp-08], 00000006
:00401F76 0F871F000000 ja 00401F9B
:00401F7C 0F84E6FDFFFF je 00401D68
:00401F82 837DF801 cmp dword ptr [ebp-08], 00000001
:00401F86 0F840BFEFFFF je 00401D97
:00401F8C 837DF802 cmp dword ptr [ebp-08], 00000002
:00401F90 0F842AFEFFFF je 00401DC0
:00401F96 E9B7FFFFFF jmp 00401F52
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401F76(C)
|
:00401F9B 817DF800010000 cmp dword ptr [ebp-08], 00000100
:00401FA2 0F8715000000 ja 00401FBD
:00401FA8 0F8454FEFFFF je 00401E02
:00401FAE 837DF80F cmp dword ptr [ebp-08], 0000000F
:00401FB2 0F84FCFEFFFF je 00401EB4
:00401FB8 E995FFFFFF jmp 00401F52
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401FA2(C)
|
:00401FBD 817DF811010000 cmp dword ptr [ebp-08], 00000111 <--就是它,WM_COMMAND=0x111
:00401FC4 0F8718000000 ja 00401FE2
:00401FCA 0F8403FEFFFF je 00401DD3 <--跳到这个地址看看
:00401FD0 817DF801010000 cmp dword ptr [ebp-08], 00000101
:00401FD7 0F8452FEFFFF je 00401E2F
:00401FDD E970FFFFFF jmp 00401F52
跳到WM_COMMAND消息处理部分:
:00401DD3 8B4510 mov eax, dword ptr [ebp+10]
:00401DD6 C1E810 shr eax, 10
:00401DD9 25FFFF0000 and eax, 0000FFFF
:00401DDE 0FB7C0 movzx eax, ax
:00401DE1 50 push eax
:00401DE2 8B4514 mov eax, dword ptr [ebp+14]
:00401DE5 50 push eax
:00401DE6 8B4510 mov eax, dword ptr [ebp+10]
:00401DE9 25FFFF0000 and eax, 0000FFFF
:00401DEE 50 push eax
:00401DEF 8B45FC mov eax, dword ptr [ebp-04]
:00401DF2 50 push eax
:00401DF3 E817090000 call 0040270F <--进这个CALL
:00401DF8 83C410 add esp, 00000010
:00401DFB 33C0 xor eax, eax
:00401DFD E956020000 jmp 00402058
* Referenced by a CALL at Address:
|:00401DF3
|
:0040270F 55 push ebp
:00402710 8BEC mov ebp, esp
:00402712 83EC04 sub esp, 00000004
:00402715 53 push ebx
:00402716 56 push esi
:00402717 57 push edi
:00402718 8B450C mov eax, dword ptr [ebp+0C]
:0040271B 8945FC mov dword ptr [ebp-04], eax
:0040271E E917010000 jmp 0040283A <--再跳到后面
:00402723 8B4508 mov eax, dword ptr [ebp+08]
:00402726 C7801013000000000000 mov dword ptr [ebx+00001310], 00000000
...........
终于到达目的地了,仔细看好,[ebp-4]是消息的wParam值,也就是各个菜单项或快捷键的ID值,这些ID值可以用资源编辑工具(如eXeScope,ResHacker)等看到,用ResHacker分析这个程序,可以发现它的菜单ID值从40001至40017(即0x9C41-0x9C51),还有一个快捷键F1,ID值为40021(0x9C55).
:0040283A 816DFC419C0000 sub dword ptr [ebp-04], 00009C41 <--ID值与9C41的差
:00402841 837DFC14 cmp dword ptr [ebp-04], 00000014
:00402845 0F875E000000 ja 004028A9 <--如果超出范围就不处理
:0040284B 8B45FC mov eax, dword ptr [ebp-04]
:0040284E FF248555284000 jmp dword ptr [4*eax+00402855] <--根据差值的不同选择下面的表中不同的值进行跳转,好像一个CASE结构,很有意思的写法
:00402855 23274000 DWORD 00402723-\
:00402859 41274000 DWORD 00402741 |
:0040285D 5F274000 DWORD 0040275F |
:00402861 70274000 DWORD 00402770 |
:00402865 81274000 DWORD 00402781 |
:00402869 92274000 DWORD 00402792 |
:0040286D 92274000 DWORD 00402792 |
:00402871 92274000 DWORD 00402792 |--前17项是各个菜单项的处理
:00402875 A7274000 DWORD 004027A7 |
:00402879 A7274000 DWORD 004027A7 |
:0040287D A7274000 DWORD 004027A7 |
:00402881 BC274000 DWORD 004027BC |
:00402885 CD274000 DWORD 004027CD |
:00402889 DE274000 DWORD 004027DE |
:0040288D EF274000 DWORD 004027EF |
:00402891 00284000 DWORD 00402800 |
:00402895 11284000 DWORD 00402811-/
:00402899 A9284000 DWORD 004028A9-\
:0040289D A9284000 DWORD 004028A9 |--这三项没有用到
:004028A1 A9284000 DWORD 004028A9-/ <-修改这一句使它指向我们自己写的代码
:004028A5 24284000 DWORD 00402824----这是程序快捷键F1的处理
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040273C(U), :0040275A(U), :0040276B(U), :0040277C(U), :0040278D(U)
|:004027A2(U), :004027B7(U), :004027C8(U), :004027D9(U), :004027EA(U)
|:004027FB(U), :0040280C(U), :0040281F(U), :00402830(U), :00402835(U)
|:00402845(C), :0040BDC2(U)
|
:004028A9 5F pop edi
:004028AA 5E pop esi
:004028AB 5B pop ebx
:004028AC C9 leave
:004028AD C3 ret
软件好像故意给我们留了位置增加功能啊:).这下省事了.定义一个ID值为40020(0x9C54)的快捷键F2,在ResHack里是这样的:
VK_F1, 40021, NOINVERT, VIRTKEY //程序原有的
VK_F2, 40020, NOINVERT, VIRTKEY //自己加入的
(因为是"秘"技所以就不定义菜单了:))
然后把4028A1这里的DWORD值改为40BDB8,这里是块尾的空白,可以用来加入代码.(注:在HIEW里这一个"地址表"会被识别成类似花指令的东东,看准再改.)
在程序代码段结尾处的空白里写入自己的代码:
原来的代码:
* Reference To: KERNEL32.RtlUnwind, Ord:01C7h
|
:0040BDB2 FF2540034100 Jmp dword ptr [00410340]
:0040BDB8 00000000000000000000 BYTE 10 DUP(0)
:0040BDC2 00000000000000000000 BYTE 10 DUP(0)
:0040BDCC 00000000000000000000 BYTE 10 DUP(0)
:0040BDD6 00000000000000000000 BYTE 10 DUP(0)
用HIEW修改后:
* Reference To: KERNEL32.RtlUnwind, Ord:01C7h
|
:0040BDB2 FF2540034100 Jmp dword ptr [00410340]
:0040BDB8 C705E8114E000C000000 mov dword ptr [004E11E8], 0000000C <--自己的代码,充满12格血
:0040BDC2 E9E26AFFFF jmp 004028A9 <--自己的代码,返回
:0040BDC7 00000000000000000000 BYTE 10 DUP(0)
:0040BDD1 00000000000000000000 BYTE 10 DUP(0)
:0040BDDB 00000000000000000000 BYTE 10 DUP(0)
用HIEW应当这样输入:
mov d,[4E11E8],0c
jmp 1EA9 //1EA9是文件偏移地址,在修改完成后可以看到HIEW自动把它转成了虚拟地址4028A9
修改以后再运行一下,只要一按F2键,马上就成起死回生了!
标 题:是男人就下100层补充 (6千字)
发信人:*咖啡豆*
时 间:2003-12-02 21:40:11
详细信息:
看了RORO大侠的文章,兴致勃勃,下了一个来改。
由于已经有RORO提供的资料,所以改起来非常顺利
只是有一个地方必须说明,就是RORO说的用快捷键直接改内存的方法有一点问题,就
是每次在不同环境下运行WINDOWS程序的内存和值的对应位置不是固定的,比如说移
动了软件,或初始化的过程稍有不同,都会导致值地址的改变。所以按RORO的方法改
很可能导致非法访问或写到不知道的地址造成错误。当然了,这只是忽略了一个小问
题罢了,就让我来补充一下.
一个WINDOWS程序的运行过程是不断在运行--就绪--阻塞中循环的,当进程等待某个事
件,资源的时候,它会阻塞自己,这时需要做现场保护工作--把一些重要的变量保存
起来,当他恢复的时候就会把保护的资源还原过来。于是可以从现场恢复的时候找到
每个变量的寻址方式。
于是,先挂一次,于是回到开始时的界面,这时如果按单人游戏菜单项(就是第一项
,我汉化过了)会进行初始化工作,也就是各个变量的副初值。
先找到菜单处理的位置,由于RORO已经说的很清楚, 于是很容易就找到这里
:0040283A sub dword ptr [ebp-04], 00009C41
:00402841 cmp dword ptr [ebp-04], 00000014
:00402845 ja 004028A9
:0040284B mov eax, dword ptr [ebp-04]
:0040284E jmp dword ptr [4*eax+00402855]
:00402855 DWORD 00402723;<--由于ID是40001,所以是第一个
:00402859 DWORD 00402741
:0040285D DWORD 0040275F
:00402861 DWORD 00402770
:00402865 DWORD 00402781
:00402869 DWORD 00402792
:0040286D DWORD 00402792
:00402871 DWORD 00402792
:00402875 DWORD 004027A7
:00402879 DWORD 004027A7
:0040287D DWORD 004027A7
跳过去看看,到了这里:
:00402723 mov eax, dword ptr [ebp+08]
:00402726 mov dword ptr [ebx+00001310], 00000000
:00402730 mov eax, dword ptr [ebp+08]
:00402733 push eax
:00402734 call 004080C0
call进去看看
到达这里:
:004080C0 push ebp
:004080C1 mov ebp, esp
:004080C3 sub esp, 00000014
:004080C5 push ebx
:004080C7 push esi
:004080C8 push edi
:004080C9 call 00406E5F
:004080CE mov eax, dword ptr [ebp+08]
:004080D1 mov eax, dword ptr [eax]
:004080D3 push eax
* Reference To: USER32.GetMenu, Ord:0103h
|
:004080D4 FF1530044100 Call dword ptr [00410430]
:004080DA 8945EC mov dword ptr [ebp-14], eax
* Possible Reference to String Resource ID=00001: "/7? 100B难H"
一大堆什么东西啊!
那是最开始的对话筐的撤消和把一些菜单项DISABLE
一直拖啊拖啊,终于到了!
以下就是初始化时的语句:
:0040818E 8B4508 mov eax, dword ptr [ebp+08]
:00408191 8B8048120000 mov eax, dword ptr [eax+00001248]
:00408197 83E820 sub eax, 00000020
:0040819A 8B4D08 mov ecx, dword ptr [ebp+08]
:0040819D 89817C110000 mov dword ptr [ecx+0000117C], eax
:004081A3 8B4508 mov eax, dword ptr [ebp+08]
:004081A6 8B807C110000 mov eax, dword ptr [eax+0000117C]
:004081AC 8B4D08 mov ecx, dword ptr [ebp+08]
:004081AF 89815C110000 mov dword ptr [ecx+0000115C], eax
:004081B5 8B4508 mov eax, dword ptr [ebp+08]
:004081B8 C7808011000000000000 mov dword ptr [ebx+00001180], 00000000
:004081C2 8B4508 mov eax, dword ptr [ebp+08]
:004081C5 8B8080110000 mov eax, dword ptr [eax+00001180]
:004081CB 8B4D08 mov ecx, dword ptr [ebp+08]
:004081CE 898160110000 mov dword ptr [ecx+00001160], eax
:004081D4 8B4508 mov eax, dword ptr [ebp+08]
:004081D7 C7808C11000007000000 mov dword ptr [ebx+0000118C], 00000007
:004081E1 8B4508 mov eax, dword ptr [ebp+08]
:004081E4 8B808C110000 mov eax, dword ptr [eax+0000118C]
:004081EA 8B4D08 mov ecx, dword ptr [ebp+08]
:004081ED 89816C110000 mov dword ptr [ecx+0000116C], eax
:004081F3 8B4508 mov eax, dword ptr [ebp+08]
:004081F6 C780901100000C000000 mov dword ptr [ebx+00001190], 0000000C
接下来的是最激动人心的,血的初始化:
:00408200 8B4508 mov eax, dword ptr [ebp+08]
:00408203 8B8090110000 mov eax, dword ptr [eax+00001190]
:00408209 8B4D08 mov ecx, dword ptr [ebp+08]
:0040820C 898170110000 mov dword ptr [ecx+00001170], eax;<---血的寻址
很容易看出,血是放在[ebp+00001170]
其实所有的现场恢复都在这里了
找到寻址方式就好办了,按照RORO大虾的方法
加个快捷键,然后通过在
:00402855 23274000 DWORD 00402723
:00402859 41274000 DWORD 00402741
:0040285D 5F274000 DWORD 0040275F
:00402861 70274000 DWORD 00402770
:00402865 81274000 DWORD 00402781
:00402869 92274000 DWORD 00402792
:0040286D 92274000 DWORD 00402792
:00402871 92274000 DWORD 00402792
:00402875 A7274000 DWORD 004027A7
:00402879 A7274000 DWORD 004027A7
:0040287D A7274000 DWORD 004027A7
:00402881 BC274000 DWORD 004027BC
:00402885 CD274000 DWORD 004027CD
:00402889 DE274000 DWORD 004027DE
:0040288D EF274000 DWORD 004027EF
:00402891 00284000 DWORD 00402800
:00402895 11284000 DWORD 00402811
:00402899 A9284000 DWORD 004028A9
:0040289D C2BD4000 DWORD 0040BDC2;<--改成跳到我改的地方
:004028A1 A9284000 DWORD 004028A9
:004028A5 24284000 DWORD 00402824
改一个跳转
跳到最后加代码的地方:
:0040BDB2 FF2540034100 Jmp dword ptr [00410340]
:0040BDB8 00000000000000000000 BYTE 10 DUP(0);<--原来的代码
:0040BDC2 mov ecx, dword ptr [ebp+08] | 我加的代码
:0040BDC5 mov dword ptr [ebx+00001170], 00FFFFFF; |
:0040BDCF jmp 004028A9 |
:0040BDD4 BYTE 10 DUP(0)
:0040BDDE BYTE 10 DUP(0)
:0040BDE8 BYTE 10 DUP(0)
:0040BDF2 BYTE 10 DUP(0)
:0040BDFC BYTE 10 DUP(0)
于是一按空格就变成FFFFFF血(16777215点),变成小强!
再作成免注册中文版,全部搞定。
最后请大侠门拍小力点..哇!不要拍头啊!!