Remote Injection - c++

So, i'm injecting a code in the memory of another process like this:
void RemoteInj::ExecuteFunction(DWORD Start, DWORD End, DWORD Entry, RemoteArgs* Args)
{
unsigned long Id;
int size = End - Start;
cout << size << endl;
void* Func = VirtualAllocEx(hProcess, NULL, size+10, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
void* ep = (void*)(Entry-Start+(DWORD)(Func));
WriteProcessMemory(hProcess, Func, (void*)Start, size, NULL);
void* Data = VirtualAllocEx(hProcess, NULL, sizeof(RemoteArgs)+1, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, Data, (void*)Args, sizeof(RemoteArgs), NULL);
cout << hex << Func << endl;
cout << "Function: 0x" << hex << Start << endl << "End: 0x" << hex << End << endl;
system("PAUSE");
CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)ep, Data, NULL, NULL);
CloseHandle(hProcess);
}
My problem is: If i use calls in that thread, for example:
void F(RemoteArgs* arg)
{
while (true)
{
arg->pSleep(50); //Works
Sleep(50); //doesnt work
}
return;
}
No need to explain why it doesn't work, i know, it's another process....My question is: Is there a way to make function like this(Sleep()) work, i could try importing to the process also the IAT with the proper distance, do you have a better idea?Thanks!

As you suspect, the reason this doesn't work right off the bat is that the call to Sleep in your process actually goes to a location in your import address table (IAT) which has a jump to the real Sleep implementation in kernel32.dll. Even though the other process also imports kernel32.dll (all processes do), it obviously does not have an identical IAT.
There are ways, but none that I know of are trivial.

Related

RestoreFile Call (File Management API - fmapi.dll) Returns Invalid Handle

