簡體   English   中英

C++ 從模塊大小的進程中讀取所有 memory

[英]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

我的問題是:

  • GetModuleSize 是計算應用程序最后地址的不正確方法嗎? 如果是這樣,我可以糾正它嗎?
  • 通過將最后一個地址乘以 2,我能夠讀取&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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM