C++ dll dont inject correctly - c++

I decided to create my own dll injector but the problem is that almost when I finished my code a problem occurs, in the following code my dll does not inject correctly, I tried everything like checking if my dll was good or even my code in general but nothing works. (I want to specify that for my processId if I use GetCurrentProcessId() my dll is injected correctly but not where I want so it is imperative for me to use GetProcessIdByName.) Thank you to all those who will help me!
#include <Windows.h>
#include <TlHelp32.h>
#include <tchar.h>
#include <string>
#include <iostream>
using namespace std;
DWORD GetProcessIdByName(const char* processName)
{
DWORD processId = 0;
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(snap, &pe))
{
do
{
if (!_stricmp(pe.szExeFile, processName))
{
processId = pe.th32ProcessID;
break;
}
} while (Process32Next(snap, &pe));
}
CloseHandle(snap);
}
return processId;
}
int main()
{
const char* processName = "OLLYDBG.exe";
DWORD processId = GetProcessIdByName(processName);
LPCSTR dllPath = "C:\\Users\\Alban\\source\\repos\\Cheat\\Cheat\\testdll.dll";
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
if (hProcess == NULL)
{
cout << "Error with 'OpenProcess', error code : " << GetLastError() << endl;
return 1;
}
cout << "process id : " << processId << endl;
LPVOID pdllPath = VirtualAllocEx(hProcess, NULL, strlen(dllPath) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pdllPath == NULL)
{
cout << "failed to allocate dll path, error code : " << GetLastError() << endl;
return 1;
}
cout << "path to memory : " << hex << pdllPath << endl;
BOOL writedMemory = WriteProcessMemory(hProcess, pdllPath, LPVOID(dllPath), strlen(dllPath) + 1, NULL);
if (writedMemory == 0)
{
cout << "failed to write memory, error code : " << GetLastError() << endl;
return 1;
}
HANDLE hloadThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("KERNEL32.DLL"), "LoadLibraryA"), pdllPath, 0, NULL);
if (hloadThread == NULL)
{
cout << "Can not create remote thread, error code : " << GetLastError() << endl;
return 1;
}
WaitForSingleObject(hloadThread, INFINITE);
BOOL virtualFree = VirtualFreeEx(hProcess, pdllPath, 0, MEM_RELEASE);
if (virtualFree == 0)
{
cout << "Can not release memory, error code : " << GetLastError() << endl;
}
CloseHandle(hProcess);
}

Related

Trying to null a string on explorer.exe but it cant read the memory [duplicate]

I know that there are other people that have asked this question but it seems as though none of them reached a satisfying or understandable conclusion. I can't use what isn't answered. I am not quite sure what the problem is and I have tried various different solutions with no success so here is my code:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)7312);
if(hProc == NULL)
{
cout << "Error: " << GetLastError() << endl;
}
HANDLE token;
OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &token);
void *baseAddr = VirtualAllocEx(hProc, NULL, 500, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(baseAddr == NULL)
{
cout << "VirtualAllocEx has failed" << endl;
}
else
{
cout << "Base Address: " << baseAddr << "\n" << endl;
}
DWORD prevProt;
if(VirtualProtectEx(hProc, &baseAddr, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &prevProt) == 0)
{
if(GetLastError() == 87)
{
cout << "ERROR_INVALID_PARAMETER\n" << endl;
}
else if(GetLastError() == 487)
{
cout << "ERROR_INVALID_ADDRESS\n" << endl;
}
}
void *buffer;
if(ReadProcessMemory(hProc, baseAddr, &buffer, sizeof(SIZE_T), NULL) == 0)
{
if(GetLastError() == 299)
{
cout << "ERROR_PARTIAL_COPY" << endl;
}
}
}
Any contribution and knowledge you can offer is deeply appreciated! :)
I see some issues with your code.
Bad error handling. If an error happens, you log it, but keep going forward with bad data. If an error happens, STOP. And you are misusing GetLastError().
You are passing the wrong base addess to VirtualProtectEx(). &baseAddr neds to be baseAddr instead. Also, you are allocating and protecting the memory with EXECUTE permissions, which you should not be using unless you intend to store executable code in the memory (which this code is not doing).
You are using sizeof(DWORD) to set protection flags on the remote memory, but you are using sizeof(SIZE_T) to read the memory. DWORD is a fixed 32 bits in size, but SIZE_T is 32 or 64 bits, depending on the platform you are compiling for. Change SIZE_T to DWORD to match the rest of your code.
You are not allocating any memory in the calling process for ReadProcessMemory() to write to. Change void *buffer; to DWORD buffer;.
Try this:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
DWORD dwError;
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)7312);
if (hProc == NULL)
{
dwError = GetLastError();
cout << "OpenProcess has failed. Error: " << dwError << endl;
return 0;
}
HANDLE token;
if (!OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &token))
{
dwError = GetLastError();
cout << "OpenProcessToken has failed. Error: " << dwError << endl;
return 0;
}
void *baseAddr = VirtualAllocEx(hProc, NULL, 500, MEM_RESERVE, PAGE_READWRITE);
if (baseAddr == NULL)
{
dwError = GetLastError();
cout << "VirtualAllocEx has failed. Error: " << dwError << endl;
return 0;
}
cout << "Base Address: " << baseAddr << endl;
DWORD prevProt;
if (!VirtualProtectEx(hProc, baseAddr, sizeof(DWORD), PAGE_READWRITE, &prevProt))
{
dwError = GetLastError();
cout << "VirtualAllocEx has failed. Error: ";
if (dwError == ERROR_INVALID_PARAMETER)
{
cout << "ERROR_INVALID_PARAMETER";
}
else if (dwError == ERROR_INVALID_ADDRESS)
{
cout << "ERROR_INVALID_ADDRESS";
}
else
{
cout << dwError;
}
cout << endl;
return 0;
}
DWORD buffer;
if (ReadProcessMemory(hProc, baseAddr, &buffer, sizeof(DWORD), NULL))
{
dwError = GetLastError();
cout << "ReadProcessMemory has failed. Error: ";
if (dwError == ERROR_PARTIAL_COPY)
{
cout << "ERROR_PARTIAL_COPY";
}
else
{
cout << dwError;
}
cout << endl;
return 0;
}
cout << "Value: " << buffer << endl;
return 0;
}
Some more issues:
You are reserving memory in the remote process, but you are not committing physical storage for that memory, and you are not writing anything into the memory before reading from it. Reading reserved uncommitted memory is not very useful, and is the likely culprit of your error:
https://stackoverflow.com/a/4457745/65863
ReadProcessMemory would return FALSE and GetLastError would return ERROR_PARTIAL_COPY when the copy hits a page fault.
Working Set
When a process references pageable memory that is not currently in its working set, a page fault occurs.
You are not using the token returned by OpenProcessToken(), so that call is useless.
You are protecting the remote memory with VirtualProtectEx() using the same protection flags you specified when allocating the memory. So this call is useless, too.
The expression &buffer is wrong - ReadProcessMemory won't allocate buffer for you, it will write on the buffer you provide. You need to allocate memory, and pass that buffer to ReadProcessMemory. Possible approach:
void *buffer = new BYTE[512];
ReadProcessMemory(hProc, baseAddr, buffer, sizeof(SIZE_T), NULL);

MapViewOfFile() Returns only the Last Word in the Buffer (See the Example)

I wrote a simple inter-process communication with a memory-mapped file. The code works relatively well, but I have a problem with the buffer that I'll explain shortly. Here is the code (C++, Windows):
#define UNICODE
#define _UNICODE
#include <iostream>
#include <tchar.h>
#include <Windows.h>
int wmain(int argc, wchar_t** argv)
{
if (argc != 2)
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
HANDLE hMapFile;
HANDLE hEvent;
HANDLE isOpened = CreateEvent(NULL, true, false, L"IsOpened"); // To check if a `win32mmap w` runs
if (wcscmp(argv[1], L"w") == 0)
{
SetEvent(isOpened);
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, L"mmapFile");
if (hMapFile == NULL)
{
std::cout << "CreateFileMapping() Error: " << GetLastError() << "\n";
return GetLastError();
}
hEvent = CreateEvent(NULL, true, false, L"mmapEvent");
if (hEvent == INVALID_HANDLE_VALUE || hEvent == NULL)
{
std::cout << "CreateEvent() Error: " << GetLastError() << "\n";
return GetLastError();
}
char* buff = (char*)MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, 0);
if (!buff)
{
std::cout << "MapViewOfFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
while (buff[0] != L'.')
{
std::cin >> buff;
SetEvent(hEvent);
}
UnmapViewOfFile(buff);
}
else if (wcscmp(argv[1], L"r") == 0)
{
if (WaitForSingleObject(isOpened, 0) == WAIT_TIMEOUT)
{
std::cout << "Waiting for `win32mmap w`...";
WaitForSingleObject(isOpened, INFINITE);
std::cout << "\n";
}
hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, L"mmapFile");
if (hMapFile == NULL)
{
std::cout << "CreateFileMapping() Error: " << GetLastError() << "\n";
return GetLastError();
}
hEvent = OpenEvent(EVENT_ALL_ACCESS, false, L"mmapEvent");
if (hEvent == INVALID_HANDLE_VALUE || hEvent == NULL)
{
std::cout << "CreateFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
char* buff = (char*)MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (!buff)
{
std::cout << "MapViewOfFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
if (!buff)
{
std::cout << "MapViewOfFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
while (true)
{
WaitForSingleObject(hEvent, INFINITE);
ResetEvent(hEvent);
if (buff[0] == '.')
{
break;
}
std::cout << buff << "\n";
}
UnmapViewOfFile(buff);
}
else
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
CloseHandle(hMapFile);
return 0;
}
The program is a simple inter-process communication "chat" that relies on memory-mapped files. To use the program, you need to make two executable instance of the program: win32mmap w and win32mmap r. The first instance is used to type text that is displayed in the second instance. When you type . in the first instance, both of them are terminated.
My problem is when I run the 2 instances of the program, and I type the world Hello in the first instance (win32mmap w), the second instance shows Hello as expected. But when I type Hello World in the first instance, the second instance shows only the word World instead of Hello World. How can I fix the code that the buffer will get the whole text?
Your writer is not waiting for the reader to consume the data before overwriting it with new data.
You need 2 events - one for the reader to wait on signaling when the buffer has data to read, and one for the writer to wait on signaling when the buffer needs data.
Try this instead:
#define UNICODE
#define _UNICODE
#include <iostream>
#include <tchar.h>
#include <Windows.h>
const DWORD BufSize = 1024;
int wmain(int argc, wchar_t** argv)
{
if (argc != 2)
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
HANDLE hMapFile;
char* buff;
HANDLE hNeedDataEvent;
HANDLE hHasDataEvent;
DWORD dwError;
HANDLE isOpened = CreateEvent(NULL, TRUE, FALSE, L"IsOpened"); // To check if a `win32mmap w` runs
if (isOpened == NULL)
{
dwError = GetLastError();
std::cout << "CreateEvent() Error: " << dwError << "\n";
return dwError;
}
if (wcscmp(argv[1], L"w") == 0)
{
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BufSize, L"mmapFile");
if (hMapFile == NULL)
{
dwError = GetLastError();
std::cout << "CreateFileMapping() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
buff = (char*) MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, BufSize);
if (!buff)
{
dwError = GetLastError();
std::cout << "MapViewOfFile() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
hNeedDataEvent = CreateEvent(NULL, TRUE, TRUE, L"mmapNeedDataEvent");
if (hNeedDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "CreateEvent() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
hHasDataEvent = CreateEvent(NULL, TRUE, FALSE, L"mmapHasDataEvent");
if (hHasDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "CreateEvent() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
SetEvent(isOpened);
while (WaitForSingleObject(hNeedDataEvent, INFINITE) == WAIT_OBJECT_0)
{
std::cin.get(buff, BufSize);
ResetEvent(hNeedDataEvent);
SetEvent(hHasDataEvent);
if (buff[0] == L'.') break;
}
}
else if (wcscmp(argv[1], L"r") == 0)
{
if (WaitForSingleObject(isOpened, 0) == WAIT_TIMEOUT)
{
std::cout << "Waiting for `win32mmap w`...";
WaitForSingleObject(isOpened, INFINITE);
std::cout << "\n";
}
hMapFile = OpenFileMapping(FILE_MAP_READ, FALSE, L"mmapFile");
if (hMapFile == NULL)
{
dwError = GetLastError();
std::cout << "CreateFileMapping() Error: " << dwError << "\n";
return dwError;
}
char* buff = (char*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, BufSize);
if (!buff)
{
dwError = GetLastError();
std::cout << "MapViewOfFile() Error: " << dwError << "\n";
return dwError;
}
hNeedDataEvent = OpenEvent(SYNCHRONIZE, FALSE, L"mmapNeedDataEvent");
if (hNeedDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "OpenEvent() Error: " << dwError << "\n";
return dwError;
}
hHasDataEvent = OpenEvent(SYNCHRONIZE, FALSE, L"mmapHasDataEvent");
if (hHasDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "OpenEvent() Error: " << dwError << "\n";
return dwError;
}
do
{
SetEvent(hNeedDataEvent);
if (WaitForSingleObject(hHasDataEvent, INFINITE) != WAIT_OBJECT_0)
break;
std::cout << buff << "\n";
ResetEvent(hHasDataEvent);
}
while (buff[0] != '.');
}
else
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
UnmapViewOfFile(buff);
CloseHandle(hMapFile);
CloseHandle(hNeedDataEvent);
CloseHandle(hHasDataEvent);
CloseHandle(isOpened);
return 0;
}

ReadProcessMemory() Returning 0 ERROR_PARTIAL_COPY

#include <Windows.h>
#include <iostream>
#include <vector>
#include <TlHelp32.h>
#include <tchar.h>
using namespace std;
DWORD GetModuleBase(LPSTR lpModuleName, DWORD dwProcessId)
{
MODULEENTRY32 lpModuleEntry = {0};
HANDLE hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId );
if(!hSnapShot)
return NULL;
lpModuleEntry.dwSize = sizeof(lpModuleEntry);
BOOL bModule = Module32First( hSnapShot, &lpModuleEntry );
while(bModule)
{
if(!strcmp( lpModuleEntry.szModule, lpModuleName ) )
{
CloseHandle( hSnapShot );
return (DWORDLONG)lpModuleEntry.modBaseAddr;
}
bModule = Module32Next( hSnapShot, &lpModuleEntry );
}
CloseHandle( hSnapShot );
return NULL;
}
int main() {
DWORD pID;
DWORDLONG off1, off2;
DWORDLONG baseAddress;
char moduleName[] = _T("AoE2DE_s.exe");
HWND hGameWindow;
HANDLE pHandle;
//Get Handles
hGameWindow = FindWindow(NULL, "Age of Empires II: Definitive Edition");
cout << "Game Window: " << hGameWindow << std::endl;
GetWindowThreadProcessId(hGameWindow, &pID);
cout << "Process ID: " << pID << std::endl;
pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
cout << "Process Handle: " << std::hex << pHandle << std::endl;
//Get Client Base Addy
DWORDLONG clientBase = GetModuleBase(moduleName, pID);
cout << "Client Base: " << clientBase << std::endl;
ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), NULL);
DWORD lastError = GetLastError();
cout << "Error: " << lastError << std::endl;
cout << "Base Address: " << std::hex << baseAddress << std::endl;
ReadProcessMemory(pHandle, (LPCVOID)(baseAddress + 0x18), &off1, sizeof(DWORDLONG), NULL);
cout << "After Offset 1: " << std::hex << off1 << std::endl;
ReadProcessMemory(pHandle, (LPCVOID)(off1 + 0x9230), &off2, sizeof(DWORDLONG), NULL);
cout << "After Final Offset: " << off2 << std::endl;
cin.get();
}
The error occurs on this line:
ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), NULL);
Application output for debugging purposes:
Game Window: 0x1307c2
Process ID: 11988
Process Handle: 0xec
Client Base: cc640000
Error: 12b
Base Address: 0
After Offset 1: 401519
After Final Offset: 8
Not sure how it is failing here, I'm somewhat new to this. Everything else goes through perfectly without error's but fails on the first ReadProcessMemory() if someone can help bring the solution for this to light I would be grateful.
ReadProcessMemory is defined like this:
BOOL ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesRead
);
If it returns zero then there has been an error, and only in that case GetLastError will return a meaningfull error number.
So correct usage would be:
SIZE_T readBytes;
if (!ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), &readBytes)) {
DWORD lastError = GetLastError();
cout << "ReadProcessMemory failed: Error: " << lastError << " read " << readBytes << std::endl;
}
else
{
cout << "ReadProcessMemory succeeded"; << std::endl;
cout << "Base Address: " << std::hex << baseAddress << std::endl;
}

ReadProcessMemory error 299 after checking page rights + page backing [duplicate]

I know that there are other people that have asked this question but it seems as though none of them reached a satisfying or understandable conclusion. I can't use what isn't answered. I am not quite sure what the problem is and I have tried various different solutions with no success so here is my code:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)7312);
if(hProc == NULL)
{
cout << "Error: " << GetLastError() << endl;
}
HANDLE token;
OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &token);
void *baseAddr = VirtualAllocEx(hProc, NULL, 500, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(baseAddr == NULL)
{
cout << "VirtualAllocEx has failed" << endl;
}
else
{
cout << "Base Address: " << baseAddr << "\n" << endl;
}
DWORD prevProt;
if(VirtualProtectEx(hProc, &baseAddr, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &prevProt) == 0)
{
if(GetLastError() == 87)
{
cout << "ERROR_INVALID_PARAMETER\n" << endl;
}
else if(GetLastError() == 487)
{
cout << "ERROR_INVALID_ADDRESS\n" << endl;
}
}
void *buffer;
if(ReadProcessMemory(hProc, baseAddr, &buffer, sizeof(SIZE_T), NULL) == 0)
{
if(GetLastError() == 299)
{
cout << "ERROR_PARTIAL_COPY" << endl;
}
}
}
Any contribution and knowledge you can offer is deeply appreciated! :)
I see some issues with your code.
Bad error handling. If an error happens, you log it, but keep going forward with bad data. If an error happens, STOP. And you are misusing GetLastError().
You are passing the wrong base addess to VirtualProtectEx(). &baseAddr neds to be baseAddr instead. Also, you are allocating and protecting the memory with EXECUTE permissions, which you should not be using unless you intend to store executable code in the memory (which this code is not doing).
You are using sizeof(DWORD) to set protection flags on the remote memory, but you are using sizeof(SIZE_T) to read the memory. DWORD is a fixed 32 bits in size, but SIZE_T is 32 or 64 bits, depending on the platform you are compiling for. Change SIZE_T to DWORD to match the rest of your code.
You are not allocating any memory in the calling process for ReadProcessMemory() to write to. Change void *buffer; to DWORD buffer;.
Try this:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
DWORD dwError;
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)7312);
if (hProc == NULL)
{
dwError = GetLastError();
cout << "OpenProcess has failed. Error: " << dwError << endl;
return 0;
}
HANDLE token;
if (!OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &token))
{
dwError = GetLastError();
cout << "OpenProcessToken has failed. Error: " << dwError << endl;
return 0;
}
void *baseAddr = VirtualAllocEx(hProc, NULL, 500, MEM_RESERVE, PAGE_READWRITE);
if (baseAddr == NULL)
{
dwError = GetLastError();
cout << "VirtualAllocEx has failed. Error: " << dwError << endl;
return 0;
}
cout << "Base Address: " << baseAddr << endl;
DWORD prevProt;
if (!VirtualProtectEx(hProc, baseAddr, sizeof(DWORD), PAGE_READWRITE, &prevProt))
{
dwError = GetLastError();
cout << "VirtualAllocEx has failed. Error: ";
if (dwError == ERROR_INVALID_PARAMETER)
{
cout << "ERROR_INVALID_PARAMETER";
}
else if (dwError == ERROR_INVALID_ADDRESS)
{
cout << "ERROR_INVALID_ADDRESS";
}
else
{
cout << dwError;
}
cout << endl;
return 0;
}
DWORD buffer;
if (ReadProcessMemory(hProc, baseAddr, &buffer, sizeof(DWORD), NULL))
{
dwError = GetLastError();
cout << "ReadProcessMemory has failed. Error: ";
if (dwError == ERROR_PARTIAL_COPY)
{
cout << "ERROR_PARTIAL_COPY";
}
else
{
cout << dwError;
}
cout << endl;
return 0;
}
cout << "Value: " << buffer << endl;
return 0;
}
Some more issues:
You are reserving memory in the remote process, but you are not committing physical storage for that memory, and you are not writing anything into the memory before reading from it. Reading reserved uncommitted memory is not very useful, and is the likely culprit of your error:
https://stackoverflow.com/a/4457745/65863
ReadProcessMemory would return FALSE and GetLastError would return ERROR_PARTIAL_COPY when the copy hits a page fault.
Working Set
When a process references pageable memory that is not currently in its working set, a page fault occurs.
You are not using the token returned by OpenProcessToken(), so that call is useless.
You are protecting the remote memory with VirtualProtectEx() using the same protection flags you specified when allocating the memory. So this call is useless, too.
The expression &buffer is wrong - ReadProcessMemory won't allocate buffer for you, it will write on the buffer you provide. You need to allocate memory, and pass that buffer to ReadProcessMemory. Possible approach:
void *buffer = new BYTE[512];
ReadProcessMemory(hProc, baseAddr, buffer, sizeof(SIZE_T), NULL);