Background:
I'm trying to write a C++ application that can scan for and attempt to restore deleted files from a WinPE environment, mostly as a learning exercise. This app utilizes the FMAPI library (fmapi.dll), which is a scarcely-documented library that only works in a WinPE environment (does not work in a full Windows OS). I've been using the ScanRestorableFiles example released by MS (available here) as a starting point.
Now, I've done a LOT of digging and have found next to nothing when it comes to FMAPI documentation - just the sample noted above and some basic MSDN docs here. The MSDN pages provide the definitions for the API functions and a few extra notes on a couple of the functions that provide a hint or two, but that's it. So I thought I'd come here in hopes of finding some assistance.
Also please note, as far as development languages go, C++ is not my strong point - I would consider myself novice at best.
Now to the issue at hand:
My app is able to successfully load the library, create the file restore context and scan for restorable files. However, once I try to call the RestoreFile() function on one of the restorable items that was returned by the ScanRestorableFiles() call, I get an Invalid Handle error. The "restored file" ends up being a 0-byte file (it does get created successfully in the proper place) with no data in it.
Interestingly, even after returning the Invalid Handle error code, my app holds a handle open on the file until the file restore context is closed (I know this because if I try to read the restored file immediately after attempting to restore it, I get a "file is in use by another process" error).
Posted below is the entire code for my app (its just a single source file, not counting headers and such) - since this seems to be a rarely-used API, I feel like I should post the whole thing to add context to each function call (and also because I'm not quite sure exactly what may or may not be relevant to the issue I'm having).
Code:
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <sstream>
#include <stdlib.h>
#define SCAN_PATH L"\\"
//
//Define the needed FMAPI structures as documented in FMAPI
//
#define FILE_RESTORE_MAJOR_VERSION_2 0x0002
#define FILE_RESTORE_MINOR_VERSION_2 0x0000
#define FILE_RESTORE_VERSION_2 ((FILE_RESTORE_MAJOR_VERSION_2 << 16) | FILE_RESTORE_MINOR_VERSION_2)
using namespace std;
//External API function declarations
//We don't have an import library or
//header for the FMAPI functions, so
//we must dynamically link to them at
//runtime.
typedef PVOID PFILE_RESTORE_CONTEXT;
typedef enum {
ContextFlagVolume = 0x00000001,
ContextFlagDisk = 0x00000002,
FlagScanRemovedFiles = 0x00000004,
FlagScanRegularFiles = 0x00000008,
FlagScanIncludeRemovedDirectories = 0x00000010
} RESTORE_CONTEXT_FLAGS;
typedef enum {
FileRestoreProgressInfo = 100,
FileRestoreFinished = 101
} FILE_RESTORE_PACKET_TYPE, *PFILE_RESTORE_PACKET_TYPE;
typedef BOOL (WINAPI *FuncCreateFileRestoreContext) (
_In_ PCWSTR Volume,
_In_ RESTORE_CONTEXT_FLAGS Flags,
_In_ LONGLONG StartSector,
_In_ LONGLONG BootSector,
_In_ DWORD Version,
_Out_ PFILE_RESTORE_CONTEXT* Context
);
typedef BOOL (WINAPI *FuncCloseFileRestoreContext) (
_In_ PFILE_RESTORE_CONTEXT Context
);
typedef struct _RESTORABLE_FILE_INFO
{
ULONG Size;
DWORD Version;
ULONGLONG FileSize;
FILETIME CreationTime;
FILETIME LastAccessTime;
FILETIME LastWriteTime;
DWORD Attributes;
BOOL IsRemoved;
LONGLONG ClustersUsedByFile;
LONGLONG ClustersCurrentlyInUse;
ULONG RestoreDataOffset;
WCHAR FileName[1]; // Single-element array indicates a variable-length structure
} RESTORABLE_FILE_INFO, *PRESTORABLE_FILE_INFO;
typedef struct _FILE_RESTORE_PROGRESS_INFORMATION {
LONGLONG TotalFileSize;
LONGLONG TotalBytesCompleted;
LONGLONG StreamSize;
LONGLONG StreamBytesCompleted;
PVOID ClbkArg;
} FILE_RESTORE_PROGRESS_INFORMATION, *PFILE_RESTORE_PROGRESS_INFORMATION;
typedef struct _FILE_RESTORE_FINISHED_INFORMATION {
BOOL Success;
ULONG FinalResult;
PVOID ClbkArg;
} FILE_RESTORE_FINISHED_INFORMATION, *PFILE_RESTORE_FINISHED_INFORMATION;
typedef BOOL (WINAPI *FuncScanRestorableFiles) (
_In_ PFILE_RESTORE_CONTEXT Context,
_In_ PCWSTR Path,
_In_ ULONG FileInfoSize,
_Out_bytecap_(FileInfoSize) PRESTORABLE_FILE_INFO FileInfo,
_Out_ PULONG FileInfoUsed
);
typedef BOOLEAN (*FILE_RESTORE_CALLBACK) (
_In_ FILE_RESTORE_PACKET_TYPE PacketType,
_In_ ULONG PacketLength,
_In_ PVOID PacketData
);
typedef BOOL (WINAPI *FuncRestoreFile) (
_In_ PFILE_RESTORE_CONTEXT Context,
_In_ PRESTORABLE_FILE_INFO RestorableFile,
_In_ PCWSTR DstFile,
_In_opt_ FILE_RESTORE_CALLBACK Callback,
_In_opt_ PVOID ClbkArg
);
HMODULE hLib;
wchar_t VOLUME[255];
BOOLEAN FuncRestoreCallback(_In_ FILE_RESTORE_PACKET_TYPE pType, _In_ ULONG pLength, _In_ PVOID pData)
{
// This is the callback that is passed to RestoreFile(), which
// returns data about the status of an attempted restoration.
if (pType == FileRestoreProgressInfo)
{
wcout << L"FILE RESTORE PROGRESS INFO:" << L"\n";
wprintf(L"Length of status data: %lu\n", pLength);
wcout << L"Location of data: " << pData << L"\n";
PFILE_RESTORE_PROGRESS_INFORMATION restoreProgressInfo = static_cast<PFILE_RESTORE_PROGRESS_INFORMATION>(pData);
wprintf(L"Total file size: %lld\n", restoreProgressInfo->TotalFileSize);
wprintf(L"Total bytes completed: %lld\n", restoreProgressInfo->TotalBytesCompleted);
wprintf(L"Stream size: %lld\n", restoreProgressInfo->StreamSize);
wprintf(L"Stream bytes completed: %lld\n", restoreProgressInfo->StreamBytesCompleted);
//wcout << L"Callback arg data: " << restoreProgressInfo->ClbkArg << L"\n";
wprintf(L"Callback arg: %p\n", restoreProgressInfo->ClbkArg);
}
else if (pType == FileRestoreFinished)
{
wcout << L"FILE RESTORE FINISHED INFO:" << L"\n";
wprintf(L"Length of status data: %lu\n", pLength);
wcout << L"Location of data: " << pData << L"\n";
// Obtain the struct
PFILE_RESTORE_FINISHED_INFORMATION restoreFinishedInfo = static_cast<PFILE_RESTORE_FINISHED_INFORMATION>(pData);
// Try to read some data from it
wprintf(L"Success data: %d\n", restoreFinishedInfo->Success);
wprintf(L"Final result data: %lu\n", restoreFinishedInfo->FinalResult);
wprintf(L"Callback arg: %p\n", restoreFinishedInfo->ClbkArg);
}
return TRUE;
}
void Scan(_In_ PFILE_RESTORE_CONTEXT context, _In_ LPCWSTR path)
{
// This is the main function that scans the files
// Dynamically link to the needed FMAPI functions
FuncScanRestorableFiles ScanRestorableFiles;
ScanRestorableFiles = reinterpret_cast<FuncScanRestorableFiles>( GetProcAddress( hLib, "ScanRestorableFiles" ) );
ULONG neededBufferSize = 0;
BOOL success = TRUE;
RESTORABLE_FILE_INFO tempFileInfo;
// Call ScanRestorableFiles the first time with a size of 0 to get the required buffer size
if ( ! ScanRestorableFiles(context, path, 0, &tempFileInfo, &neededBufferSize) )
{
wprintf(L"Failed to retrieve required buffer size, Error: #%u\n", GetLastError());
return;
}
// Create the buffer needed to hold restoration information
BYTE *buffer = new BYTE[neededBufferSize];
wcout << L"Initial buffer size is: " << neededBufferSize << L"\n";
// Loops until an error occurs or no more files found
while (success)
{
// Cast the byte buffer pointer into a structure pointer
PRESTORABLE_FILE_INFO fileInfo = reinterpret_cast<PRESTORABLE_FILE_INFO>(buffer);
#pragma warning( push )
#pragma warning( disable : 6386 ) /* warning is ignored since fileInfo grows in size by design */
success = ScanRestorableFiles(context, path, neededBufferSize, fileInfo, &neededBufferSize);
#pragma warning( pop )
wcout << L"Current buffer size is: " << neededBufferSize << L"\n";
if (success)
{
wcout << L"Call returned success! Required buffer size from latest call is " << neededBufferSize <<
L" bytes." L"\n";
if (fileInfo->IsRemoved)
{
// Found restorable file
wprintf(L"Restorable file found: %s\n", fileInfo->FileName);
// Echo size of char array containing file name
wcout << L"Restorable file name size: " <<
(sizeof(fileInfo->FileName) / sizeof(fileInfo->FileName[0])) << L"\n";
// Echo RESTORABLE_FILE_INFO structure info to console
wcout << L"Restorable file info structure memory address: " << fileInfo << L"\n";
wcout << L"Restorable file info structure size (returned via RESTORABLE_FILE_INFO): " << fileInfo->Size << L"\n";
wcout << L"Restorable file info structure size (returned via sizeof()): " << sizeof(*fileInfo) << L"\n";
// Echo restorable file (FMAPI) version to console
wcout << L"Restorable file version: " << fileInfo->Version << L"\n";
// Retrieve creation, write and access times for the file
// Define temp FILETIME, SYSTEMTIME and TIME_ZONE_INFORMATION
// structure vars
// All of these types and functions are defined in windows.h
FILETIME tmpFT;
SYSTEMTIME tmpST;
TIME_ZONE_INFORMATION tmpTZI;
// Initialize empty char arrays
wchar_t szLocalDate[255] = {0}, szLocalTime[255] = {0};
// Get local time zone info
SetTimeZoneInformation(&tmpTZI);
// Get file creation time
FileTimeToLocalFileTime(&(fileInfo->CreationTime), &tmpFT);
FileTimeToSystemTime(&tmpFT, &tmpST);
// Format to readable output and store in char arrays
GetDateFormatEx(LOCALE_NAME_SYSTEM_DEFAULT, DATE_LONGDATE, &tmpST, NULL, szLocalDate, 255, NULL);
GetTimeFormatEx(LOCALE_NAME_SYSTEM_DEFAULT, 0, &tmpST, NULL, szLocalTime, 255);
wcout << L"Restorable file created: " << szLocalDate << " " << szLocalTime << L"\n";
// Clear array for re-use
fill(begin(szLocalDate), end(szLocalDate), 0);
// Get last write time
FileTimeToLocalFileTime(&(fileInfo->LastWriteTime), &tmpFT);
FileTimeToSystemTime(&tmpFT, &tmpST);
// Format to readable output and store in char arrays
GetDateFormatEx(LOCALE_NAME_SYSTEM_DEFAULT, DATE_LONGDATE, &tmpST, NULL, szLocalDate, 255, NULL);
GetTimeFormatEx(LOCALE_NAME_SYSTEM_DEFAULT, 0, &tmpST, NULL, szLocalTime, 255);
wcout << L"Restorable file last written: " << szLocalDate << " " << szLocalTime << L"\n";
// Clear array for re-use
fill(begin(szLocalDate), end(szLocalDate), 0);
// Get last access time
FileTimeToLocalFileTime(&(fileInfo->LastAccessTime), &tmpFT);
FileTimeToSystemTime(&tmpFT, &tmpST);
// Format to readable output and store in char arrays
GetDateFormatEx(LOCALE_NAME_SYSTEM_DEFAULT, DATE_LONGDATE, &tmpST, NULL, szLocalDate, 255, NULL);
GetTimeFormatEx(LOCALE_NAME_SYSTEM_DEFAULT, 0, &tmpST, NULL, szLocalTime, 255);
wcout << L"Restorable file last accessed: " << szLocalDate << " " << szLocalTime << L"\n";
// Output the rest of the file info
wcout << L"Restorable file attributes: " << fileInfo->Attributes << L"\n";
wcout << L"Restorable file size: " << fileInfo->FileSize << L"\n";
wcout << L"Restorable file ClustersUsedByFile: " << fileInfo->ClustersUsedByFile << L"\n";
wcout << L"Restorable file ClustersCurrentlyInUse: " << fileInfo->ClustersCurrentlyInUse << L"\n";
wcout << L"Restorable file RestoreDataOffset: " << fileInfo->RestoreDataOffset << L"\n";
// Attempt to restore the file
wstring tmpStr;
getline(wcin, tmpStr);
// Convert input to uppercase
for (wstring::size_type i = 0; i < tmpStr.size(); i++)
{
towupper(tmpStr[i]);
}
wcout << L"tmpStr is: " << tmpStr << L"\n";
if (tmpStr == L"RESTORE")
{
// Attempt to restore the file
wcout << L"Attempting to restore file " << fileInfo->FileName << L"..." << L"\n";
FuncRestoreFile RestoreFile;
//RestoreFile = (FuncRestoreFile)GetProcAddress( hLib, "RestoreFile" );
RestoreFile = reinterpret_cast<FuncRestoreFile>(GetProcAddress(hLib, "RestoreFile"));
wcout << L"RestoreFile address: " << RestoreFile << L"\n";
BOOL tmpRetVal = false;
PCWSTR restoredFileName = L"X:\\testfile.txt";
wcout << L"New file name: " << restoredFileName << L"\n";
PVOID cbArg = NULL;
tmpRetVal = RestoreFile(context, fileInfo, restoredFileName, &FuncRestoreCallback, cbArg);
wcout << L"Return value: " << tmpRetVal << L" ; cbArg: " << cbArg << L"\n";
if (tmpRetVal == 0)
{
wcout << L"Error was: " << GetLastError() << L"\n";
}
}
else if (tmpStr == L"CLOSE")
{
// Abort the scanning process and close the file restore context
wcout << L"Aborting scan and closing file restore context..." << L"\n";
success = false;
}
}
}
else
{
DWORD err = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER == err)
{
wcout << L"Insufficient buffer size! Current size is " << sizeof(buffer) << L" bytes; " <<
L" required size is " << neededBufferSize << L" bytes. Resizing..." << L"\n";
delete [] buffer;
buffer = new BYTE[neededBufferSize];
success = true;
}
else if (ERROR_NO_MORE_FILES == err)
{
wprintf(L"Scanning Complete.\n");
success = false;
}
else
{
wprintf(L"ScanRestorableFiles, Error #%u.\n", err);
}
}
}
delete [] buffer;
buffer = NULL;
}
//
// Program entry point
//
void __cdecl wmain(int argc, wchar_t *argv[])
{
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
// Load the FMAPI DLL
hLib = ::LoadLibraryEx(L"fmapi.dll", NULL, NULL);
if ( !hLib )
{
wprintf(L"Could not load fmapi.dll. Error #%u.\n", GetLastError());
return;
}
// Dynamically link to the needed FMAPI functions
FuncCreateFileRestoreContext CreateFileRestoreContext;
CreateFileRestoreContext = reinterpret_cast<FuncCreateFileRestoreContext>( GetProcAddress( hLib, "CreateFileRestoreContext" ) );
FuncCloseFileRestoreContext CloseFileRestoreContext;
CloseFileRestoreContext = reinterpret_cast<FuncCloseFileRestoreContext>( GetProcAddress( hLib, "CloseFileRestoreContext" ) );
// Set the flags value for which kind of items we want to scan for
RESTORE_CONTEXT_FLAGS flags;
flags = (RESTORE_CONTEXT_FLAGS)(ContextFlagVolume | FlagScanRemovedFiles);
switch (argc)
{
case 2:
{
if (wcslen(argv[1]) < (sizeof(VOLUME) / sizeof(VOLUME[0]))) // ensure that argv[1] is not >255 chars long
{
wcscpy_s(VOLUME, argv[1]);
}
else
{
wcscpy_s(VOLUME, 255, argv[1]);
}
wcout << L"Volume set to: " << VOLUME << L"\n";
wcout << L"Defaulting to VOLUME search type; setting flags accordingly..." << L"\n";
flags = (RESTORE_CONTEXT_FLAGS)(ContextFlagVolume | FlagScanRemovedFiles);
break;
}
case 3:
{
if (wcslen(argv[1]) < (sizeof(VOLUME) / sizeof(VOLUME[0]))) // ensure that argv[1] is not >255 chars long
{
wcscpy_s(VOLUME, argv[1]);
}
else // if it is, only copy the first 255 chars
{
wcscpy_s(VOLUME, 255, argv[1]);
}
int len;
// Get length of second argument passed by the user
len = wcslen(argv[2]);
// Allocate new wchar_t array big enough to hold it
wchar_t *tmpArg = new (nothrow) wchar_t[len + 1];
// Ensure that the memory was allocated successfully
if (tmpArg == nullptr)
{
// Error allocating memory - bail out
wcout << L"Error allocating memory! Bailing out..." << L"\n";
return;
}
// Copy the argument string from argv to tmpArg
wcscpy_s(tmpArg, len + 1, argv[2]);
// Convert to uppercase
_wcsupr_s(tmpArg, len + 1);
// Check whether VOLUME or DISK search type was specified and set flags accordingly
if (wcscmp(tmpArg, L"VOLUME") == 0)
{
wcout << L"Volume set to: " << VOLUME << L"\n";
if (wcschr(VOLUME, L':') != NULL)
{
wcout << L"VOLUME search type specified; setting flags accordingly..." << L"\n";
flags = (RESTORE_CONTEXT_FLAGS)(ContextFlagVolume | FlagScanRemovedFiles);
}
else
{
wcout << L"VOLUME search type specified, but the volume identifier given doesn't appear " <<
L"to be a valid mounted volume! Please check your arguments and try again." << L"\n";
delete [] tmpArg;
return;
}
}
else if (wcscmp(tmpArg, L"DISK") == 0)
{
wcout << L"Disk set to: " << VOLUME << L"\n";
if (wcschr(VOLUME, L':') == NULL)
{
wcout << L"DISK search type specified; setting flags accordingly..." << L"\n";
flags = (RESTORE_CONTEXT_FLAGS)(ContextFlagDisk | FlagScanRemovedFiles);
}
else
{
wcout << L"DISK search type specified, but the disk identifier given doesn't appear " <<
L"to be a valid physical disk! Please check your arguments and try again." << L"\n";
delete [] tmpArg;
return;
}
}
else
{
wcout << L"UNKNOWN search type specified! Defaulting to VOLUME; setting flags accordingly..." << L"\n";
flags = (RESTORE_CONTEXT_FLAGS)(ContextFlagVolume | FlagScanRemovedFiles);
}
delete [] tmpArg;
break;
}
default:
{
// Set the default volume to scan here
wcscpy_s(VOLUME, L"\\\\.\\D:");
wcout << L"No arguments specified! Defaulting to VOLUME search of \\\\.\\D:" << L"\n";
break;
}
}
// Create the FileRestoreContext
PFILE_RESTORE_CONTEXT context = NULL;
if ( ! CreateFileRestoreContext(VOLUME, flags, 0, 0, FILE_RESTORE_VERSION_2, &context) )
{
DWORD err = GetLastError();
wprintf(L"Failed to Create FileRestoreContext, Error #%u.\n", err);
return;
}
else
{
wcout << L"Success! File restore context created! Value of context is: " << context << L"\n";
}
// Find restorable files starting at the given directory
Scan(context, SCAN_PATH);
// Close the context
if (context)
{
CloseFileRestoreContext(context);
context = NULL;
}
}
Please note this is still a very rudimentary app in its beginning stages. It basically begins a scan, defaulting (if no args are given) to scanning the D:\ drive and attempting to restore a deleted file to X:\testfile.txt. For those that may not be familiar with WinPE, X: is the system drive in a WinPE environment, and D: is usually the letter assigned to the OS drive of the machine that is booted to PE while in the PE environment, depending on the setup, with C: being the system reserved partition.
For each restorable file found, it pauses, and if the user enters the text "RESTORE" and hits ENTER, it will attempt to restore the file (this takes place around line 247). The callback function that indicates status for the restoration returns error code 6 (via FinalResult), as does GetLastError().
Any help on this is very much appreciated!

c/c++ how can i get base address of .exe running process?

Im looking for a method/function that i can use to get base address of "program.exe"+03262C08 -> B4895A0. This address is from Cheat Engine and base address has been found with Pointer scanner. In pointer scanner i can press show module list and there is address of program.exe starting at address 00400000 program.exe. Pointer scanner was scanned for address 09c3000(The address which i want to reach after base address+many offsets[the final address]). This address is base for certain object but i cant reach the address. I'm able to get only base address of exe file at 00400000. I'm trying to add offsets from pointer 03262C08(and the others) but i cant still reach the address. I cant use function FindWindow(). Becouse a name of the program will be changing and it will be redundant to stick with it. I'm using OpenProcess(), EnumProcessModulesEx(), GetModuleFileNameEx() functions. I have tried others as well like GetModuleInformation(),... with the same result. GetModuleHandle() ended with result 0x126 [ERROR_MOD_NOT_FOUND]. I'm using 64 bit OS and I'm trying to get base address of another process.
I can see all processes on local machine and modules of "program" process.
if (!K32EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) {
return 1;
}
cProcesses = cbNeeded / sizeof(DWORD);
cout << setw(15) << left << "Process ID" << setw(10) << left << "Modules";
cout << setw(30) << left << "Process Name" << endl;
for (i = 0; i < cProcesses; i++) {
if (aProcesses[i] != 0) {
ProcessView::GetProccesses(aProcesses[i], modules, sizeModules, &cModules, &hCurrProcess);
if (hCurrProcess != NULL) {
cout << endl << setw(15) << left << aProcesses[i] << setw(10) << left << cModules;
ProcessView::PrintModuleName(hCurrProcess, modules);
CloseHandle(hCurrProcess);
}
}
}
ProcessView::GetProccesses(cProcesses, modules, sizeModules, &cModules, &hCurrProcess);
system("cls");
ProcessView::PrintModuleNameAll(hCurrProcess, modules, cModules);
I added here definition of function in example from ProcessView.h file that i have created.
static void GetProccesses(_In_ DWORD processID, _Inout_ HMODULE ahModules[], _In_ int sizeModules, _Out_ DWORD* cModules, _Out_ HANDLE* hProcess);
static void PrintModuleName(_In_ HANDLE processID, _In_ HMODULE* modules);
static void PrintModuleNameAll(_In_ HANDLE hProcess, _In_ HMODULE * modules, _In_ DWORD cModules);
Windows has been using Address Space Layout Randomization for about a decade now, but the module base in EXE's is far older than that. Simply ignore it, it's now meaningless.
And don't forget: each process has its own address space. A pointer in one process is meaningless in the other.
To use ReadProcessMemory or WriteProcessMemory on an address which is found via pointer chain on a process and dynamically get the module base address at runtime you need to accomplish these steps:
Find the Process with ToolHelp32Snapshot
Find the Module with ToolHelp32Snapsho
Get a handle to the process with correct permissions
Walk the pointer chain, de-referencing and adding offsets
Then you can Call ReadProcessMemory or WriteProcessMemory
You must run as administrator
For this example I will use a simple assault cube cheat I've made
#include <iostream>
#include <vector>
#include <Windows.h>
#include "proc.h"
int main()
{
//Get ProcId of the target process
DWORD procId = GetProcId(L"ac_client.exe");
//Getmodulebaseaddress
uintptr_t moduleBase = GetModuleBaseAddress(procId, L"ac_client.exe");
//Get Handle to Process
HANDLE hProcess = 0;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, procId);
//Resolve base address of the pointer chain
uintptr_t dynamicPtrBaseAddr = moduleBase + 0x10f4f4;
std::cout << "DynamicPtrBaseAddr = " << "0x" << std::hex << dynamicPtrBaseAddr << std::endl;
//Resolve our ammo pointer chain
std::vector<unsigned int> ammoOffsets = { 0x374, 0x14, 0x0 };
uintptr_t ammoAddr = FindDMAAddy(hProcess, dynamicPtrBaseAddr, ammoOffsets);
std::cout << "ammoAddr = " << "0x" << std::hex << ammoAddr << std::endl;
//Read Ammo value
int ammoValue = 0;
ReadProcessMemory(hProcess, (BYTE*)ammoAddr, &ammoValue, sizeof(ammoValue), nullptr);
std::cout << "Curent ammo = " << std::dec << ammoValue << std::endl;
//Write to it
int newAmmo = 1337;
WriteProcessMemory(hProcess, (BYTE*)ammoAddr, &newAmmo, sizeof(newAmmo), nullptr);
//Read out again
ReadProcessMemory(hProcess, (BYTE*)ammoAddr, &ammoValue, sizeof(ammoValue), nullptr);
std::cout << "New ammo = " << std::dec << ammoValue << std::endl;
getchar();
return 0;
}
The header file proc.cpp:
DWORD GetProcId(const wchar_t* procName)
{
DWORD procId = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof(procEntry);
if (Process32First(hSnap, &procEntry))
{
do
{
if (!_wcsicmp(procEntry.szExeFile, procName))
{
procId = procEntry.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &procEntry));
}
}
CloseHandle(hSnap);
return procId;
}
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, 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;
}
uintptr_t FindDMAAddy(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
uintptr_t addr = ptr;
for (unsigned int i = 0; i < offsets.size(); ++i)
{
ReadProcessMemory(hProc, (BYTE*)addr, &addr, sizeof(addr), 0);
addr += offsets[i];
}
return addr;
}

Write in another process' memory with WriteProcessMemory and a Pointer [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
There are probably several post that explain my problem in several ways... But I have been searching in google and stackoverflow searchbox and I didn't found anything. So here I go.
I want to Write in a Process Memory a String Changing it in c++, but I don't even know clearly how it work so..
I have this pointer:
Image of the pointer
Please, can someone help me doing it?
I've tried it but it's not working..
#include <windows.h>
#include <iostream>
int main() {
HWND hWnd = FindWindow(0, "WindowName");
if (hWnd == 0) {
std::cout << "Cannot find window." << std::endl;
}
DWORD pId;
GetWindowThreadProcessId(hWnd, &pId);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
DWORD baseAddress = 0x009B03D0;
DWORD offset = 0xA7;
DWORD ptrAddress;
char *newString = "newvalue";
ReadProcessMemory(hProc, (void*)baseAddress, &ptrAddress, sizeof(DWORD), 0);
WriteProcessMemory(hProc, (void*)(ptrAddress + offset), newString, strlen(newString), 0);
std::cout << "Done. " << &ptrAddress << std::endl;
std::getchar();
}
I should get the pointer and jumpt to the last one because I only have one offset.. But I'm not getting the correct one..
Edit:
Here is my new code, it works until the WriteProcessMemory function.. What can be wrong?
CODE THAT ACTUALLY WORKS:
int main()
{
unsigned long Pointer; /* to hold the final value */
unsigned long temp; /* hold the temp values */
unsigned long address = 0x009B03D0;
unsigned long offset = 0xA7;
unsigned long newString = 0;
DWORD pid;
HWND hwnd;
hwnd = FindWindow(0, TEXT("NewWindow"));
if (!hwnd)
{
cout << "No!\n";
cin.get();
}
else
{
GetWindowThreadProcessId(hwnd, &pid);
HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (!phandle)
{
cout << "None!\n";
cin.get();
}
else
{
while (1)
{
ReadProcessMemory(phandle, reinterpret_cast<LPVOID>(address), &temp, sizeof(temp), 0);
Pointer = temp + offset;
//Good
ReadProcessMemory(phandle, reinterpret_cast<LPVOID>(Pointer), &newString, 16, 0);
cout << reinterpret_cast<LPVOID>(Pointer) << " en " << newString;
Sleep(1000);
}
return 0;
}
}
}
CODE THAT NOT WORK:
int main()
{
unsigned int Pointer; /* to hold the final value */
unsigned int temp; /* hold the temp values */
unsigned int address = 0x009B03D0;
unsigned int offset = 0xA7;
unsigned int newString = 1768060259;
DWORD pid;
HWND hwnd;
hwnd = FindWindow(0, TEXT("NewWindow"));
if (!hwnd)
{
cout << "NO\n";
cin.get();
}
else
{
GetWindowThreadProcessId(hwnd, &pid);
HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (!phandle)
{
cout << "NONE\n";
cin.get();
}
else
{
while (1)
{
ReadProcessMemory(phandle, reinterpret_cast<LPVOID>(address), &temp, sizeof(temp), 0);
Pointer = temp + offset;
//Good
if (!WriteProcessMemory(phandle, reinterpret_cast<LPVOID>(Pointer), &newString, sizeof(newString), 0))
std::cerr << "Couldn't write process memory:" << GetLastError() << std::endl;
cout << reinterpret_cast<LPVOID>(Pointer) << " en " << newString;
Sleep(1000);
}
return 0;
}
}
}
Each process has its own memory and address space. So ReadProcessMemory() and WriteProcessMemory() use an intermediary buffer to do their job of accessing memory of another process.
Unfortunately, there are issues with your ReadProcessMemory() call:
you don't initialise ptrAddress to point to a buffer
you pass the address of ptrAddress and not its value that should point to a valid buffer
you pass 0 (i.e. a nullptr) instead of passing the address of the zie variable that should contain the number of bytes that could be read.
Note also that you manage the address in the target process using a DWORD for a LPCVOID. The first is always 32 bits, while the latter depend on your compiling options (32 bit code or 64 bit code).
You should also verify the error code in case of failure. It is almost certain taht special priviledges are required to read/write in distinct processes.
Here an adjusted code, with some diagnosis messages to help you further.
HWND hWnd = FindWindow(0, TEXT("WindowName") );
if (hWnd == 0) {
std::cerr << "Cannot find window." << std::endl;
}
else {
DWORD pId;
GetWindowThreadProcessId(hWnd, &pId);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
if (hProc) {
char *newString = "newvalue";
size_t sz = strlen(newString) + 1;
LPVOID baseAddress = (LPVOID)0x009B03D0;
DWORD offset = 0xA7;
LPVOID ptrAddress = new char[sz];
SIZE_T bytes_read = 0, bytes_written=0;
if (ReadProcessMemory(hProc, baseAddress, ptrAddress, sz, &bytes_read) || GetLastError()== ERROR_PARTIAL_COPY) {
if (bytes_read == 0)
std::cerr << "Houston, we have a problem..." << std::endl;
if(!WriteProcessMemory(hProc, baseAddress, (LPCVOID)newString, sz, &bytes_written))
std::cerr << "Couldn't write process memory:" << GetLastError() << std::endl;
std::cout << "Done. " << bytes_read <<" bytes read and "<<bytes_written<<" bytes written"<< std::endl;
}
else {
std::cerr<< "Couldn't read process memory:" << GetLastError() << std::endl;
}
delete[] ptrAddress;
}
else {
std::cerr << "Couldn't open process " << pId << ": " << GetLastError() << std::endl;
}
}
std::getchar();

Edited code using ReadProcessMemory has issues

asked a question Call CloseHandle on handle that is a function parameter?
After someone edited the code, I updated it to find the code no longer works as intended.
intptr_t readMem(HANDLE processHandle, intptr_t address, int sizeToReadBytes)
{
intptr_t memValue = 0;
bool success = ReadProcessMemory(processHandle, (LPVOID)address, memValue, sizeToReadBytes, NULL);
if (!success)
std::wcout << "Memory read failed on address: " << std::hex << address << "\n";
return memValue;
}
In the line
ReadProcessMemory(processHandle, (LPVOID)address, memValue, sizeToReadBytes, NULL);
The memValue wouldn't compile without (LPVOID) or (LPCVOID) casts, but with them the code no longer reads the memory (or writes in the case of the functions using WriteProcessMemory
Originally (and now I've changed it back in my little program) it uses a reference &memValue and works fine.
My question is:
Should this work?
Or is the edit correct and the rest of my program potentially wrong?
I can provide more code if needed, just not sure which bits and didn't want to clog up the screen more than I have... Also should I rollback the edit?
The third parameter of ReadProcessMemory() is a memory address in the calling process where the function writes the read data to. You are not passing a memory address, though. In the code shown in the third revision to the original question, you were type-casting the value of an uninitialized integer variable into a memory pointer. So the function would try to write to random memory. Now you have removed the type-cast, so the code should not even compile anymore.
Your readMem() function is not designed correctly. You need to change it so that either:
The caller allocates memory of the required size and then the function simply fills the memory:
bool readMem(HANDLE processHandle, intptr_t address, void *memValue, int sizeToReadBytes)
{
bool success = ReadProcessMemory(processHandle, (LPVOID)address, memValue, sizeToReadBytes, NULL);
if (!success)
std::wcout << "Memory read failed on address: " << std::hex << address << "\n";
return success;
}
intptr_t memValue = 0;
readMem(processHandle, address, &memValue, sizeof(memValue));
The function allocates memory and returns it to the caller:
void* readMem(HANDLE processHandle, intptr_t address, int sizeToReadBytes)
{
uint8_t memValue = new uint8_t[sizeToReadBytes];
bool success = ReadProcessMemory(processHandle, (LPVOID)address, memValue, sizeToReadBytes, NULL);
if (!success) {
std::wcout << "Memory read failed on address: " << std::hex << address << "\n";
delete [] memValue;
memValue = NULL;
}
return memValue;
}
intptr_t *memValue = (intptr_t*) readMem(processHandle, address, sizeof(intptr_t));
...
delete [] memValue;
Or:
bool readMem(HANDLE processHandle, intptr_t address, int sizeToReadBytes, std:vector<uint8_t> &memValue)
{
memValue.resize(sizeToReadBytes);
bool success = ReadProcessMemory(processHandle, (LPVOID)address, &memValue[0], sizeToReadBytes, NULL);
if (!success)
std::wcout << "Memory read failed on address: " << std::hex << address << "\n";
return success;
}
std::vector<uint8_t> buffer;
readMem(processHandle, address, sizeof(intptr_t), buffer);
intptr_t memValue = (intptr_t*) &buffer[0];

Why won't my program inject my .dll properly?

Been stuck for a few hours making a (simple) dll injector that takes a .dll file and a process as arguments and then injects said .dll into the process, and I'm about to start tearing my hair out.
It doesn't function properly, and for no obvious reason either. The dll simply won't load into the process, but without any error messages being displayed. I did the exact same thing but with ANSI functions instead of Unicode and it worked like a charm, which after some testing is leading me to believe it's PROBABLY a problem with the file path not being loaded properly but I have no idea why.
I've attached my entire source code below and added some comments to hopefully clarify somewhat. And like I said, if I'm right, then the important part should start somewhere around:
//Get the full path of our dll and store it in a variable
Help a bro out.
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;
int main()
{
HANDLE hSnapshot, hProc = NULL;
PROCESSENTRY32 PE32;
PE32.dwSize = sizeof(PROCESSENTRY32);
WCHAR injProcName[100] = {NULL}, injDllName[100] = {NULL};
//Let user input options
cout << "Dll injector started!" << endl << "Please enter the name of the dll you would like to inject: ";
wcin >> injDllName;
cout << "Enter the name of the target process: ";
wcin >> injProcName;
//Create snapshot
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
Process32First(hSnapshot, &PE32);
//Load the first process into PE32 and loop to see if target process is running
do {
if(wcscmp(PE32.szExeFile, injProcName) == 0) {
wcout << PE32.szExeFile << " found!" << endl;
wcout << "Attempting to open " << injProcName << ".." << endl;
hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PE32.th32ProcessID);
if(!hProc)
{
cout << "Failed to open process!" << endl;
return 1;
}
break;
}
}
while(Process32Next(hSnapshot, &PE32));
if(!hProc) {
cout << "Unable to locate process!" << endl;
return 1;
}
cout << "Process successfully opened!" << endl;
//Get the full path of our dll and store it in a variable
WCHAR DllPath[MAX_PATH] = {NULL};
GetFullPathName(injDllName, MAX_PATH, DllPath, NULL);
wcout << DllPath << endl;
//Allocate memory in target process
cout << "Allocating memory.." << endl;
LPVOID DllMemAddr = VirtualAllocEx(hProc,
NULL,
wcslen(DllPath),
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
//Write our path into target process memory
wcout << "Writing dll to target process.." << endl;
WriteProcessMemory(hProc,
DllMemAddr,
DllPath,
wcslen(DllPath),
NULL);
//Get the memory address of LoadLibraryW
LPVOID LoadAddr = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
//Finally, start a new thread with the address of LoadLibraryW and our dll path as argument
cout << "Executing dll in remote process.." << endl;
CreateRemoteThread(hProc,
NULL,
NULL,
(LPTHREAD_START_ROUTINE)LoadAddr,
DllMemAddr,
NULL,
NULL);
cout << "Dll sucessfully injected!" << endl;
cin.get();
return 0;
}
wcslen returns length in wchar_t units. But VirtualAllocEx and WriteProcessMemory receive a length in byte units. So you only write half the string, because wchar_t is two bytes wide. And you did not write the null terminator.
You need to pass (wcslen(DllPath)+1)*sizeof(wchar_t).
Incidentally, your ANSI code was probably broken too because, presumably, it also missed the null terminator. But you probably got away with it by chance.
A little error checking would not go amis, while we are in the business of looking at your code. And initialising DllPath is a little pointless when you follow it with the call to GetFullPathName.