Question on querying memory regions (Windows) - c++

I had written a program that enumerates all the memory regions of a process with the following attributes: MEM_COMMIT and PAGE_READWRITE, and that at the end of the program prints the total size of all the regions found, everything seems to work well, then I tried it on programs at 64 bits and it turned out that the total regions size was greater than the RAM available on my PC.
On my PC there are 15.9GB of RAM available while one of the scans that I made was 18.363.846.656 Byte (18.3 GB).
I wonder, how is it possible? is it a mistake in my code, or are they using some memory management methods that I am not aware of?
#include <iostream>
#include <Windows.h>
int main()
{
// Get an handle to the process
HWND hWnd = FindWindowA(NULL, "WindowName");
DWORD pid; GetWindowThreadProcessId(hWnd, &pid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
// Declaration of some variables
char* Ptr(0);
MEMORY_BASIC_INFORMATION Mem;
size_t totalSize = 0;
// Start querying
while (VirtualQueryEx(hProcess, Ptr, &Mem, sizeof(MEMORY_BASIC_INFORMATION)))
{
if (Mem.State == MEM_COMMIT && Mem.Protect == PAGE_READWRITE)
{
totalSize += Mem.RegionSize;
std::cout << std::hex << Mem.BaseAddress << " - " << (LPVOID)(Mem.RegionSize + (INT64)Mem.BaseAddress) << " - size:(" << std::dec << Mem.RegionSize << ")\n";
}
Ptr += Mem.RegionSize;
}
std::cout << "[" << totalSize << "]";
CloseHandle(hProcess);
return 0;
}

You cannot query physical memory using any normal documented Windows API functions. Virtual Memory is intended to be an abstraction, the Operating System is meant to handle all this in the background for you.
There is RAMMap from SysInternals which can display information regarding physical memory but the source code is not public. RAMMap is explained in this video from Microsoft
To learn more about how the system works you can look up "physical memory" in the Windows Internals book.
There is some code in this answer which claims to be able to query physical memory from usermode here using NtOpenSection and NtMapViewOfSection.
To interact with physical memory from a kernel driver you can read this source code

Related

When injected into a program's memory space, how do you read each byte from 0 to 0xFFFFFFFFF? I am creating a pattern scanner

I am trying to create a pattern scanner, to find every byte sequence starting with "MZ" (4d5a) inside a programs memory. For that I'm injecting a DLL into the target program.
I try to look for the "MZ" pattern as I see some sneaky modules that are unlinking themselves from the modulelist.
From within the program's memory space I was hoping to iterate from 0 to 0xFFFFFFFFF and check for byte patterns. By simply doing something like this:
unsigned i = 0;
while (i < 0xFFFFFFFFF) {
if ((BYTE*) i != NULL) {
std::cout << "Print byte: " << ConvertToHexString( (BYTE*) i) << std::endl;
}
i++;
}
ConvertToHexString successfully converts (BYTE*) to std::string.
I thought it was that easy, even if I hit memory I wasn't allowed to read. I thought my NULL check was sufficient. Seemed it was not. However, if I start from the modulebase (uintptr_t pModuleBase = (uintptr_t)GetModuleHandle(NULL)), I can actually see the bytes.
Below is my code:
DllMain:
BOOL APIENTRY DllMain(
...snip...
CloseHandle(CreateThread(0, 0, (LPTHREAD_START_ROUTINE)SignatureScanner, moduleHandle, 0, 0));
...snip...
}
SignatureScanner:
DWORD WINAPI SignatureScanner(HMODULE moduleHandle)
{
// Create Console
AllocConsole();
FILE* f;
freopen_s(&f, "CONOUT$", "w", stdout);
// Get module base
uintptr_t pModuleBase = (uintptr_t)GetModuleHandle(NULL);
while (true)
{
if (GetAsyncKeyState(VK_NUMPAD1) & 1)
{
unsigned i = 0;
while (i < 0xFFFFFFFFF) {
if ((BYTE*) i != NULL) {
std::cout << "Print byte: " << ConvertToHexString( (BYTE*) i) << std::endl;
}
i++;
}
}
if (GetAsyncKeyState(VK_NUMPAD2) & 1)
{
break;
}
Sleep(100);
}
fclose(f);
FreeConsole();
FreeLibraryAndExitThread(moduleHandle, 0);
return 0;
}
Virtual Address Space
The virtual address space for a process is the set of virtual memory
addresses that it can use. The address space for each process is
private and cannot be accessed by other processes unless it is shared.
Default Virtual Address Space for 32-bit Windows:
Low 2GB (0x00000000 through 0x7FFFFFFF) - Used by the process.
High 2GB (0x80000000 through 0xFFFFFFFF) - Used by the system.
You are trying to read the address space that does not belong to your process, try to use VirtualProtectEx + ReadProcessMemory.
In addition, It is not recommended to use CreateThread in DllMain: Dynamic-Link Library Best Practices(You don't need to inject Dll as well)
Then, we don't need to read all the address. A module is an executable file or DLL. Each process consists of one or more modules. The first module is the executable file. It is mapped into the module base address. So you could ReadProcessMemory from the module base address(Refer to PE Format.)
You could use the EnumProcessModules + GetModuleInformation to get the base address and the size of the linear space that the module occupies, in bytes.
Or You can just use EnumProcessModules + GetModuleBaseName to check modules list and confirm which module has unlinked.

Read memory from application which does not allow it

I am currently trying to read the entirety of the memory of a game which blocks calls to OpenProcess and ReadProcessMemory (I believe this is done through a windows driver/service, although I'm not sure how).
I use the following code to do try and open the process and read its memory to a file:
HANDLE process = OpenProcess(PROCESS_VM_READ, 0, pid);
if (!process) {
cout << "Failed to open process.";
return 1;
}
cout << "Successfully opened processs." << endl << "Dumping memory to mem.dmp..." << endl;
ofstream fout;
fout.open("mem.dmp");
char *base = (char *)0;
char *readCount = (char *)0;
do {
char buffer[PAGE_SIZE];
if (ReadProcessMemory(process, base, buffer, PAGE_SIZE, NULL) != 0)
{
fout << buffer;
}
base += PAGE_SIZE;
readCount++;
} while (base != 0);
if (readCount == 0) {
cout << "Warning: No memory was read from the process." << endl;
}
fout.flush();
fout.close();
However, when run, this cannot even open the process.
The only way to get past the driver blocking the process from being opened for memory reading is to dump the entirety of the physical memory to a file. I have no idea how to do this, other than having to set windows to dump all of the physical memory on a blue screen, and then forcing my computer to shutdown with a blue screen. This is obviously quite inconvenient as I will want to analyse the application's memory quite frequently.
Is there any way to dump all of the physical memory without using this method on Windows? I know virtually nothing about the driver or how it works so it would be almost impossible to work out another way of bypassing it.
You are trying to access the "0th" memory position, that is not possible (SO does not allow you to do it):
char *base = (char *) 0;
You should set correcly the address where you wanna read, and that address must be a readable address. Check the ReadProcessMemory doc here
lpBaseAddress [in]: A pointer to the base address in the specified
process from which to read. Before any data transfer occurs, the
system verifies that all data in the base address and memory of the
specified size is accessible for read access, and if it is not
accessible the function fails.
Check also the examples in this post
here

Access Violation while calculating a pointer

I'm quite afraid the question is really, really simple, but even thou I'm starting to grip the idea of pointers, hints from experienced users shorten the time I need to spend on it to understand everything. Ive got a simple example, I won't go into details what its supposed to do later on, because I think my mistake is something very basic. I'm getting:
Exception thrown: read access violation.
_First was 0x815110.
When executing this code:
#include <Windows.h>
#include <iostream>
#include "Header.h"
#pragma comment(linker, "/SECTION:.data,RWE")
using std::cout;
using std::endl;
int main() {
DWORD dwProcessID = 0;
cout << "Looking for game process..." << endl;
while (dwProcessID == 0) {
dwProcessID = GetProcessID(L"PathOfExile.exe");
Sleep(100);
}
std::cout << "Game Client found" << std::endl;
printf("dwProcessID = %p\n", dwProcessID);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID);
MODULEENTRY32 module;
module.dwSize = sizeof(MODULEENTRY32);
Module32First(snapshot, &module);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessID);
HANDLE hToken = NULL;
if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken))
printf("Failed to open access token\n");
if (!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE))
printf("Failed to set debug privilege\n");
printf("PoE base address = %p\n", module.modBaseAddr);
BYTE jmp[] = "\xBA\x00\x00\x80\x3F\x89\x10\x89\x16\xE9\x00\x00\x00\x00";
BYTE *dwMaphack = (BYTE*)(module.modBaseAddr + 0x4D5110);
cout << dwMaphack << endl;
*(DWORD*)&jmp[10] = (DWORD)(dwMaphack - jmp) - 6;
DWORD dwOldProt;
VirtualProtectEx(hProcess, (LPVOID)dwMaphack, 8, PAGE_EXECUTE_READWRITE, &dwOldProt);
// tbc
while (1) {
}
return 0;
}
The open process methods and other basic stuff are in the header and they do work fine, what I don't get is why when I change the byte pointer BYTE *dwMaphack to DWORD *dwMaphack, there's no longer an access violation error?
I'm trying to base my code on an outdated code of someones that no longer works, so the reason for doing these operations is only partially known for me, I know what it's supposed to do in programming terms, but I don't know the effect in the game, yet. I don't think it's important in terms of the error I'm getting anyway. Thanks in advance for the answers!
BYTE is an alias for unsigned char.
std::cout has an overloaded operator<< that accepts an unsigned char* pointer as input and prints it as a character string (as stated by Harry Johnston, https://stackoverflow.com/a/41538200/7376565). So it crashes when it tries to access memory it does not have access to.
std::cout does not have an operator<< overload for DWORD* (aka unsigned long*), but it does have one for void*, so any non-character pointer will print just the value of the pointer itself. When you change dwMaphack to DWORD*, operator<< doesn't try to access the memory that dwMaphack points to, so no access violation occurs.
Here's your problem:
cout << dwMaphack << endl;
This is attempting to print the value that dwMaphack points to, not the value of the pointer. Since the pointer is only valid in the remote process, attempting to dereference it results in an access violation.
This works:
cout << (DWORD_PTR)dwMaphack << endl;

Can I use ReadProcessMemory to read program memory of a process in windows?

I have this thread running within my program's process. The thread is supposed to read this process' program memory to detect, if any forbidden code injections have occurred. Now how do I get access to the program memory of the process? Can I use the
ReadProcessMemory();
function, to read the program memory if I get the process handle with ALL_ACCESS flags?
Also is there a way to search this program memory in such way that I could limit this memory scanning to few specific method of interest or detect the base address and length for particular method?
Yes, if you get process handle with READ permissions (included in PROCESS_ALL_ACCESS) you can use ReadProcessMemory() to read the memory of the target process.
What you are looking to do is called pattern scanning. First you would use VirtualQueryEx() to find memory regions which have MEM_COMMIT as the state and do not have PAGE_NOACCESS or PAGE_GUARD as the protection type.
You loop through these memory regions using a pattern scan function to find specific signatures which you want to blacklist.
Here is the basic idea to looping through the memory
int main()
{
DWORD procid = GetProcId("whatever.exe");
MEMORY_BASIC_INFORMATION meminfo;
unsigned char* addr = 0;
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procid);
MEMORY_BASIC_INFORMATION mbi;
while (VirtualQueryEx(hProc, addr, &mbi, sizeof(mbi)))
{
if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS)
{
std::cout << "base : 0x" << std::hex << mbi.BaseAddress << " end : 0x" << std::hex << (uintptr_t)mbi.BaseAddress + mbi.RegionSize << "\n";
}
addr += mbi.RegionSize;
}
CloseHandle(hProc);
}
You can find many different pattern scanning functions to complete the job from here.