Win API ReadProcessMemory at base address of DLL returning unexpected data

I'm trying to read the contents of a DLL from memory for some academic research. Specifically, the NTDSA.DLL library for the purpose of mutating specific instructions to simulate programming errors to force the system to fail. The failure will then be recorded to train machine learning algorithms to predict future failures (this is an attempt to generalize previously published research seen here).
I'm getting what I believe to be the base address in virtual memory of the lsass.exe process (which loads the target DLL) through the process outlined here. I'm then calling ReadProcessMemory with an allocated buffer and the handle to lsass obtained by calling OpenProcess with 'PROCESS_ALL_ACCESS' set. The ReadProcessMemory returns with error code 299 80% of the time (partial read) with zero bytes read. My assumption is that the area I'm trying to access is in use when the call is made. Fortunately, it will occasionally return the number of bytes I'm requesting. Unfortunately, the data returned does not match what is on disk when compared to the static DLL in the System32 directory.
So the question is, is ReadProcessMemory doing something funny with the address that I give it, or is my virtual address wrong? Is there another way to figure out where that DLL gets loaded into memory? Any thoughts? Any help or suggestions would be greatly appreciated.
Adding Code:
// FaultInjection.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <psapi.h>
#include <string>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <io.h>
#include <tchar.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]) {
// Declarations
int pid = 0;
__int64* start_addr;
DWORD size_of_ntdsa;
DWORD aProcesses[1024], cbNeeded, cProcesses;
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
HMODULE hmods[1024];
unsigned int i;
// Get All pids
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)){
cout << "Failed to get all PIDs: " << GetLastError() << endl;
return -1;
}
// Find pid for lsass.exe
cProcesses = cbNeeded / sizeof(DWORD);
for (i = 0; i < cProcesses; i++) {
if (aProcesses[i] != 0) {
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);
if (hProc != NULL) {
HMODULE hMod;
DWORD cbNeededMod;
if (EnumProcessModules(hProc, &hMod, sizeof(hMod), &cbNeededMod)) {
GetModuleBaseName(hProc, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR));
}
if (wstring(szProcessName).find(L"lsass.exe") != string::npos) {
pid = aProcesses[i];
}
CloseHandle(hProc);
}
}
}
cout << "lsass pid: " << pid << endl;
HANDLE h_lsass = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!h_lsass) {
cout << "Failed to open process (are you root?): " << GetLastError() << endl;
return -1;
}
// Get Process Image File Name
char filename[MAX_PATH];
if (GetProcessImageFileName(h_lsass, (LPTSTR)&filename, MAX_PATH) == 0) {
cout << "Failed to get image file name: " << GetLastError() << endl;
CloseHandle(h_lsass);
return -1;
}
// Enumerate modules within process
if (EnumProcessModules(h_lsass, hmods, sizeof(hmods), &cbNeeded)) {
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(h_lsass, hmods[i], szModName, sizeof(szModName) / sizeof(TCHAR))) {
if (wstring(szModName).find(L"NTDSA.dll") != string::npos) {
_tprintf(TEXT("%s\n"), szModName);
MODULEINFO lModInfo = { 0 };
if (GetModuleInformation(h_lsass, hmods[i], &lModInfo, sizeof(lModInfo))){
cout << "\t Base Addr: " << lModInfo.lpBaseOfDll << endl;
cout << "\t Entry Point: " << lModInfo.EntryPoint << endl;
cout << "\t Size of image: " << lModInfo.SizeOfImage << endl;
start_addr = (__int64*)lModInfo.lpBaseOfDll;
size_of_ntdsa = lModInfo.SizeOfImage;
}
else {
cout << "Failed to Print enumerated list of modules: " << GetLastError() << endl;
}
}
} else {
cout << "Failed to Print enumerated list of modules: " << GetLastError() << endl;
}
}
}
else {
cout << "Failed to enum the modules: " << GetLastError() << endl;
}
// Ready to continue?
string cont = "";
cout << "Continue? [Y|n]: ";
getline(cin, cont);
if (cont.find("n") != string::npos || cont.find("N") != string::npos) {
CloseHandle(h_lsass);
return 0;
}
void* buf = malloc(size_of_ntdsa);
if (!buf) {
cout << "Failed to allocate space for memory contents: " << GetLastError() << endl;
CloseHandle(h_lsass);
return -1;
}
SIZE_T num_bytes_read = 0;
int count = 0;
if (ReadProcessMemory(h_lsass, &start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
cout << "Read success. Got " << num_bytes_read << " bytes: " << endl;
} else {
int error_code = GetLastError();
if (error_code == 299) {
cout << "Partial read. Got " << num_bytes_read << " bytes: " << endl;
} else {
cout << "Failed to read memory: " << GetLastError() << endl;
CloseHandle(h_lsass);
free(buf);
return -1;
}
}
if (num_bytes_read > 0) {
FILE *fp;
fopen_s(&fp, "C:\\ntdsa_new.dll", "w");
SIZE_T bytes_written = 0;
while (bytes_written < num_bytes_read) {
bytes_written += fwrite(buf, 1, num_bytes_read, fp);
}
fclose(fp);
cout << "Wrote " << bytes_written << " bytes." << endl;
}
CloseHandle(h_lsass);
free(buf);
return 0;
}
Code works as described minus my amateur mistake of sending the address of the variable I was using to store the address of the location in virtual memory of the target application. In above code, changed:
if (ReadProcessMemory(h_lsass, &start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
to
if (ReadProcessMemory(h_lsass, start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
Works like a charm. Thank you ssbssa for pointing out mistake, sorry for wasting anyone's time.