[英]C++ read all memory from process within modulesize
I have been trying to read all memory addresses within a process range only, (see question: C++ read memory addresses within process range only ).我一直在尝试仅读取进程范围内的所有 memory 地址(请参阅问题: C++ 仅读取进程范围内的 memory 地址)。 I succeeded with reading from memory and it seems like I received the correct baseaddress
for the process.我成功地从baseaddress
读取,似乎我收到了正确的进程基地址。 The problem I was having was to find specific values which I assumed the program would have.我遇到的问题是找到我认为程序会有的特定值。
For example if I played a game and had the score 500 , I wanted to find 500 in the memory.例如,如果我玩了一个游戏并且得分为500 ,我想在 memory 中找到500 。 I stepped through all the addresses but could not find the value.我遍历了所有地址,但找不到值。 So I decided to read my own program (which is 64-bit) and set a value to 500 , print its address and manually search and see if I found it.所以我决定阅读我自己的程序(它是 64 位的)并将一个值设置为500 ,打印它的地址并手动搜索,看看我是否找到它。
int number = 500;
std::cout << &number;
For some reason the address it was written to was out of bounds of the process range.由于某种原因,它写入的地址超出了进程范围。
I calculate the address range with:我计算地址范围:
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);
Methods used:使用的方法:
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;
}
and和
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;
}
Since the value of number
is written out of bounds I assume that GetModuleSize
, might be incorrect.由于number
的值超出范围,我假设GetModuleSize
可能不正确。
Last address for me is: 0x4F4628
, std::cout << &number;
我的最后一个地址是: 0x4F4628
, std::cout << &number;
gives me 0x6DFDD4
给我0x6DFDD4
My questions are:我的问题是:
&number
.通过将最后一个地址乘以 2,我能够读取&number
的值。 Is this because modulesize gives me a 32-bit range or is this giving me addresses out of bounds for the process?这是因为 modulesize 给了我一个 32 位的范围,还是给我的地址超出了进程的范围? I compile with: g++ main.cpp -ox -lpsapi -DUNICODE -m64
, and had to add libgcc_s_seh-1.dll
to my path in order to run my program.我编译时使用: g++ main.cpp -ox -lpsapi -DUNICODE -m64
,并且必须将libgcc_s_seh-1.dll
添加到我的路径中才能运行我的程序。
My entire project on github: https://github.com/Darclander/memory-reading我在 github 上的整个项目: https://github.com/Darclander/memory-reading
(Not sure if it is better for me to post the entire code on here). (不确定在这里发布整个代码对我来说是否更好)。
A "module" in WIN32 terms is an executable image file. WIN32 术语中的“模块”是可执行映像文件。 This image contains things like code, static variables, stack unwind tables and more.此图像包含代码、static 变量、堆栈展开表等内容。 The value you are attempting to read is a local variable and thus will be allocated on the stack.您尝试读取的值是局部变量,因此将在堆栈上分配。 The stack is not part of the image, so you won't find it there.堆栈不是图像的一部分,所以你不会在那里找到它。
What you need to do is find the address and size of the stack.您需要做的是找到堆栈的地址和大小。 See How can I locate a process' global and stack areas in Win32?请参阅如何在 Win32 中定位进程的全局和堆栈区域? on how to do that.关于如何做到这一点。
You probably also want to read the heap in addition to the stack, you can find all open heaps by using GetProcessHeaps and get the addresses/sizes with HeapSummary .除了堆栈之外,您可能还想读取堆,您可以使用GetProcessHeaps找到所有打开的堆,并使用HeapSummary获取地址/大小。
As @para said, the module is a image of PE file.正如@para 所说,该模块是PE文件的图像。
The variable you want to read is stored on the current thread stack, you will need to get the base address and limit address of the stack, with NtQueryInformationThread
你要读取的变量存储在当前线程栈中,你需要获取栈的基地址和限制地址,用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;
}
Process module sample:流程模块示例:
#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;
}
Result:结果:
If you do not know the specific thread ID, you can refer to this document to Traversing the Thread List如果不知道具体的线程ID,可以参考这篇文档遍历线程列表
(Note: NtQueryInformationThread
may be altered or unavailable in future versions of Windows. ) (注意:在 Windows 的未来版本中, NtQueryInformationThread
可能会被更改或不可用。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.