Memory 使用与上一次打开完全相同的地址结构启动进程
是否可以在windows中启动与前一个进程打开时地址结构完全相同的进程Memory 使用与上一次打开完全相同的地址结构启动进程,memory,ram,Memory,Ram,是否可以在windows中启动与前一个进程打开时地址结构完全相同的进程 为了澄清这个问题的目的,我应该提到我使用cheatengine()来欺骗一些游戏!它包括几次迭代以查找参数(例如弹药)并将其冻结。但是,每次我重新启动游戏时,由于游戏的内存结构发生变化,我需要再次经历耗时的迭代。因此,如果有一种方法使用与以前完全相同的内存结构来启动游戏,我就不需要进行迭代。不是说这是不可能的,但由于进程将使用动态内存分配例程(包括新操作符和malloc()),这实际上是太多的工作。此外,当可执行文件导入的D
为了澄清这个问题的目的,我应该提到我使用cheatengine()来欺骗一些游戏!它包括几次迭代以查找参数(例如弹药)并将其冻结。但是,每次我重新启动游戏时,由于游戏的内存结构发生变化,我需要再次经历耗时的迭代。因此,如果有一种方法使用与以前完全相同的内存结构来启动游戏,我就不需要进行迭代。不是说这是不可能的,但由于进程将使用动态内存分配例程(包括新操作符和malloc()),这实际上是太多的工作。此外,当可执行文件导入的DLL加载到内存中时,它们具有首选的imagebase,但如果该地址已被使用,则操作系统会将其加载到不同的内存位置。此外,可以在进程上启用地址空间布局随机化(ASLR),这是一种将代码段的内存地址随机化的安全措施 解决你的问题比你所问的要容易得多。要解决上述动态内存分配问题,您仍然可以利用以下方法解析变量的正确地址:
- 与模块基座的相对偏移量
- 多级指针
- 模式扫描
uintptr_t GetModuleBase(const wchar_t * ModuleName, DWORD ProcessId) {
// This structure contains lots of goodies about a module
MODULEENTRY32 ModuleEntry = { 0 };
// Grab a snapshot of all the modules in the specified process
HANDLE SnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessId);
if (!SnapShot)
return NULL;
// You have to initialize the size, otherwise it will not work
ModuleEntry.dwSize = sizeof(ModuleEntry);
// Get the first module in the process
if (!Module32First(SnapShot, &ModuleEntry))
return NULL;
do {
// Check if the module name matches the one we're looking for
if (!wcscmp(ModuleEntry.szModule, ModuleName)) {
// If it does, close the snapshot handle and return the base address
CloseHandle(SnapShot);
return (DWORD)ModuleEntry.modBaseAddr;
}
// Grab the next module in the snapshot
} while (Module32Next(SnapShot, &ModuleEntry));
// We couldn't find the specified module, so return NULL
CloseHandle(SnapShot);
return NULL;
}
要获取进程ID,请执行以下操作:
bool GetPid(const wchar_t* targetProcess, DWORD* procID)
{
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap && snap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(snap, &pe))
{
do
{
if (!wcscmp(pe.szExeFile, targetProcess))
{
CloseHandle(snap);
*procID = pe.th32ProcessID;
return true;
}
} while (Process32Next(snap, &pe));
}
}
return false;
}
使用我的示例,您可以组合这些函数并执行以下操作:
DWORD procId;
GetPid(L"game.exe", &procId);
uintptr_t modBaseAddr = GetModuleBase(L"client.dll", procId);
uintptr_t ammoAddr = modBaseAddr + 0xDEADCODE;
如果地址不是“静态”的,您可以找到指向它的指针,指针的基址必须是静态的,然后您只需按照上面的指南,取消对指针的每个级别的引用并添加偏移量
当然我也有一个函数:)
uintpttr\u t FindDmaAddy(句柄hProcHandle,uintpttr\u t基地址,uintptpr\u t偏移量[],int PointerLevel)
{
uintptr_t指针=基址;
uintptr_t pTemp;
uintptr_t pointerAddr;
for(int i=0;i
我强烈建议您观看一些Youtube教程,看看它是如何完成的,更好地用视频格式进行解释。即使您让操作系统保持一切不变,您也无法阻止进程自行做出会影响地址结构的决定。我建议你通过做一些事情来学习编程,而不是试图在游戏中作弊(这是一个非常高级的话题)。亲爱的,事实上,这种作弊是作为一个商业项目进行的,我应该提取一些游戏参数,以便能够控制一些外围设备!无论如何,谢谢你的建议:-)在这种情况下,你可以与游戏供应商合作,获得你所需要的;无论如何,谢谢你的详尽回答。
uintptr_t FindDmaAddy(HANDLE hProcHandle, uintptr_t BaseAddress, uintptr_t Offsets[], int PointerLevel)
{
uintptr_t pointer = BaseAddress;
uintptr_t pTemp;
uintptr_t pointerAddr;
for (int i = 0; i < PointerLevel; i++)
{
if (i == 0)
{
ReadProcessMemory(hProcHandle, (LPCVOID)pointer, &pTemp, sizeof(pTemp), NULL);
}
pointerAddr = pTemp + Offsets[i];
ReadProcessMemory(hProcHandle, (LPCVOID)pointerAddr, &pTemp, sizeof(pTemp), NULL);
}
return pointerAddr;
}