Cheat Engine RPCS3 设置

随着 RPCS3 的崛起,自然会有不少人想要使用金手指在那些单人游戏。但是如果你尝试过直接在 RPCS3 上用 Cheat Engine 扫描功能的话想必你应该遇过一些问题,譬如说你想找的地址不存在,或者地址内存的字节倒反了。基于这些原因,这教程会教你如何简单的在 Cheat Engine 上做一些调整,让你能在 RPCS3 上使用基本扫描功能。但在开始前我必须强调虽然理论上这些设置适用于每个 RPCS3 里的游戏,而我也只在 EXVSFB 上做过实践测试,所以我不敢保证不会有出入。如果你看到你的游戏金手指教程的设置和这教程有些出入,那就请你使用配合你游戏的设置。


MEM_MAPPED 设置

首先,我们必须开启 Cheat Engine 里的 MEM_MAPPED 功能。开启这一个功能的目的是为了让 Cheat Engine 有能力扫描模拟器里游戏的内存。然而如果这项功能没开,Cheat Engine 只能扫描到模拟器本身的内存,而不是游戏的内存。换而言之对我们来说是没用的。

在 Cheat Engine 里,按下编辑 -> 设置

在设置窗口弹出后,按下扫描设置。
最重要的是 MEM_PRIVATE, MEM_IMAGE 和 MEM_MAPPED 都打了勾然后按下确定, 如图


逆向字节 (Big Endian) 支持

由于模拟器的内存方式不同,如果要扫描地址普通的字节是行不通的。在大部分模拟器里都需要逆向字节才能扫描。但是在普通的 Cheat Engine 里没有逆向字节的数值类型,所以我们必须自定义新的数值类型。

在 Cheat Engine 里, 鼠标右击数值类型旁的选项,然后选择定义新的“自定义类型”(自动汇编),如图

按下过后会有一个自动汇编的窗口弹出,把里面的东西全部删了,然后把下面这些代码贴入

alloc(TypeName,256) 
alloc(ByteSize,4) 
alloc(ConvertRoutine,1024) 
alloc(ConvertBackRoutine,1024) 
alloc(UsesFloat,1)
alloc(CallMethod,1)

TypeName: 
db '逆向2字节',0 

ByteSize: 
dd 2 

//The convert routine should hold a routine that converts the data to an integer (in eax) 
//function declared as: stdcall int ConvertRoutine(unsigned char *input); 
//Note: Keep in mind that this routine can be called by multiple threads at the same time. 
ConvertRoutine: 
//jmp dllname.functionname 
[64-bit] 
//or manual: 
//parameters: (64-bit) 
//rcx=address of input 
xor eax,eax 
mov ax,[rcx] //eax now contains the bytes 'input' pointed to 
xchg ah,al //convert to big endian 

ret 
[/64-bit] 

[32-bit] 
//jmp dllname.functionname 
//or manual: 
//parameters: (32-bit) 
push ebp 
mov ebp,esp 
//[ebp+8]=input 
//example: 
mov eax,[ebp+8] //place the address that contains the bytes into eax 
mov ax,[eax] //place the bytes into eax so it's handled as a normal 4 byte value 
and eax,ffff //cleanup 
xchg ah,al //convert to big endian 

pop ebp 
ret 4 
[/32-bit] 

//The convert back routine should hold a routine that converts the given integer back to a row of bytes (e.g when the user wats to write a new value) 
//function declared as: stdcall void ConvertBackRoutine(int i, unsigned char *output); 
ConvertBackRoutine: 
//jmp dllname.functionname 
//or manual: 
[64-bit] 
//parameters: (64-bit) 
//ecx=input 
//rdx=address of output 
//example: 
xchg ch,cl //convert the little endian input into a big endian input 
mov [rdx],cx //place the integer the 4 bytes pointed to by rdx 

ret 
[/64-bit] 

[32-bit] 
//parameters: (32-bit) 
push ebp 
mov ebp,esp 
//[ebp+8]=input 
//[ebp+c]=address of output 
//example: 
push eax 
push ebx 
mov eax,[ebp+8] //load the value into eax 
mov ebx,[ebp+c] //load the address into ebx 

//convert the value to big endian 
xchg ah,al 

mov [ebx],ax //write the value into the address 
pop ebx 
pop eax 

pop ebp 
ret 8 
[/32-bit] 

贴入过后,你的自动汇编应该会和下面的图片内容一样。核对了过后便可按下确定

按下确定了过后,你便会发现数值类型里会多了一个逆向2字节的选项,如图

接下来我们用一样的方式把逆向4字节加入数值类型里。

alloc(TypeName,256) 
alloc(ByteSize,4) 
alloc(ConvertRoutine,1024) 
alloc(ConvertBackRoutine,1024) 
alloc(UsesFloat,1)
alloc(CallMethod,1)

TypeName: 
db '逆向4字节',0 

ByteSize: 
dd 4 

//The convert routine should hold a routine that converts the data to an integer (in eax) 
//function declared as: stdcall int ConvertRoutine(unsigned char *input); 
//Note: Keep in mind that this routine can be called by multiple threads at the same time. 
ConvertRoutine: 
//jmp dllname.functionname 
[64-bit] 
//or manual: 
//parameters: (64-bit) 
//rcx=address of input 
xor eax,eax 
mov eax,[rcx] //eax now contains the bytes 'input' pointed to 
bswap eax //convert to big endian 

ret 
[/64-bit] 

[32-bit] 
//jmp dllname.functionname 
//or manual: 
//parameters: (32-bit) 
push ebp 
mov ebp,esp 
//[ebp+8]=input 
//example: 
mov eax,[ebp+8] //place the address that contains the bytes into eax 
mov eax,[eax] //place the bytes into eax so it's handled as a normal 4 byte value 

bswap eax 

pop ebp 
ret 4 
[/32-bit] 

//The convert back routine should hold a routine that converts the given integer back to a row of bytes (e.g when the user wats to write a new value) 
//function declared as: stdcall void ConvertBackRoutine(int i, unsigned char *output); 
ConvertBackRoutine: 
//jmp dllname.functionname 
//or manual: 
[64-bit] 
//parameters: (64-bit) 
//ecx=input 
//rdx=address of output 
//example: 
bswap ecx //convert the little endian input into a big endian input 
mov [rdx],ecx //place the integer the 4 bytes pointed to by rdx 

ret 
[/64-bit] 

[32-bit] 
//parameters: (32-bit) 
push ebp 
mov ebp,esp 
//[ebp+8]=input 
//[ebp+c]=address of output 
//example: 
push eax 
push ebx 
mov eax,[ebp+8] //load the value into eax 
mov ebx,[ebp+c] //load the address into ebx 

//convert the value to big endian 
bswap eax 

mov [ebx],eax //write the value into the address 
pop ebx 
pop eax 

pop ebp 
ret 8 
[/32-bit] 

按下确定了过后,在用一样的方式把逆向浮游加入数值类型里 。

alloc(TypeName,256) 
alloc(ByteSize,4) 
alloc(ConvertRoutine,1024) 
alloc(ConvertBackRoutine,1024) 
alloc(UsesFloat,4)
alloc(CallMethod,1)

TypeName: 
db '逆向浮游',0 
ByteSize: 
dd 4 
UsesFloat:
db 01

ConvertRoutine: 
[32-bit] 
push ebp 
mov ebp,esp 
mov eax,[ebp+8] //place the address that contains the bytes into eax 
mov eax,[eax]   //place the bytes into eax 
bswap eax 
pop ebp 
ret 4 
[/32-bit] 

[64-bit] 
//rcx=address of input 
mov eax,[rcx] //eax now contains the bytes 'input' pointed to 
bswap eax 
ret 
[/64-bit] 

ConvertBackRoutine: 
[32-bit] 
push ebp 
mov ebp,esp 
//[ebp+8]=input 
//[ebp+c]=address of output 
push eax 
push ebx 
mov eax,[ebp+8] //load the value into eax 
mov ebx,[ebp+c] //load the address into ebx 
bswap eax 
mov [ebx],eax //write the value into the address 
pop ebx 
pop eax 

pop ebp 
ret 8 
[/32-bit] 

[64-bit] 
//ecx=input 
//rdx=address of output 
bswap ecx 
mov [rdx],ecx //place the integer the 4 bytes pointed to by rdx 
ret 
[/64-bit]

按下确定了过后,简单的设置就完成了!

你的数值类型应该会有3个新的选项

下一次扫描 RPCS3 游戏里的数据时,你便可以用逆向字节或逆向浮游。

接下来我们将会实践扫描 EXVSFB 里的数值,开启无限生命值等等。

Leave a comment

Design a site like this with WordPress.com
Get started