元始天尊 发表于 2014-3-26 19:38:13

【翻译】CheatEngine用法1

以下是官网的2个教程
教程:自动汇编:按键



http://www.cheatengine.org/keypresstut.php   
   很多人都会问到一个问题是如何在某键按下的时候让CheatEngine产生响应。如果你使用了CheatEngine的自动汇编脚本,就很容易解决这个问题。
首先你必须要保存程序状态(pushad/popad),然后吧你要检查的按键压入栈顶部,调用GetAsyncKeystate。然后通过检查存在ax的返回值查看该键
是否正被按下还是曾经被按下过。第15位为1代表是当前按下的键,第0位为1代表从上次调用该函数到现在的某个时间该键被按下过。
如果该键当前没有没按下就跳出所有的游戏修改代码(例如执行减少血量hp的代码)并且返回给调用者,如果当前被按下就执行你的常规代码。
(设置值,跳过减少血量的hp例程,等。。。)   
例子:
origin:
jmp mycode
exit:

mycode:
pushad //由于不知道GetAsyncKeystate改了哪些寄存,我猜是eax,ebx,ecx,我讨厌猜测
pushfd //保存标志寄存器是好习惯

...
push 'X' ;要查看状态的键,对于特殊键需要自己google
call GetAsyncKeyState
//第15位为1代表是当前按下的键
//第0位为1代表从上次调用该函数到现在的某个时间该键被按下过
//查看第0位为1的方法如下:
//and ax,1 //与掩码 0000000000000001做与运算
//cmp ax,1
//jne notpressedsincelasttime

//注意上面的代码只是简单实现,其实有很多好方法但是会让人难以理解。
shr ax,#15 //由于是16位寄存器,右移AX寄存器并将左边填充0,1000000000000000就转换为0000000000000001, 没有高于第15位的位了
cmp ax,1 //如果第15位置1,ax现在的值九尾0或1
jne notpressed

//如果按下了
...
...运行按下该键的响应代码(例如 mov ,#100 设置生命值为100)
...

notpressed:
//清理
popfd
popad

originalcodeandothercleanupstuff:
...
jmp exit




教程:自定义扫描:乘8
http://www.cheatengine.org/customscanmultiplyby8tut.php
这个教程会展示如何进行自定义扫描。
由于各种原因大家仍然想进行自定义扫描,下面的自定义扫描脚本会将给定的值乘8,并显示出除8的结果。
地址列表同时会显示正常情况下未除8的结果。

如何使用:
选择自定义值类型,点击新建,写入下面的脚本,点击ok,赋予一个名称,然后扫描你要找的值
代码:

{不要改变下面代码中alloc的那些名字,你可以自由增加新的alloc,别忘了在中dealloc他们}
alloc(checkroutine,2048)
alloc(prologue,2048)
alloc(epilogue,2048)
alloc(fastscanstepsize,4)
alloc(variablesize,4)
alloc(firstscan,4)
alloc(scantext,4) //会获取给定字符串的地址
alloc(scanvalue,8) //will get the value of the input string converted to an 8-byte value
alloc(singlescanvalue,4) //会获取输入的float型值
alloc(doublescanvalue,8) //会获取输入的double型值
alloc(inttostr,1024)

variablesize:
dd 4 //定义每个搜到的结果保存为多少字节

fastscanstepsize:
dd 1 //定义快速搜索时候的步长大小(1=不变)

firstscan:
dd 0 //如果想用上次搜到的值继续搜索,置1

/* routines:
提示: 你可以用任意语言写这些函数,并输出为dll,然后使用Loadlibrary 或者调用exportfunction来使用*/

checkroutine:
/*
edx=指向新值的指针
ecx=指向旧值得指针
*/


mov eax, //eax获取新值
cmp eax, //将eax和用户输入值比较
setz al //如果匹配则置al为1,否则置0(忽略eax高比特位)
ret

prologue:
shl ,3
//你可以在这里放置要在扫描开始前执行的代码
ret

epilogue:
//你可以在这里放置要在扫描结束后执行的代码
ret

scandisplayroutinetype:
/*
displayroutinetype是一个特殊的全局标志,无需这个地址处的字节决定如何显示值
0=1字节标记
1=2字节标记
2=4字节标记
3=8字节标记
4=float标记
5=double标记
6=数组类型标记
7=ascii字符串标志
8=unicode字符串标志
ff=使用 'scandisplayroutine:' 转换data为字符串
*/
db ff //2=4字节标志


label(inttostr_loop)
label(inttostr_reverseresult)
alloc(tempinttostrbuf,50)
inttostr:
//input:
//eax=value
//edi=字符串存储空间
push ecx
push edx
push edi
push esi

mov esi,tempinttostrbuf
mov ecx,#10
inttostr_loop:
xor edx,edx
div ecx
add dl,'0'
mov ,dl
inc esi

cmp eax,0
jne inttostr_loop

///反转结果

dec esi

inttostr_reverseresult:
mov al,
mov byte ,al
inc edi
dec esi

cmp esi,tempinttostrbuf //back at base ?
jae inttostr_reverseresult

mov byte ,0

pop esi
pop edi
pop edx
pop ecx
ret

scandisplayroutine:
/*如果 'scandisplayroutinetype:' 设置为 255 这个例程会被调用,转换指定地址的值为ascii字符串
eax=指向字节数组的地址
edx=指向目的字符串的地址 (最多50个字符)

注意: scandisplayroutine 只有16kb
*/

push eax
push edi
mov eax,
shr eax,3
mov edi,edx
call inttostr
pop edi
pop eax

ret


dealloc(checkroutine)
dealloc(prologue,2048)
dealloc(epilogue,2048)
dealloc(fastscanstepsize)
dealloc(variablesize)
dealloc(scantext)
dealloc(scanvalue)
dealloc(singlescanvalue)
dealloc(doublescanvalue)
dealloc(inttostr)
dealloc(tempinttostrbuf)


Anonymous 发表于 2014-3-27 20:19:44

顶一个。。。。。。。。。。。。。

ZhengBin 发表于 2017-2-21 03:12:02

不错!不错!不错!
页: [1]
查看完整版本: 【翻译】CheatEngine用法1