找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 5495|回复: 2

【翻译】CheatEngine用法1

[复制链接]
发表于 2014-3-26 19:38:13 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
以下是官网的2个教程

教程:自动汇编:按键





     很多人都会问到一个问题是如何在某键按下的时候让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 [ecx+24],#100 设置生命值为100)
...

notpressed:
//清理
popfd
popad

originalcodeandothercleanupstuff:
...
jmp exit





教程:自定义扫描:乘8


这个教程会展示如何进行自定义扫描。

由于各种原因大家仍然想进行自定义扫描,下面的自定义扫描脚本会将给定的值乘8,并显示出除8的结果。

地址列表同时会显示正常情况下未除8的结果。


如何使用:

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

代码:

[enable]
{不要改变下面代码中alloc的那些名字,你可以自由增加新的alloc,别忘了在[disable]中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,[edx] //eax获取新值
cmp eax,[scanvalue] //将eax和用户输入值比较
setz al //如果匹配则置al为1,否则置0(忽略eax高比特位)

ret

prologue:
shl [scanvalue],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 [esi],dl
inc esi

cmp eax,0
jne inttostr_loop

///反转结果

dec esi

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

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

mov byte [edi],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,[eax]
shr eax,3
mov edi,edx
call inttostr
pop edi
pop eax

ret

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



回复

使用道具 举报

发表于 2014-3-27 20:19:44 | 显示全部楼层
顶一个。。。。。。。。。。。。。
回复

使用道具 举报

发表于 2017-2-21 03:12:02 | 显示全部楼层
不错!不错!不错!
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-21 20:56 , Processed in 0.034595 second(s), 21 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表