简体   繁体   English

C++ 从模块大小的进程中读取所有 memory

[英]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:我的问题是:

  • Is GetModuleSize an incorrect way of calculating the last address for the application? GetModuleSize 是计算应用程序最后地址的不正确方法吗? If so, can I correct it?如果是这样,我可以纠正它吗?
  • By multiplying the last address with 2, I was able to read the value of &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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM