将数据写入 C 中另一个程序的指针?
Write data to a pointer of another program in C?
我目前正在学习 C,尤其是内存的工作原理,以及我如何写入和读取程序使用的数据。为了练习,我开始为游戏 Undertale 编写一个小作弊程序,它会不断地用最大健康值覆盖健康地址,这将使角色立于不败之地。我用Cheat Engine搜索了健康值的地址,现在我有这个代码:
#include <stdio.h>
#include <Windows.h>
int main(void) {
printf("\n");
double MAXHEALTH = 20;
HWND hwnd = FindWindowA(NULL, "UNDERTALE");
if(hwnd == NULL) {
printf("ERROR: COULD NOT FIND GAME WINDOW. PLEASE OPEN THE GAME.\n");
return 1;
}
printf("[+] Undertale window found\n");
DWORD processID;
GetWindowThreadProcessId(hwnd, &processID);
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
if (processID == NULL) {
printf("ERROR: COULD NOT HANDLE PROCESS.\n");
return 1;
}
printf("[+] Obtained handle\n");
while(1) {
printf("[*] Writing max health value to health address..\n");
WriteProcessMemory(handle, (LPVOID)0x049B2F8, &MAXHEALTH, sizeof(MAXHEALTH), 0);
printf("[+] Done!\n");
}
return 0;
}
并且有效。糟糕的是,当你关闭游戏并重新打开它时,所有的地址都不一样......那不是很有效。所以我想尝试使用Cheat Engine来查找健康值的基地址。我进行了多次指针扫描,并将结果缩小到大约 150 个地址,指向健康地址。我尝试随机选择一个,关闭游戏,重新打开它,它起作用了:我可以使用我找到的指针修改健康值。
所以我想我会在我的代码中使用它。在指针扫描window中的"Base Address"下显示"UNDERTALE.exe"+059E4F8
。我尝试用指针的地址替换我的代码中的地址(我输入 (LPVOID)0x059E4F8
),但是没有用。输出重复说“[+] Done!
”,但健康值没有改变,而它在 Cheat Engine 中工作......我是整个内存管理的新手,我做错了什么?我想做的事有可能吗?
我希望我对我所做的一切的解释足够清楚,如果没有,请告诉我。
谢谢。
好的,我找到了如何做我想做的事。我终于明白了(也许这很明显但是嘿)我发现的第一个指针只是 5 个指针链中的第一个,我必须遵循它才能到达健康地址。所以我读取每个指针包含的值来查找下一个,直到最终到达正确的健康地址。现在每次我 运行 游戏时我的作弊都会起作用 :) .
我的代码(我知道它没有优化,我可以使用 for 循环,但它只是为了测试目的。):
#include <stdio.h>
#include <Windows.h>
int main(void) {
printf("\n");
LPVOID readPointer;
double health;
int pointerval = 0x00400000 + 0x0059E470 ; //UNDERTALE.exe base address + first offset to get to first pointer
HWND hwnd = FindWindowA(NULL, "UNDERTALE");
if(hwnd == NULL) {
printf("ERROR: COULD NOT FIND GAME WINDOW. PLEASE OPEN THE GAME.\n");
return 1;
}
printf("[+] Undertale window found\n");
DWORD procID;
GetWindowThreadProcessId(hwnd, &procID);
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
if (procID == NULL) {
printf("ERROR: COULD NOT OBTAIN HANDLE FOR PROCESS.\n");
return 1;
}
printf("[+] Obtained handle\n");
printf("[*] Following pointer chain...\n");
printf("[*] Reading pointer 1 value from memory at address 0x%p...\n", pointerval);
ReadProcessMemory(handle, (PVOID*)pointerval, &readPointer, sizeof(readPointer), 0);
pointerval = (int*)readPointer;
printf("Pointer 1 value: 0x%p\n", pointerval);
printf("Applying offset 0x98..\n\n");
pointerval += 0x98;
printf("[*] Reading pointer 2 value from memory at address 0x%p...\n", pointerval);
ReadProcessMemory(handle, (PVOID*)pointerval, &readPointer, sizeof(readPointer), 0);
pointerval = (int*)readPointer;
printf("Pointer 2 value: 0x%p\n", pointerval);
printf("Applying offset 0xC..\n\n");
pointerval += 0xC;
printf("[*] Reading pointer 3 value from memory at address 0x%p...\n", pointerval);
ReadProcessMemory(handle, (PVOID*)pointerval, &readPointer, sizeof(readPointer), 0);
pointerval = (int*)readPointer;
printf("Pointer 3 value: 0x%p\n", pointerval);
printf("Applying offset 0x4..\n\n");
pointerval += 0x4;
printf("[*] Reading pointer 4 value from memory at address 0x%p...\n", pointerval);
ReadProcessMemory(handle, (PVOID*)pointerval, &readPointer, sizeof(readPointer), 0);
pointerval = (int*)readPointer;
printf("Pointer 4 value: 0x%p\n", pointerval);
printf("Applying offset 0x1D0..\n\n");
pointerval += 0x1D0;
printf("[+] Pointer chain over: health address is 0x%p.\n\n",pointerval);
printf("[*] Reading actual health value\n");
ReadProcessMemory(handle, (PVOID*)pointerval, &health, sizeof(health), 0);
printf("[+] Actual health value: %f\n\n",health);
printf("[*] Writing health value to health address repeatedly..\n");
printf("[+] God mode activated ;)\n");
while(1) {
WriteProcessMemory(handle, (LPVOID)pointerval, &health, sizeof(health), 0);
}
return 0;
}
我目前正在学习 C,尤其是内存的工作原理,以及我如何写入和读取程序使用的数据。为了练习,我开始为游戏 Undertale 编写一个小作弊程序,它会不断地用最大健康值覆盖健康地址,这将使角色立于不败之地。我用Cheat Engine搜索了健康值的地址,现在我有这个代码:
#include <stdio.h>
#include <Windows.h>
int main(void) {
printf("\n");
double MAXHEALTH = 20;
HWND hwnd = FindWindowA(NULL, "UNDERTALE");
if(hwnd == NULL) {
printf("ERROR: COULD NOT FIND GAME WINDOW. PLEASE OPEN THE GAME.\n");
return 1;
}
printf("[+] Undertale window found\n");
DWORD processID;
GetWindowThreadProcessId(hwnd, &processID);
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
if (processID == NULL) {
printf("ERROR: COULD NOT HANDLE PROCESS.\n");
return 1;
}
printf("[+] Obtained handle\n");
while(1) {
printf("[*] Writing max health value to health address..\n");
WriteProcessMemory(handle, (LPVOID)0x049B2F8, &MAXHEALTH, sizeof(MAXHEALTH), 0);
printf("[+] Done!\n");
}
return 0;
}
并且有效。糟糕的是,当你关闭游戏并重新打开它时,所有的地址都不一样......那不是很有效。所以我想尝试使用Cheat Engine来查找健康值的基地址。我进行了多次指针扫描,并将结果缩小到大约 150 个地址,指向健康地址。我尝试随机选择一个,关闭游戏,重新打开它,它起作用了:我可以使用我找到的指针修改健康值。
所以我想我会在我的代码中使用它。在指针扫描window中的"Base Address"下显示"UNDERTALE.exe"+059E4F8
。我尝试用指针的地址替换我的代码中的地址(我输入 (LPVOID)0x059E4F8
),但是没有用。输出重复说“[+] Done!
”,但健康值没有改变,而它在 Cheat Engine 中工作......我是整个内存管理的新手,我做错了什么?我想做的事有可能吗?
我希望我对我所做的一切的解释足够清楚,如果没有,请告诉我。
谢谢。
好的,我找到了如何做我想做的事。我终于明白了(也许这很明显但是嘿)我发现的第一个指针只是 5 个指针链中的第一个,我必须遵循它才能到达健康地址。所以我读取每个指针包含的值来查找下一个,直到最终到达正确的健康地址。现在每次我 运行 游戏时我的作弊都会起作用 :) .
我的代码(我知道它没有优化,我可以使用 for 循环,但它只是为了测试目的。):
#include <stdio.h>
#include <Windows.h>
int main(void) {
printf("\n");
LPVOID readPointer;
double health;
int pointerval = 0x00400000 + 0x0059E470 ; //UNDERTALE.exe base address + first offset to get to first pointer
HWND hwnd = FindWindowA(NULL, "UNDERTALE");
if(hwnd == NULL) {
printf("ERROR: COULD NOT FIND GAME WINDOW. PLEASE OPEN THE GAME.\n");
return 1;
}
printf("[+] Undertale window found\n");
DWORD procID;
GetWindowThreadProcessId(hwnd, &procID);
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
if (procID == NULL) {
printf("ERROR: COULD NOT OBTAIN HANDLE FOR PROCESS.\n");
return 1;
}
printf("[+] Obtained handle\n");
printf("[*] Following pointer chain...\n");
printf("[*] Reading pointer 1 value from memory at address 0x%p...\n", pointerval);
ReadProcessMemory(handle, (PVOID*)pointerval, &readPointer, sizeof(readPointer), 0);
pointerval = (int*)readPointer;
printf("Pointer 1 value: 0x%p\n", pointerval);
printf("Applying offset 0x98..\n\n");
pointerval += 0x98;
printf("[*] Reading pointer 2 value from memory at address 0x%p...\n", pointerval);
ReadProcessMemory(handle, (PVOID*)pointerval, &readPointer, sizeof(readPointer), 0);
pointerval = (int*)readPointer;
printf("Pointer 2 value: 0x%p\n", pointerval);
printf("Applying offset 0xC..\n\n");
pointerval += 0xC;
printf("[*] Reading pointer 3 value from memory at address 0x%p...\n", pointerval);
ReadProcessMemory(handle, (PVOID*)pointerval, &readPointer, sizeof(readPointer), 0);
pointerval = (int*)readPointer;
printf("Pointer 3 value: 0x%p\n", pointerval);
printf("Applying offset 0x4..\n\n");
pointerval += 0x4;
printf("[*] Reading pointer 4 value from memory at address 0x%p...\n", pointerval);
ReadProcessMemory(handle, (PVOID*)pointerval, &readPointer, sizeof(readPointer), 0);
pointerval = (int*)readPointer;
printf("Pointer 4 value: 0x%p\n", pointerval);
printf("Applying offset 0x1D0..\n\n");
pointerval += 0x1D0;
printf("[+] Pointer chain over: health address is 0x%p.\n\n",pointerval);
printf("[*] Reading actual health value\n");
ReadProcessMemory(handle, (PVOID*)pointerval, &health, sizeof(health), 0);
printf("[+] Actual health value: %f\n\n",health);
printf("[*] Writing health value to health address repeatedly..\n");
printf("[+] God mode activated ;)\n");
while(1) {
WriteProcessMemory(handle, (LPVOID)pointerval, &health, sizeof(health), 0);
}
return 0;
}