Code:
#include <iostream>
#include <windows.h>
#include <Tlhelp32.h>
#include <vector>
#include <fstream>
#include <Shlwapi.h>
using namespace std;
typedef struct ProcessInfo {
int procId;
char * procName;
} ProcessInfo;
ProcessInfo EnumerateProcesses();
void PrintMemoryProtection(DWORD constant);
int CheckProtection(DWORD constant);
int main(int argc, char * argv[]) {
if (argc != 2 && argc != 1) {
printf("Usage: <memHack.exe> <executable.exe>\n");
return 1;
}
char path[MAX_PATH];
GetModuleFileName(0, path, MAX_PATH);
PathRemoveFileSpec(path);
SetCurrentDirectory(path);
LUID privLuid;
HANDLE hTokenHandle = 0;
// Change the process security token to debug mode
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hTokenHandle))
printf("[!] Error opening process token: %d\n", GetLastError());
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privLuid))
printf("[!] Error looking up the privilege value: %d\n", GetLastError());
TOKEN_PRIVILEGES sTokenPrivs;
sTokenPrivs.PrivilegeCount = 1;
sTokenPrivs.Privileges[0].Luid = privLuid;
sTokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hTokenHandle, FALSE, &sTokenPrivs, NULL, NULL, NULL))
printf("[!] Error adjusting process token privileges: %d\n", GetLastError());
CloseHandle(hTokenHandle);
bool userInput = false;
ProcessInfo sProcInfo;
memset(&sProcInfo, 0, sizeof(ProcessInfo));
/* Check if file exists */
if (argc == 2) {
OFSTRUCT fileInfo;
HFILE fileHandle = 0;
if ((fileHandle = OpenFile(argv[1], &fileInfo, OF_EXIST)) == HFILE_ERROR) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
printf("[!] File \"%s\" does not exist.\n", argv[1]);
CloseHandle((HANDLE)fileHandle);
return 1;
}
}
CloseHandle((HANDLE)fileHandle);
}
/* If not parsed a file to load, enumerate processes for user decision */
else {
userInput = true;
sProcInfo = EnumerateProcesses();
}
HANDLE targetProcess = 0;
/* Opening a running process or loading a process */
if (userInput) {
if ((targetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, sProcInfo.procId)) == NULL) {
printf("[!] Error acquiring %s process handle with PID %d: %d\n", sProcInfo.procName, sProcInfo.procId, GetLastError());
return 1;
}
}
else {
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInformation;
memset(&startupInfo, 0, sizeof STARTUPINFO);
memset(&processInformation, 0, sizeof PROCESS_INFORMATION);
startupInfo.cb = sizeof STARTUPINFO;
if (!CreateProcess(argv[1], NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation)) {
printf("[!] Error loading program and creating process: %d\n", GetLastError());
return 1;
}
if (processInformation.hProcess)
targetProcess = processInformation.hProcess;
if (processInformation.hThread)
CloseHandle(processInformation.hThread);
}
MEMORY_BASIC_INFORMATION mbi;
SYSTEM_INFO si;
GetSystemInfo(&si);
void * memCount = 0;
unsigned char * memoryDump = 0;
ofstream file("dump.txt");
while (memCount < si.lpMaximumApplicationAddress) {
VirtualQueryEx(targetProcess, memCount, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
memoryDump = new unsigned char[mbi.RegionSize];
if (CheckProtection(mbi.Protect)) {
if (ReadProcessMemory(targetProcess, mbi.BaseAddress, memoryDump, mbi.RegionSize, NULL)) {
for (SIZE_T n = 0; n < mbi.RegionSize; n++) {
if (byteCount % 16 == 0)
sprintf((char *)file, "\n0x%x: ", (unsigned long)mbi.BaseAddress + n);
file.write((const char *)memoryDump, mbi.RegionSize);
delete [] memoryDump;
}
}
memCount = (LPVOID)((unsigned long)mbi.BaseAddress + (unsigned long)mbi.RegionSize);
}
file.close();
if (targetProcess)
CloseHandle(targetProcess);
}
// Returns the name of the user chosen process
ProcessInfo EnumerateProcesses() {
HANDLE hSnapshot = 0;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) {
printf("[!] Failed to obtain process snapshot handle: %d\n", GetLastError());
CloseHandle(hSnapshot);
exit(0);
}
PROCESSENTRY32 sProc;
sProc.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hSnapshot, &sProc)) {
printf("Failed to enumerate first process from snapshot: %d\n", GetLastError());
CloseHandle(hSnapshot);
exit(0);
}
vector<char *> processes;
vector<int> processIds;
do {
char * tmp = new char[MAX_PATH];
strcpy(tmp, sProc.szExeFile);
processes.push_back(tmp);
processIds.push_back(sProc.th32ProcessID);
} while (Process32Next(hSnapshot, &sProc));
for (unsigned int i = 2; i < processes.size(); i++)
printf("[%02d] %s - %d\n", i - 1, processes[i], processIds[i]);
int process = 0;
printf("\nProcess #: ");
cin >> process;
process += 1;
ProcessInfo sProcInfo;
sProcInfo.procName = new char[MAX_PATH];
strcpy(sProcInfo.procName, processes[process]);
sProcInfo.procId = processIds[process];
for (unsigned int i = 0; i < processes.size(); i++)
delete [] processes[i];
return sProcInfo;
}
int CheckProtection(DWORD constant) {
switch (constant) {
case PAGE_EXECUTE:
return 1;
break;
case PAGE_EXECUTE_READ:
return 1;
break;
case PAGE_EXECUTE_READWRITE:
return 1;
break;
case PAGE_EXECUTE_WRITECOPY:
return 1;
break;
case PAGE_NOACCESS:
return 0;
break;
case PAGE_READONLY:
return 1;
break;
case PAGE_READWRITE:
return 1;
break;
case PAGE_WRITECOPY:
return 1;
break;
default:
return 0;
}
}