What C++ Write function should I use?

I prefer not to use XML library parser out there, so can you give me suggestion which good write function to use to write data to XML file? I will make alot of to calls to the write function so the write function should be able to keep track of the last write position and it should not take too much resource. I have two different write below but I can't keep track the last write position unless I have to read the file until end of file.
case#1
FILE *pfile = _tfopen(GetFileNameXML(), _T("w"));
if(pfile)
{
_fputts(TEXT(""), pfile);
}
if(pfile)
{
fclose(pfile);
pfile = NULL;
}
case#2
HANDLE hFile = CreateFile(GetFileNameXML(), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
WriteFile(hFile,,,,,);
}
CloseHandle(hFile);
thanks.
If all you need is to write some text files, use C++'s standard library file facilities. The samples here will be helpful: http://www.cplusplus.com/doc/tutorial/files/
First, what's your aversion to using a standard XML processing library?
Next, if you decide to roll your own, definitely don't go directly at the Win32 APIs - at least not unless you're going to write out the generated XML in large chunks, or you're going to implement your own buffering layer.
It's not going to matter for dealing with tiny files, but you specifically mention good performance and many calls to the write function. WriteFile has a fair amount of overhead, it does a lot of work and involves user->kernel->user mode switches, which are expensive. If you're dealing with "normally sized" XML files you probably won't be able to see much of a difference, but if you're generating monstrously sized dumps it's definitely something to keep in mind.
You mention tracking the last write position - first off, it should be easy... with FILE buffers you have ftell, with raw Win32 API you have SetFilePointerEx - call it with liDistanceToMove=0 and dwMoveMethod=FILE_CURRENT, and you get the current file position after a write. But why do you need this? If you're streaming out an XML file, you should generally keep on streaming until you're done writing - are you closing and re-opening the file? Or are you writing a valid XML file which you want to insert more data into later?
As for the overhead of the Win32 file functions, it may or may not be relevant in your case (depending on the size of the files you're dealing with), but with larger files it matters a lot - included below is a micro-benchmark that simpy reads a file to memory with ReadFile, letting you specify different buffer sizes from the command line. It's interesting to look at, say, Process Explorer's IO tab while running the tool. Here's some statistics from my measly laptop (Win7-SP1 x64, core2duo P7350#2.0GHz, 4GB ram, 120GB Intel-320 SSD).
Take it for what it is, a micro-benchmark. The performance might or might not matter in your particular situation, but I do believe the numbers demonstrate that there's considerable overhead to the Win32 file APIs, and that doing a little buffering of your own helps.
With a fully cached 2GB file:
BlkSz Speed
32 14.4MB/s
64 28.6MB/s
128 56MB/s
256 107MB/s
512 205MB/s
1024 350MB/s
4096 800MB/s
32768 ~2GB/s
With a "so big there will only be cache misses" 4GB file:
BlkSz Speed CPU
32 13MB/s 49%
64 26MB/s 49%
128 52MB/s 49%
256 99MB/s 49%
512 180MB/s 49%
1024 200MB/s 32%
4096 185MB/s 22%
32768 205MB/s 13%
Keep in mind that 49% CPU usage means that one CPU core is pretty much fully pegged - a single thread can't really push the machine much harder. Notice the pathological behavior of the 4kb buffer in the second table - it was reproducible, and I don't have an explanation for it.
Crappy micro-benchmark code goes here:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <string>
#include <assert.h>
unsigned getDuration(FILETIME& timeStart, FILETIME& timeEnd)
{
// duration is in 100-nanoseconds, we want milliseconds
// 1 millisecond = 1000 microseconds = 1000000 nanoseconds
LARGE_INTEGER ts, te, res;
ts.HighPart = timeStart.dwHighDateTime; ts.LowPart = timeStart.dwLowDateTime;
te.HighPart = timeEnd.dwHighDateTime; te.LowPart = timeEnd.dwLowDateTime;
res.QuadPart = ((te.QuadPart - ts.QuadPart) / 10000);
assert(res.QuadPart < UINT_MAX);
return res.QuadPart;
}
int main(int argc, char* argv[])
{
if(argc < 2) {
puts("Syntax: ReadFile [filename] [blocksize]");
return 0;
}
char *filename= argv[1];
int blockSize = atoi(argv[2]);
if(blockSize < 1) {
puts("Please specify a blocksize larger than 0");
return 1;
}
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
if(INVALID_HANDLE_VALUE == hFile) {
puts("error opening input file");
return 1;
}
std::vector<char> buffer(blockSize);
LARGE_INTEGER fileSize;
if(!GetFileSizeEx(hFile, &fileSize)) {
puts("Failed getting file size.");
return 1;
}
std::cout << "File size " << fileSize.QuadPart << ", that's " << (fileSize.QuadPart / blockSize) <<
" blocks of " << blockSize << " bytes - reading..." << std::endl;
FILETIME dummy, kernelStart, userStart;
GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, &kernelStart, &userStart);
DWORD ticks = GetTickCount();
DWORD bytesRead = 0;
do {
if(!ReadFile(hFile, &buffer[0], blockSize, &bytesRead, 0)) {
puts("Error calling ReadFile");
return 1;
}
} while(bytesRead == blockSize);
ticks = GetTickCount() - ticks;
FILETIME kernelEnd, userEnd;
GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, &kernelEnd, &userEnd);
CloseHandle(hFile);
std::cout << "Reading with " << blockSize << " sized blocks took " << ticks << "ms, spending " <<
getDuration(kernelStart, kernelEnd) << "ms in kernel and " <<
getDuration(userStart, userEnd) << "ms in user mode. Hit enter to countinue." << std::endl;
std::string dummyString;
std::cin >> dummyString;
return 0;
}