如何制作内存hack(Minecraft Windows 10)
首先
我将写下关于简单的内存修改技巧。没有什么特别的动机。请自行承担责任进行尝试。
这次我打算写下最简单的实施方式,即实现缩放功能(在Visual Studio中)。
“Memory hacking” refers to
记忆破解是指
Windows上のプロセスの仮想メモリに無理やり書き込み&読み込みをすることで、プロセスの挙動を変えることです。
簡単ですね。それでは具体的にコードを書いていきましょう。
获取基址地址和进程句柄
在Windows系统上,执行一个进程会被分配一个进程ID。可以使用这个进程ID来获取基址和进程句柄。
#include <iostream>
#include <Windows.h>
#include <vector>
#include <TlHelp32.h>
uintptr_t GetProcId(const wchar_t* procname) //プロセスID取得
{
DWORD ProcId = 0;
HANDLE hSnap = (CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
if (hSnap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 procentry;
procentry.dwSize = sizeof(procentry);
if (Process32First(hSnap, &procentry))
{
do
{
if (!_wcsicmp(procentry.szExeFile, procname))
{
ProcId = procentry.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &procentry));
}
}
CloseHandle(hSnap);
return ProcId;
}
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)//ベースアドレス取得
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
if (!_wcsicmp(modEntry.szModule, modName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
int main()
{
DWORD procId = GetProcId(L"Minecraft.Windows.exe");//実行中のMinecraft.Windows.exeのプロセスID
uintptr_t BaseAddress = GetModuleBaseAddress(procId, L"Minecraft.Windows.exe");//ベースアドレスの取得
if (BaseAddress != NULL) {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, procId);//プロセスハンドル取得
}
return 0;
}
接下来我们会继续使用进程ID、基址和进程句柄,所以要先保留它们。
全球键盘钩子的使用方法
一番簡単な方法でやります。
while (true)
{
if (GetAsyncKeyState(67)) {//仮想キーコードを入れる今回はC
}
}
ポインターからアドレス取得
ポインターとは毎回プロセスが起動するとアドレスが変わるので、アドレスを計算するために必要なものです。
ポインターを取得する方法は次の記事で詳しく書きます。ここ
ここではそのポインターからアドレスを導き出す関数を書きます。
uintptr_t FindDMAAddy(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
uintptr_t addr = ptr;
for (unsigned int i = 0; i < offsets.size(); ++i)
{
ReadProcessMemory(hProc, (BYTE*)addr, &addr, sizeof(addr), 0);
addr += offsets[i];
}
return addr;
}
関数はこれだけです。使い方は
uintptr_t fovdirectadd = 0x0369BD40;
vector<unsigned int> fovoffset = { 0x28,0x130,0x1E8 };
int main()
{
DWORD procId = GetProcId(L"Minecraft.Windows.exe");//実行中のMinecraft.Windows.exeのプロセスID
uintptr_t BaseAddress = GetModuleBaseAddress(procId, L"Minecraft.Windows.exe");//ベースアドレスの取得
if (BaseAddress != NULL) {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, procId);//プロセスハンドル取得
uintptr_t fovaddr = FindDMAAddy(hProcess, BaseAddress + fovdirectadd, fovoffset);//これが欲しいアドレスです
}
return 0;
}
写入
準備はできましたそれでは書き込みをしてみましょう
WriteProcessMemory(hProcess, (BYTE*)Address, &value, sizeof(value), nullptr);
这是用于写入的API。
Address代表地址,value则是想要输入的值的指针,sizeof(value)表示输入值的长度。
整体代码
#include <iostream>
#include <Windows.h>
#include <vector>
#include <TlHelp32.h>
using namespace std;
uintptr_t GetProcId(const wchar_t* procname) //プロセスID取得
{
DWORD ProcId = 0;
HANDLE hSnap = (CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
if (hSnap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 procentry;
procentry.dwSize = sizeof(procentry);
if (Process32First(hSnap, &procentry))
{
do
{
if (!_wcsicmp(procentry.szExeFile, procname))
{
ProcId = procentry.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &procentry));
}
}
CloseHandle(hSnap);
return ProcId;
}
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)//ベースアドレス取得
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
if (!_wcsicmp(modEntry.szModule, modName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
uintptr_t fovdirectadd = 0x0369BD40;
vector<unsigned int> fovoffset = { 0x28,0x130,0x1E8 };
uintptr_t FindDMAAddy(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
uintptr_t addr = ptr;
for (unsigned int i = 0; i < offsets.size(); ++i)
{
ReadProcessMemory(hProc, (BYTE*)addr, &addr, sizeof(addr), 0);
addr += offsets[i];
}
return addr;
}
int main()
{
DWORD procId = GetProcId(L"Minecraft.Windows.exe");//実行中のMinecraft.Windows.exeのプロセスID
uintptr_t BaseAddress = GetModuleBaseAddress(procId, L"Minecraft.Windows.exe");//ベースアドレスの取得
if (BaseAddress != NULL) {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, procId);//プロセスハンドル取得
uintptr_t fovaddr = FindDMAAddy(hProcess, BaseAddress + fovdirectadd, fovoffset);//これが欲しいアドレスです
float value = 0.0f;
while (true)
{
if (GetAsyncKeyState(67)) {
value = 30.0f;
WriteProcessMemory(hProcess, (BYTE*)fovaddr, &value, sizeof(value), nullptr);
}
else {
value = 110.0f;
WriteProcessMemory(hProcess, (BYTE*)fovaddr, &value, sizeof(value), nullptr);
}
}
}
return 0;
}
最后
我们使用这种技术几乎可以做任何事情。甚至可以轻松制作恶意黑客软件。所以请绝对不要滥用。指针扫描的方法将在下次讲解。
请参考
引导式的黑客攻击
获取异步按键状态