[英]C++ read all memory from process within modulesize
我一直在嘗試僅讀取進程范圍內的所有 memory 地址(請參閱問題: C++ 僅讀取進程范圍內的 memory 地址)。 我成功地從baseaddress
讀取,似乎我收到了正確的進程基地址。 我遇到的問題是找到我認為程序會有的特定值。
例如,如果我玩了一個游戲並且得分為500 ,我想在 memory 中找到500 。 我遍歷了所有地址,但找不到值。 所以我決定閱讀我自己的程序(它是 64 位的)並將一個值設置為500 ,打印它的地址並手動搜索,看看我是否找到它。
int number = 500;
std::cout << &number;
由於某種原因,它寫入的地址超出了進程范圍。
我計算地址范圍:
uintptr_t moduleBase = GetModuleBaseAddress(procId, L"x.exe");
uintptr_t moduleSize = GetModuleSize(procId, L"x.exe");
// Set base and last address and print them for user
uintptr_t dynamicPtrBaseAddr = moduleBase;
uintptr_t dynamicPtrLastAddr = (moduleBase + moduleSize);
使用的方法:
uintptr_t GetModuleSize(DWORD procId, const wchar_t* modName) {
uintptr_t modBaseSize = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | 0x10, procId);
if(hSnap != INVALID_HANDLE_VALUE) {
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if(Module32First(hSnap, &modEntry)) {
do {
if(!_wcsicmp(modEntry.szModule, modName)) {
modBaseSize = (uintptr_t)modEntry.modBaseSize;
break;
}
} while(Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseSize;
}
和
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName) {
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | 0x10, 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;
}
由於number
的值超出范圍,我假設GetModuleSize
可能不正確。
我的最后一個地址是: 0x4F4628
, std::cout << &number;
給我0x6DFDD4
我的問題是:
&number
的值。 這是因為 modulesize 給了我一個 32 位的范圍,還是給我的地址超出了進程的范圍? 我編譯時使用: g++ main.cpp -ox -lpsapi -DUNICODE -m64
,並且必須將libgcc_s_seh-1.dll
添加到我的路徑中才能運行我的程序。
我在 github 上的整個項目: https://github.com/Darclander/memory-reading
(不確定在這里發布整個代碼對我來說是否更好)。
WIN32 術語中的“模塊”是可執行映像文件。 此圖像包含代碼、static 變量、堆棧展開表等內容。 您嘗試讀取的值是局部變量,因此將在堆棧上分配。 堆棧不是圖像的一部分,所以你不會在那里找到它。
您需要做的是找到堆棧的地址和大小。 請參閱如何在 Win32 中定位進程的全局和堆棧區域? 關於如何做到這一點。
除了堆棧之外,您可能還想讀取堆,您可以使用GetProcessHeaps找到所有打開的堆,並使用HeapSummary獲取地址/大小。
正如@para 所說,該模塊是PE文件的圖像。
你要讀取的變量存儲在當前線程棧中,你需要獲取棧的基地址和限制地址,用NtQueryInformationThread
#include <windows.h>
#include <iostream>
#include <winternl.h>
#include <tlhelp32.h>
#pragma warning(disable : 4996)
using namespace std;
typedef enum _mTHREADINFOCLASS {
ThreadBasicInformation = 0
} mTHREADINFOCLASS;
typedef struct _mTEB {
NT_TIB Tib;
PVOID EnvironmentPointer;
CLIENT_ID Cid;
PVOID ActiveRpcInfo;
PVOID ThreadLocalStoragePointer;
PPEB Peb;
ULONG LastErrorValue;
ULONG CountOfOwnedCriticalSections;
PVOID CsrClientThread;
PVOID Win32ThreadInfo;
ULONG Win32ClientInfo[0x1F];
PVOID WOW32Reserved;
ULONG CurrentLocale;
ULONG FpSoftwareStatusRegister;
PVOID SystemReserved1[0x36];
PVOID Spare1;
ULONG ExceptionCode;
ULONG SpareBytes1[0x28];
PVOID SystemReserved2[0xA];
ULONG GdiRgn;
ULONG GdiPen;
ULONG GdiBrush;
CLIENT_ID RealClientId;
PVOID GdiCachedProcessHandle;
ULONG GdiClientPID;
ULONG GdiClientTID;
PVOID GdiThreadLocaleInfo;
PVOID UserReserved[5];
PVOID GlDispatchTable[0x118];
ULONG GlReserved1[0x1A];
PVOID GlReserved2;
PVOID GlSectionInfo;
PVOID GlSection;
PVOID GlTable;
PVOID GlCurrentRC;
PVOID GlContext;
NTSTATUS LastStatusValue;
UNICODE_STRING StaticUnicodeString;
WCHAR StaticUnicodeBuffer[0x105];
PVOID DeallocationStack;
PVOID TlsSlots[0x40];
LIST_ENTRY TlsLinks;
PVOID Vdm;
PVOID ReservedForNtRpc;
PVOID DbgSsReserved[0x2];
ULONG HardErrorDisabled;
PVOID Instrumentation[0x10];
PVOID WinSockData;
ULONG GdiBatchCount;
ULONG Spare2;
ULONG Spare3;
ULONG Spare4;
PVOID ReservedForOle;
ULONG WaitingOnLoaderLock;
PVOID StackCommit;
PVOID StackCommitMax;
PVOID StackReserved;
} mTEB;
typedef NTSTATUS (WINAPI *fpNtQueryInformationThread)(
IN HANDLE ThreadHandle,
IN mTHREADINFOCLASS ThreadInformationClass,
OUT PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength
);
typedef struct _THREAD_BASIC_INFORMATION {
NTSTATUS ExitStatus;
mTEB* TebBaseAddress;
CLIENT_ID ClientId;
KAFFINITY AffinityMask;
KPRIORITY Priority;
KPRIORITY BasePriority;
} THREAD_BASIC_INFORMATION, * PTHREAD_BASIC_INFORMATION;
void fun()
{
return;
}
int main()
{
DWORD pid = 21112;//process id
DWORD tid = 5512;//thread id
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if (hProcess == NULL)
{
int error = GetLastError();
cout << "OpenProcess error: " << error << endl;
}
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,false, tid);
if (hThread == NULL)
{
int error = GetLastError();
cout << "OpenThread error: " << error << endl;
}
HMODULE h = LoadLibrary(L"ntdll.dll");
fpNtQueryInformationThread NtQueryInformationThread = (fpNtQueryInformationThread)GetProcAddress(h,"NtQueryInformationThread");
THREAD_BASIC_INFORMATION info = { 0 };
NTSTATUS ret = NtQueryInformationThread(hThread, ThreadBasicInformation, &info, sizeof(THREAD_BASIC_INFORMATION), NULL);
NT_TIB tib = { 0 };
if (!ReadProcessMemory(hProcess, info.TebBaseAddress, &tib, sizeof(NT_TIB), nullptr))
{
int error = GetLastError();
cout << "ReadProcessMemory error: " << error << endl;
}
cout << tib.StackLimit << " to " << tib.StackBase << endl;
return 0;
}
流程模塊示例:
#include <windows.h>
#include <iostream>
int main()
{
int number = 500;
std::cout << &number << std::endl;
std::cout << "Pid = " << GetCurrentProcessId() << std::endl;
std::cout << "Tid = " << GetCurrentThreadId() << std::endl;
getchar();
return 0;
}
結果:
如果不知道具體的線程ID,可以參考這篇文檔遍歷線程列表
(注意:在 Windows 的未來版本中, NtQueryInformationThread
可能會被更改或不可用。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.