mirror of
https://github.com/waryas/WaryasSWHE.git
synced 2025-12-13 13:23:08 +08:00
Add files via upload
This commit is contained in:
901
exploit.cpp
Normal file
901
exploit.cpp
Normal file
@@ -0,0 +1,901 @@
|
||||
#include "exploit.hpp"
|
||||
#include "utils.hpp"
|
||||
#include <psapi.h>
|
||||
#include <stdio.h>
|
||||
#include <Windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <stdint.h>
|
||||
#include <winternl.h>
|
||||
#include <mmsystem.h>
|
||||
#include <time.h>
|
||||
#include <shlwapi.h>
|
||||
#include <unordered_set>
|
||||
#include "pe_mapper.hpp"
|
||||
|
||||
#define NTHEADER(ImgBase) PIMAGE_NT_HEADERS64(PIMAGE_DOS_HEADER(ImgBase)->e_lfanew + uint64_t(ImgBase))
|
||||
#define SET_BIT(Val, Num, Up) \
|
||||
{ \
|
||||
if (Up) \
|
||||
{ \
|
||||
Val |= (1 << Num); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Val &= ~(1 << Num); \
|
||||
} \
|
||||
}
|
||||
#define IS_BIT_SET(Val, Num) (Val & (1 << Num))
|
||||
|
||||
#define SHARED_MEM_WPARAM_STRUCT 0x800
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned char* make_fake_pe() {
|
||||
unsigned char* p = (unsigned char*)malloc(0x200);
|
||||
if (!p) return NULL;
|
||||
memset(p, 0, 0x200);
|
||||
*(unsigned short*)(p + 0x0) = 0x5A4D;
|
||||
*(unsigned int*)(p + 0x3C) = 0x40;
|
||||
*(unsigned int*)(p + 0x40) = 0x00004550;
|
||||
*(unsigned short*)(p + 0x44) = 0x8664;
|
||||
*(unsigned short*)(p + 0x46) = 1;
|
||||
*(unsigned short*)(p + 0x54) = 0xF0;
|
||||
*(unsigned short*)(p + 0x58) = 0x20B;
|
||||
*(unsigned int*)(p + 0x58 + 0x10) = 0x0;
|
||||
size_t sec = 0x148;
|
||||
memcpy(p + sec + 0x0, ".data\0\0\0", 8);
|
||||
*(unsigned int*)(p + sec + 0x8) = 0x1000;
|
||||
*(unsigned int*)(p + sec + 0xC) = 0x100000 - 0x1000; //offset
|
||||
*(unsigned int*)(p + sec + 0x10) = 0x1000; //size
|
||||
*(unsigned int*)(p + sec + 0x14) = 0x200;
|
||||
*(unsigned int*)(p + sec + 0x24) = 0x60000000u; //permission
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
OBFUSCATE void CExploit::ChangeProtection(uint64_t Address, size_t size, DWORD protection) {
|
||||
ShowWindow(ProcessData->ProcessHwnd, 0);
|
||||
Sleep(0);
|
||||
|
||||
|
||||
struct wparam {
|
||||
uint64_t memcpy{};
|
||||
uint64_t arg2{};
|
||||
uint64_t function_ptr{};
|
||||
uint64_t arg1{};
|
||||
uint64_t lock{};
|
||||
UNICODE_STRING dst{}; // 0x28
|
||||
UNICODE_STRING src{}; // 0x38
|
||||
uint64_t val{}; // 0x48
|
||||
|
||||
};
|
||||
|
||||
wparam* a = (wparam*)(LocalSharedMemory + SHARED_MEM_WPARAM_STRUCT);
|
||||
|
||||
memset(a, 0, sizeof(wparam));
|
||||
a->arg1 = PAGE_READWRITE;
|
||||
a->arg2 = rand()*rand();
|
||||
a->memcpy = set_mrprot;
|
||||
a->function_ptr = t;
|
||||
a->lock = 0;
|
||||
|
||||
|
||||
auto hhook = SetWindowsHookExA(WH_SHELL, (HOOKPROC)w, ddll, ProcessData->ThreadID);
|
||||
if (!hhook) {
|
||||
printf("Failed critical %08x - process has crashed!\n", GetLastError());
|
||||
Sleep(5000);
|
||||
ExitProcess(0);
|
||||
}
|
||||
Sleep(0);
|
||||
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand() * rand());
|
||||
|
||||
a->dst.Length = 8;
|
||||
a->dst.MaximumLength = 8;
|
||||
a->dst.Buffer = (PWSTR)(mr_data_addr_ptr);
|
||||
a->src.Length = 8;
|
||||
a->src.MaximumLength = 8;
|
||||
a->src.Buffer = (PWSTR)(RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x48);
|
||||
a->arg1 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x28;
|
||||
a->arg2 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x38;
|
||||
a->memcpy = write_fn;
|
||||
a->function_ptr = t;
|
||||
a->val = Address;
|
||||
a->lock = 0;
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand()* rand());
|
||||
|
||||
a->dst.Length = 8;
|
||||
a->dst.MaximumLength = 8;
|
||||
a->dst.Buffer = (PWSTR)(mr_data_size_ptr);
|
||||
a->src.Length = 8;
|
||||
a->src.MaximumLength = 8;
|
||||
a->src.Buffer = (PWSTR)(RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x48);
|
||||
a->arg1 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x28;
|
||||
a->arg2 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x38;
|
||||
a->memcpy = write_fn;
|
||||
a->function_ptr = t;
|
||||
a->val = size;
|
||||
a->lock = 0;
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand()* rand());
|
||||
|
||||
a->arg1 = protection;
|
||||
a->arg2 = rand() * rand();
|
||||
a->memcpy = set_mrprot;
|
||||
a->function_ptr = t;
|
||||
a->lock = 0;
|
||||
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand()* rand());
|
||||
|
||||
|
||||
a->dst.Length = 8;
|
||||
a->dst.MaximumLength = 8;
|
||||
a->dst.Buffer = (PWSTR)(mr_data_addr_ptr);
|
||||
a->src.Length = 8;
|
||||
a->src.MaximumLength = 8;
|
||||
a->src.Buffer = (PWSTR)(RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x48);
|
||||
a->arg1 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x28;
|
||||
a->arg2 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x38;
|
||||
a->memcpy = write_fn;
|
||||
a->function_ptr = t;
|
||||
a->val = mr_data_addr_orig;
|
||||
a->lock = 0;
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand()* rand());
|
||||
|
||||
a->dst.Length = 8;
|
||||
a->dst.MaximumLength = 8;
|
||||
a->dst.Buffer = (PWSTR)(mr_data_size_ptr);
|
||||
a->src.Length = 8;
|
||||
a->src.MaximumLength = 8;
|
||||
a->src.Buffer = (PWSTR)(RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x48);
|
||||
a->arg1 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x28;
|
||||
a->arg2 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x38;
|
||||
a->memcpy = write_fn;
|
||||
a->function_ptr = t;
|
||||
a->val = mr_data_size_orig;
|
||||
a->lock = 0;
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand()* rand());
|
||||
|
||||
a->arg1 = PAGE_READONLY;
|
||||
a->arg2 = rand() * rand();
|
||||
a->memcpy = set_mrprot;
|
||||
a->function_ptr = t;
|
||||
a->lock = 0;
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand()* rand());
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
Sleep(0);
|
||||
|
||||
ShowWindow(ProcessData->ProcessHwnd, 1);
|
||||
return;
|
||||
|
||||
}
|
||||
uint64_t CExploit::MapPEHeader(uint64_t Address)
|
||||
{
|
||||
ShowWindow(ProcessData->ProcessHwnd, 0);
|
||||
Sleep(0);
|
||||
|
||||
|
||||
struct wparam {
|
||||
uint64_t memcpy{};
|
||||
uint64_t arg2{};
|
||||
uint64_t function_ptr{};
|
||||
uint64_t arg1{};
|
||||
uint64_t lock{};
|
||||
UNICODE_STRING dst{}; // 0x28
|
||||
UNICODE_STRING src{}; // 0x38
|
||||
uint64_t val{}; // 0x48
|
||||
|
||||
};
|
||||
|
||||
wparam* a = (wparam*)(LocalSharedMemory + SHARED_MEM_WPARAM_STRUCT);
|
||||
|
||||
|
||||
memset(a, 0, sizeof(wparam));
|
||||
a->arg1 = Address;
|
||||
a->arg2 = 0xFFFFFFFFFFFFFFFF;
|
||||
a->memcpy = set_protect;
|
||||
a->function_ptr = t;
|
||||
a->lock = 0;
|
||||
|
||||
|
||||
auto hhook = SetWindowsHookExA(WH_SHELL, (HOOKPROC)w, ddll, ProcessData->ThreadID);
|
||||
if (!hhook) {
|
||||
printf("Failed critical %08x - process has crashed!\n", GetLastError());
|
||||
Sleep(5000);
|
||||
ExitProcess(0);
|
||||
}
|
||||
Sleep(0);
|
||||
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand() * rand());
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
Sleep(0);
|
||||
|
||||
ShowWindow(ProcessData->ProcessHwnd, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint64_t CExploit::AllocateRX(BYTE* data, size_t size)
|
||||
{
|
||||
ShowWindow(ProcessData->ProcessHwnd, 0);
|
||||
Sleep(0);
|
||||
|
||||
|
||||
struct wparam {
|
||||
uint64_t memcpy{};
|
||||
uint64_t arg2{};
|
||||
uint64_t function_ptr{};
|
||||
uint64_t arg1{};
|
||||
uint64_t lock{};
|
||||
UNICODE_STRING dst{}; // 0x28
|
||||
UNICODE_STRING src{}; // 0x38
|
||||
uint64_t val{}; // 0x48
|
||||
|
||||
};
|
||||
|
||||
wparam* a = (wparam*)(LocalSharedMemory + SHARED_MEM_WPARAM_STRUCT);
|
||||
|
||||
|
||||
memset(a, 0, sizeof(wparam));
|
||||
a->arg1 = 0x100000;
|
||||
a->arg2 = rand() * rand();
|
||||
a->memcpy = (uintptr_t)GetProcAddress(LoadLibraryA("msvcrt.dll"), "malloc");
|
||||
a->function_ptr = t;
|
||||
a->lock = 0;
|
||||
|
||||
std::unordered_set<uintptr_t> existing_mem;
|
||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, ProcessData->ProcessID);
|
||||
if (hProcess == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("Failed to open process[%d] error[%d]\n", ProcessData->ProcessID, GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint8_t* Address{};
|
||||
MEMORY_BASIC_INFORMATION Mbi{};
|
||||
while (true)
|
||||
{
|
||||
if (!VirtualQueryEx(hProcess, Address, &Mbi, sizeof(Mbi)))
|
||||
break;
|
||||
|
||||
|
||||
if (Mbi.State == MEM_COMMIT && Mbi.Protect == PAGE_READWRITE && Mbi.RegionSize == 0x101000 && Mbi.Type == MEM_PRIVATE)
|
||||
{
|
||||
existing_mem.insert((uintptr_t)Mbi.BaseAddress);
|
||||
}
|
||||
|
||||
Address += Mbi.RegionSize;
|
||||
}
|
||||
ShowWindow(ProcessData->ProcessHwnd, 0);
|
||||
Sleep(0);
|
||||
auto hhook = SetWindowsHookExA(WH_SHELL, (HOOKPROC)w, ddll, ProcessData->ThreadID);
|
||||
if (!hhook) {
|
||||
printf("Failed critical %08x - process has crashed!\n", GetLastError());
|
||||
Sleep(5000);
|
||||
ExitProcess(0);
|
||||
}
|
||||
Sleep(0);
|
||||
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand() * rand());
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
Sleep(0);
|
||||
|
||||
ShowWindow(ProcessData->ProcessHwnd, 1);
|
||||
Address = 0;
|
||||
uintptr_t found_addr = 0;
|
||||
while (true)
|
||||
{
|
||||
|
||||
if (!VirtualQueryEx(hProcess, Address, &Mbi, sizeof(Mbi)))
|
||||
break;
|
||||
|
||||
// printf("%llx - %llx - %d - %d - %d\n", Address, Mbi.RegionSize, Mbi.Type, Mbi.Protect, Mbi.State);
|
||||
if (Mbi.State == MEM_COMMIT && Mbi.Protect == PAGE_READWRITE && Mbi.RegionSize == 0x101000 && Mbi.Type == MEM_PRIVATE)
|
||||
{
|
||||
if (!existing_mem.contains((uintptr_t)Mbi.BaseAddress)) {
|
||||
found_addr = (uintptr_t)Mbi.BaseAddress;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Address += Mbi.RegionSize;
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
if (found_addr) {
|
||||
auto x = make_fake_pe();
|
||||
unsigned char empty[0x200]{};
|
||||
WriteData(found_addr, (BYTE*)x, 0x200);
|
||||
WriteData(found_addr + 0x100000 - 0x1000, data, size);
|
||||
MapPEHeader(found_addr);
|
||||
WriteData(found_addr, (BYTE*)empty, 0x200);
|
||||
free(x);
|
||||
return found_addr + 0x100000 - 0x1000;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint64_t CExploit::ReadU64(uint64_t Address)
|
||||
{
|
||||
ShowWindow(ProcessData->ProcessHwnd, 0);
|
||||
Sleep(0);
|
||||
|
||||
|
||||
struct wparam {
|
||||
uint64_t memcpy{}; //0
|
||||
uint64_t arg2{}; //8
|
||||
uint64_t function_ptr{}; //0x10
|
||||
uint64_t arg1{}; // 0x18
|
||||
uint64_t lock{}; // 0x20
|
||||
UNICODE_STRING dst{}; // 0x28
|
||||
UNICODE_STRING src{}; // 0x38
|
||||
uint64_t val{}; // 0x48
|
||||
};
|
||||
|
||||
wparam* a = (wparam*)(LocalSharedMemory + SHARED_MEM_WPARAM_STRUCT);
|
||||
|
||||
|
||||
memset(a, 0, sizeof(wparam));
|
||||
|
||||
a->dst.Length = 8;
|
||||
a->dst.MaximumLength = 8;
|
||||
a->dst.Buffer = (PWSTR)(RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x48);
|
||||
a->src.Length = 8;
|
||||
a->src.MaximumLength = 8;
|
||||
a->src.Buffer = (PWSTR)(Address);
|
||||
a->arg1 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x28;
|
||||
a->arg2 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x38;
|
||||
a->memcpy = write_fn;
|
||||
a->function_ptr = t;
|
||||
a->lock = 0;
|
||||
|
||||
|
||||
auto hhook = SetWindowsHookExA(WH_SHELL, (HOOKPROC)w, ddll, ProcessData->ThreadID);
|
||||
if (!hhook) {
|
||||
printf("Failed critical %08x - process has crashed!\n", GetLastError());
|
||||
Sleep(5000);
|
||||
ExitProcess(0);
|
||||
}
|
||||
Sleep(0);
|
||||
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand() % 0xFFFFFFFFFFFFFFFF);
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
Sleep(0);
|
||||
|
||||
ShowWindow(ProcessData->ProcessHwnd, 1);
|
||||
|
||||
return a->val;
|
||||
}
|
||||
|
||||
|
||||
void CExploit::ReadData(uint64_t Address, BYTE* Data, size_t size)
|
||||
{
|
||||
if (size > 0x700) {
|
||||
printf("Read is too big\n");
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
ShowWindow(ProcessData->ProcessHwnd, 0);
|
||||
Sleep(0);
|
||||
|
||||
|
||||
struct wparam {
|
||||
uint64_t memcpy{}; //0
|
||||
uint64_t arg2{}; //8
|
||||
uint64_t function_ptr{}; //0x10
|
||||
uint64_t arg1{}; // 0x18
|
||||
uint64_t lock{}; // 0x20
|
||||
UNICODE_STRING dst{}; // 0x28
|
||||
UNICODE_STRING src{}; // 0x38
|
||||
uint64_t val{}; // 0x48
|
||||
};
|
||||
|
||||
wparam* a = (wparam*)(LocalSharedMemory + SHARED_MEM_WPARAM_STRUCT);
|
||||
|
||||
|
||||
memset(a, 0, sizeof(wparam));
|
||||
|
||||
a->dst.Length = size;
|
||||
a->dst.MaximumLength = size;
|
||||
a->dst.Buffer = (PWSTR)(RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x48);
|
||||
a->src.Length = size;
|
||||
a->src.MaximumLength = size;
|
||||
a->src.Buffer = (PWSTR)(Address);
|
||||
a->arg1 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x28;
|
||||
a->arg2 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x38;
|
||||
a->memcpy = write_fn;
|
||||
a->function_ptr = t;
|
||||
a->lock = 0;
|
||||
|
||||
|
||||
auto hhook = SetWindowsHookExA(WH_SHELL, (HOOKPROC)w, ddll, ProcessData->ThreadID);
|
||||
if (!hhook) {
|
||||
printf("Failed critical %08x - process has crashed!\n", GetLastError());
|
||||
Sleep(5000);
|
||||
ExitProcess(0);
|
||||
}
|
||||
Sleep(0);
|
||||
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand() % 0xFFFFFFFFFFFFFFFF);
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
Sleep(0);
|
||||
|
||||
ShowWindow(ProcessData->ProcessHwnd, 1);
|
||||
|
||||
memcpy(Data, &a->val, size);
|
||||
|
||||
}
|
||||
|
||||
void CExploit::WriteU64(uint64_t Address, uint64_t Value)
|
||||
{
|
||||
ShowWindow(ProcessData->ProcessHwnd, 0);
|
||||
Sleep(0);
|
||||
|
||||
|
||||
struct wparam {
|
||||
uint64_t memcpy{}; //0
|
||||
uint64_t arg2{}; //8
|
||||
uint64_t function_ptr{}; //0x10
|
||||
uint64_t arg1{}; // 0x18
|
||||
uint64_t lock{}; // 0x20
|
||||
UNICODE_STRING dst{}; // 0x28
|
||||
UNICODE_STRING src{}; // 0x38
|
||||
uint64_t val{}; // 0x48
|
||||
};
|
||||
|
||||
wparam* a = (wparam*)(LocalSharedMemory + SHARED_MEM_WPARAM_STRUCT);
|
||||
|
||||
|
||||
memset(a, 0, sizeof(wparam));
|
||||
|
||||
a->dst.Length = 8;
|
||||
a->dst.MaximumLength = 8;
|
||||
a->dst.Buffer = (PWSTR)(Address);
|
||||
a->src.Length = 8;
|
||||
a->src.MaximumLength = 8;
|
||||
a->src.Buffer = (PWSTR)(RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x48);
|
||||
a->arg1 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x28;
|
||||
a->arg2 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x38;
|
||||
a->memcpy = write_fn;
|
||||
a->function_ptr = t;
|
||||
a->val = Value;
|
||||
a->lock = 0;
|
||||
|
||||
|
||||
auto hhook = SetWindowsHookExA(WH_SHELL, (HOOKPROC)w, ddll, ProcessData->ThreadID);
|
||||
if (!hhook) {
|
||||
printf("Failed critical %08x - process has crashed!\n", GetLastError());
|
||||
Sleep(5000);
|
||||
ExitProcess(0);
|
||||
}
|
||||
Sleep(0);
|
||||
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand() % 0xFFFFFFFFFFFFFFFF);
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
Sleep(0);
|
||||
|
||||
ShowWindow(ProcessData->ProcessHwnd, 1);
|
||||
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CExploit::WriteData(uint64_t Address, BYTE* Data, size_t size)
|
||||
{
|
||||
|
||||
struct wparam {
|
||||
uint64_t memcpy{}; //0
|
||||
uint64_t arg2{}; //8
|
||||
uint64_t function_ptr{}; //0x10
|
||||
uint64_t arg1{}; // 0x18
|
||||
uint64_t lock{}; // 0x20
|
||||
UNICODE_STRING dst{}; // 0x28
|
||||
UNICODE_STRING src{}; // 0x38
|
||||
uint64_t val{}; // 0x48
|
||||
};
|
||||
|
||||
wparam* a = (wparam*)(LocalSharedMemory + SHARED_MEM_WPARAM_STRUCT);
|
||||
size_t max_size = 0x50;
|
||||
if (size > max_size) {
|
||||
size_t chunks = (size + max_size - 1) / max_size;
|
||||
for (size_t i = 0; i < chunks; ++i) {
|
||||
size_t remainder = size % max_size;
|
||||
size_t chunk_size = (i == chunks - 1) ? ((remainder == 0) ? max_size : remainder) : max_size;
|
||||
WriteData(Address + i * max_size, Data + i * max_size, chunk_size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ShowWindow(ProcessData->ProcessHwnd, 0);
|
||||
Sleep(0);
|
||||
|
||||
memset(a, 0, sizeof(wparam));
|
||||
|
||||
a->dst.Length = size;
|
||||
a->dst.MaximumLength = size;
|
||||
a->dst.Buffer = (PWSTR)(Address);
|
||||
a->src.Length = size;
|
||||
a->src.MaximumLength = size;
|
||||
a->src.Buffer = (PWSTR)(RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x48);
|
||||
a->arg1 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x28;
|
||||
a->arg2 = RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT + 0x38;
|
||||
a->memcpy = write_fn;
|
||||
a->function_ptr = t;
|
||||
|
||||
a->lock = 0;
|
||||
|
||||
memcpy(&a->val, Data, size);
|
||||
|
||||
auto hhook = SetWindowsHookExA(WH_SHELL, (HOOKPROC)w, ddll, ProcessData->ThreadID);
|
||||
if (!hhook) {
|
||||
printf("Failed critical %08x - process has crashed!\n", GetLastError());
|
||||
Sleep(5000);
|
||||
ExitProcess(0);
|
||||
}
|
||||
Sleep(0);
|
||||
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)RemoteSharedMemory + SHARED_MEM_WPARAM_STRUCT, rand() % 0xFFFFFFFFFFFFFFFF);
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
Sleep(0);
|
||||
|
||||
ShowWindow(ProcessData->ProcessHwnd, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool CExploit::Initialize(CProcess* Proc)
|
||||
{
|
||||
srand(GetTickCount());
|
||||
ProcessData = Proc;
|
||||
nt = LoadLibraryA("ntdll.dll");
|
||||
sh = LoadLibraryA("shell32.dll");
|
||||
ddll = LoadLibraryA("uxtheme.dll");
|
||||
|
||||
// Locate shared memory in our client.
|
||||
if (!FindSharedMemory(HANDLE(-1), &LocalSharedMemory, &SharedCount, (char*)"randomfuckingnameyougotnoidea.exe"))
|
||||
{
|
||||
printf("Failed to find shared memory in current process\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, ProcessData->ProcessID);
|
||||
if (hProcess == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("Failed to open process[%d] error[%d]\n", ProcessData->ProcessID, GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FindSharedMemory(hProcess, &RemoteSharedMemory, &SharedCount, ProcessData->exe_name))
|
||||
{
|
||||
CloseHandle(hProcess);
|
||||
printf("Failed to find shared memory in target process\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
PROCESS_BASIC_INFORMATION pbi{};
|
||||
NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), 0);
|
||||
ProcessData->peb = (uintptr_t)pbi.PebBaseAddress;
|
||||
CloseHandle(hProcess);
|
||||
|
||||
if ((*(uint32_t*)0x7FFE0260) >= 26100)
|
||||
{
|
||||
|
||||
|
||||
typedef struct _THREAD_BASIC_INFORMATION {
|
||||
NTSTATUS ExitStatus;
|
||||
PVOID TebBaseAddress;
|
||||
CLIENT_ID ClientId;
|
||||
KAFFINITY AffinityMask;
|
||||
KPRIORITY Priority;
|
||||
KPRIORITY BasePriority;
|
||||
} THREAD_BASIC_INFORMATION;
|
||||
|
||||
HANDLE hThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, false, ProcessData->ThreadID);
|
||||
THREAD_BASIC_INFORMATION x{};
|
||||
ULONG retlen{};
|
||||
NtQueryInformationThread(hThread, (THREADINFOCLASS)0, &x, sizeof(x), &retlen);
|
||||
CloseHandle(hThread);
|
||||
PVOID attack_addr = (PVOID)((uint64_t)x.TebBaseAddress + 0x1850);
|
||||
ShowWindow(ProcessData->ProcessHwnd, SW_HIDE); //wtf man
|
||||
auto hhook = SetWindowsHookExA(WH_SHELL, (HOOKPROC)GetProcAddress(nt, "RtlOpenCrossProcessEmulatorWorkConnection"), ddll, ProcessData->ThreadID);
|
||||
Sleep(0);
|
||||
SendMessageA(ProcessData->ProcessHwnd, WM_APPCOMMAND, (WPARAM)attack_addr, (LPARAM)attack_addr);
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
ShowWindow(ProcessData->ProcessHwnd, SW_SHOW); //wtf man
|
||||
printf("Fixup applied\n");
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (!ProcessData->discord_path)
|
||||
{
|
||||
printf("Failed to find discord path\n");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
/* Map and get discord rwx */
|
||||
|
||||
{
|
||||
|
||||
|
||||
const char* writeGadgetPattern = "?? 89 ?? ?? 08 57 ?? 83 ?? 20 ?? 8d ?? 20 ?? 8b ?? e8";
|
||||
|
||||
w = (uintptr_t)PatternScan(nt, writeGadgetPattern);
|
||||
if (!w) {
|
||||
printf("Failed to find W\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* trampPattern = "48 83 ec ?? 48 8b da 48 85 d2 74 ?? 83 7a ?? ?? 75 ?? 83 7a ?? ?? 75 ??";
|
||||
|
||||
t = (uintptr_t)PatternScan(sh, trampPattern);
|
||||
if (!t) {
|
||||
printf("Failed to find t\n");
|
||||
return false;
|
||||
}
|
||||
t = t & 0xFFFFFFFFFFFFFFF0;
|
||||
|
||||
const char* setProtectPattern = "48 8b e9 48 8b d1 41 8d 48 03";
|
||||
set_protect = (uintptr_t)PatternScan(nt, setProtectPattern);
|
||||
if (!set_protect) {
|
||||
printf("Failed to find set_protect\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
while (*(unsigned char*)set_protect != 0xCC) set_protect--;
|
||||
set_protect++;
|
||||
|
||||
|
||||
const char* mrDataPattern = "48 8B 05 ?? ?? ?? ?? 4C 8D 44 24 ?? 48 89 44 24";
|
||||
set_mrprot = (uintptr_t)PatternScan(nt, mrDataPattern);
|
||||
|
||||
if (!set_mrprot) {
|
||||
printf("Failed to find set_mrprot\n");
|
||||
return false;
|
||||
}
|
||||
mr_data_addr_ptr = set_mrprot + *(int32_t*)(set_mrprot + 3) + 7;
|
||||
mr_data_size_ptr = set_mrprot + *(int32_t*)(set_mrprot + 3) + 7 - 0x10;
|
||||
|
||||
mr_data_addr_orig = *(uintptr_t*)mr_data_addr_ptr;
|
||||
mr_data_size_orig = *(uintptr_t*)mr_data_size_ptr;
|
||||
|
||||
while (*(unsigned char*)set_mrprot != 0xCC) set_mrprot--;
|
||||
set_mrprot++;
|
||||
|
||||
|
||||
write_fn = (uint64_t)GetProcAddress(nt, "RtlCopyString");
|
||||
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t CExploit::get_LocalSharedMemory()
|
||||
{
|
||||
return LocalSharedMemory;
|
||||
}
|
||||
|
||||
uint64_t CExploit::get_RemoteSharedMemory()
|
||||
{
|
||||
return RemoteSharedMemory;
|
||||
}
|
||||
|
||||
uint64_t CExploit::get_RemoteBase()
|
||||
{
|
||||
return RemoteProcessBase;
|
||||
}
|
||||
|
||||
|
||||
bool CExploit::FindSharedMemory(HANDLE hProcess, uint64_t* MemoryOut, uint64_t* SharedCountOut, char* exe_name)
|
||||
{
|
||||
if (hProcess == (HANDLE)-1)
|
||||
{
|
||||
uint8_t* Address{};
|
||||
MEMORY_BASIC_INFORMATION Mbi{};
|
||||
bool found_it = false;
|
||||
while (true)
|
||||
{
|
||||
if (!VirtualQueryEx(hProcess, Address, &Mbi, sizeof(Mbi)))
|
||||
break;
|
||||
if (Mbi.State == MEM_COMMIT && Mbi.Protect == PAGE_READWRITE && Mbi.RegionSize == 0x1000 && Mbi.Type == MEM_MAPPED)
|
||||
{
|
||||
//scan inside SHCore.dll to see if this address is inside data
|
||||
auto shcore = LoadLibraryA("SHCore.dll");
|
||||
uint8_t* Address2 = (uint8_t*)shcore;
|
||||
MEMORY_BASIC_INFORMATION Mbi2{};
|
||||
int i = 0;
|
||||
while (VirtualQuery(Address2, &Mbi2, sizeof(Mbi2)))
|
||||
{
|
||||
if (i >= 9)
|
||||
break;
|
||||
if (Mbi2.Type == MEM_IMAGE && Mbi2.Protect == PAGE_READWRITE)
|
||||
{
|
||||
for (int ii = 0; ii < Mbi2.RegionSize; ii += 0x8)
|
||||
{
|
||||
if (*(uintptr_t*)&Address2[ii] == (uintptr_t)Mbi.BaseAddress)
|
||||
{
|
||||
found_it = true;
|
||||
*MemoryOut = (uintptr_t)Mbi.BaseAddress;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found_it)
|
||||
break;
|
||||
|
||||
i++;
|
||||
Address2 += Mbi2.RegionSize;
|
||||
}
|
||||
}
|
||||
if (found_it)
|
||||
break;
|
||||
Address += Mbi.RegionSize;
|
||||
}
|
||||
|
||||
|
||||
/* HANDLE h_map;
|
||||
|
||||
h_map = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, "windows_shell_global_counters");
|
||||
if (h_map == nullptr)
|
||||
return false;
|
||||
|
||||
uintptr_t frame_buffer = (uintptr_t)MapViewOfFile(h_map, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
CloseHandle(h_map);
|
||||
if (!frame_buffer)
|
||||
return false;
|
||||
printf("FrameBuffer: %llx\n", frame_buffer);
|
||||
*MemoryOut = frame_buffer;*/
|
||||
return found_it;
|
||||
}
|
||||
|
||||
|
||||
bool found = false;
|
||||
|
||||
uint8_t* Address{};
|
||||
MEMORY_BASIC_INFORMATION Mbi{};
|
||||
while (true)
|
||||
{
|
||||
if (!VirtualQueryEx(hProcess, Address, &Mbi, sizeof(Mbi)))
|
||||
break;
|
||||
|
||||
if (hProcess != GetCurrentProcess() && Mbi.State == MEM_COMMIT && Mbi.Protect == PAGE_READONLY && Mbi.RegionSize == 0x1000 && Mbi.Type == MEM_IMAGE)
|
||||
{
|
||||
char filename[1024]{};
|
||||
K32GetMappedFileNameA(hProcess, Mbi.BaseAddress, filename, sizeof(filename));
|
||||
if (strstr(filename, "DiscordHook64"))
|
||||
{
|
||||
ProcessData->discord_base = (uintptr_t)Address;
|
||||
char dos_path[1024]{};
|
||||
utils::DevicePathToDosPath(filename, dos_path, sizeof(dos_path));
|
||||
ProcessData->discord_path = _strdup(dos_path);
|
||||
}
|
||||
else if (strstr(filename, "shell32.dll") || strstr(filename, "Shell32.dll") || strstr(filename, "SHELL32.dll"))
|
||||
{
|
||||
if ((uintptr_t)sh != (uintptr_t)Address) {
|
||||
uintptr_t delta = (uintptr_t)Address - (uintptr_t)sh;
|
||||
t += delta;
|
||||
}
|
||||
|
||||
}
|
||||
else if (strstr(filename, exe_name))
|
||||
{
|
||||
ProcessData->base = (uintptr_t)Address;
|
||||
}
|
||||
}
|
||||
else if (!found && Mbi.State == MEM_COMMIT && Mbi.Protect == PAGE_READWRITE && Mbi.RegionSize == 0x1000 && Mbi.Type == MEM_MAPPED)
|
||||
{
|
||||
*(SHORT*)((this->LocalSharedMemory) + 0xF00) = 0x00;
|
||||
|
||||
|
||||
auto hhook = SetWindowsHookExA(WH_SHELL, (HOOKPROC)GetProcAddress(nt, "RtlGetIntegerAtom"), ddll, ProcessData->ThreadID);
|
||||
ShowWindow(ProcessData->ProcessHwnd, SW_HIDE);
|
||||
Sleep(1);
|
||||
auto result = SendMessage(ProcessData->ProcessHwnd, WM_APPCOMMAND, (uintptr_t)Address + 0xF00, (uintptr_t)Address + 0xF00);
|
||||
|
||||
Sleep(1);
|
||||
auto unhook = UnhookWindowsHookEx(hhook);
|
||||
ShowWindow(ProcessData->ProcessHwnd, SW_SHOW);
|
||||
if (*(SHORT*)((this->LocalSharedMemory) + 0xF00)) {
|
||||
*MemoryOut = (uintptr_t)Address;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
else if (Mbi.State == MEM_COMMIT && Mbi.Protect == PAGE_READWRITE && Mbi.RegionSize == 0x3201000 && Mbi.Type == MEM_MAPPED)
|
||||
{
|
||||
ProcessData->discord_framebuffer = (uintptr_t)Address;
|
||||
}
|
||||
|
||||
Address += Mbi.RegionSize;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
std::uint8_t* CExploit::PatternScan(void* module, const char* signature)
|
||||
{
|
||||
static auto pattern_to_byte = [](const char* pattern)
|
||||
{
|
||||
auto bytes = std::vector<int>{};
|
||||
auto start = const_cast<char*>(pattern);
|
||||
auto end = const_cast<char*>(pattern) + strlen(pattern);
|
||||
|
||||
for (auto current = start; current < end; ++current)
|
||||
{
|
||||
if (*current == '?')
|
||||
{
|
||||
++current;
|
||||
if (*current == '?')
|
||||
++current;
|
||||
bytes.push_back(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes.push_back(strtoul(current, ¤t, 16));
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
};
|
||||
|
||||
auto dosHeader = (PIMAGE_DOS_HEADER)module;
|
||||
auto ntHeaders = (PIMAGE_NT_HEADERS)((std::uint8_t*)module + dosHeader->e_lfanew);
|
||||
|
||||
auto sizeOfImage = ntHeaders->OptionalHeader.SizeOfImage;
|
||||
auto patternBytes = pattern_to_byte(signature);
|
||||
auto scanBytes = reinterpret_cast<std::uint8_t*>(module);
|
||||
|
||||
auto s = patternBytes.size();
|
||||
auto d = patternBytes.data();
|
||||
|
||||
for (auto i = 0ul; i < sizeOfImage - s; ++i)
|
||||
{
|
||||
bool found = true;
|
||||
for (auto j = 0ul; j < s; ++j)
|
||||
{
|
||||
if (scanBytes[i + j] != d[j] && d[j] != -1)
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
return &scanBytes[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CExploit::SetupRW()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool CProcess::Initialize(const wchar_t* WindowName, const wchar_t* ClassName, char* exe_name, HWND target_window)
|
||||
{
|
||||
if (!target_window)
|
||||
{
|
||||
ProcessHwnd = FindWindowW(ClassName, WindowName);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessHwnd = target_window;
|
||||
}
|
||||
this->exe_name = exe_name;
|
||||
if (!ProcessHwnd)
|
||||
return false;
|
||||
ThreadID = GetWindowThreadProcessId(ProcessHwnd, &ProcessID);
|
||||
return ThreadID != 0;
|
||||
}
|
||||
95
exploit.hpp
Normal file
95
exploit.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
#define OBFUSCATE __attribute__((annotate("obfuscate")))
|
||||
|
||||
|
||||
|
||||
#define BAD_READ_VALUE 0xBACABACABACABACA
|
||||
|
||||
class CProcess
|
||||
{
|
||||
public:
|
||||
DWORD ThreadID{};
|
||||
DWORD ProcessID{};
|
||||
HWND ProcessHwnd{};
|
||||
uintptr_t peb{};
|
||||
uintptr_t discord_base{};
|
||||
uintptr_t discord_framebuffer{};
|
||||
|
||||
uintptr_t base{};
|
||||
char* exe_name{};
|
||||
char* discord_path{};
|
||||
uintptr_t pmw_tramp_offset{};
|
||||
uintptr_t pma_tramp_offset{};
|
||||
uintptr_t gmw_tramp_offset{};
|
||||
uintptr_t present_tramp_offset{};
|
||||
uintptr_t spoofcall_offset{};
|
||||
uintptr_t grid_offset{};
|
||||
uintptr_t disable_input_offset{};
|
||||
|
||||
/// @brief Initializes the hwnd and process ID elements of the class
|
||||
/// @param WindowName
|
||||
/// @param ClassName
|
||||
/// @param exe_name
|
||||
/// @return Whether the initialization was successful
|
||||
bool Initialize(const wchar_t* WindowName, const wchar_t* ClassName = nullptr, char* exe_name = (char*)"game.exe", HWND target_window = nullptr);
|
||||
};
|
||||
|
||||
typedef struct ModuleListNode
|
||||
{
|
||||
char* moduleName;
|
||||
uint64_t baseAddress;
|
||||
struct ModuleListNode* next;
|
||||
} ModuleListNode;
|
||||
|
||||
|
||||
class CExploit
|
||||
{
|
||||
public:
|
||||
OBFUSCATE uint64_t ReadU64(uint64_t Address);
|
||||
OBFUSCATE void ReadData(uint64_t Address, BYTE* Data, size_t Size);
|
||||
OBFUSCATE void WriteU64(uint64_t Address, uint64_t Value);
|
||||
OBFUSCATE void WriteData(uint64_t Address, BYTE* Data, size_t Size);
|
||||
OBFUSCATE uint64_t AllocateRX(BYTE* data, size_t size);
|
||||
OBFUSCATE uint64_t MapPEHeader(uint64_t Address);
|
||||
OBFUSCATE void ChangeProtection(uint64_t Address, size_t size, DWORD protection);
|
||||
OBFUSCATE bool Initialize(CProcess* Proc);
|
||||
OBFUSCATE uint64_t get_LocalSharedMemory();
|
||||
OBFUSCATE uint64_t get_RemoteSharedMemory();
|
||||
OBFUSCATE uint64_t get_RemoteBase();
|
||||
private:
|
||||
OBFUSCATE bool FindSharedMemory(HANDLE hProcess, uint64_t* MemoryOut, uint64_t* SharedCountOut, char* exe_name);
|
||||
OBFUSCATE std::uint8_t* PatternScan(void* module, const char* signature);
|
||||
OBFUSCATE void SetupRW();
|
||||
private:
|
||||
CProcess* ProcessData{};
|
||||
|
||||
uint64_t SharedCount{};
|
||||
|
||||
uint64_t LocalSharedMemory{};
|
||||
uint64_t RemoteSharedMemory{};
|
||||
uint64_t RemoteProcessBase{};
|
||||
|
||||
uintptr_t set_protect{};
|
||||
|
||||
uintptr_t mr_data_addr_ptr{};
|
||||
uintptr_t mr_data_size_ptr{};
|
||||
uintptr_t mr_data_addr_orig{};
|
||||
uintptr_t mr_data_size_orig{};
|
||||
uintptr_t set_mrprot{};
|
||||
|
||||
uintptr_t r{};
|
||||
uintptr_t t{};
|
||||
uintptr_t w{};
|
||||
|
||||
uint64_t read_fn{};
|
||||
uint64_t write_fn{};
|
||||
|
||||
HMODULE nt{};
|
||||
HMODULE sh{};
|
||||
HMODULE ddll{};
|
||||
|
||||
};
|
||||
1069
internal-render-hook.cpp
Normal file
1069
internal-render-hook.cpp
Normal file
File diff suppressed because it is too large
Load Diff
232
pe_mapper.cpp
Normal file
232
pe_mapper.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
#include "pe_mapper.hpp"
|
||||
#include <fstream>
|
||||
|
||||
PEMemoryMapper::PEMemoryMapper(const std::string& path)
|
||||
{
|
||||
/* Open file */
|
||||
this->binary_.open(path, std::ios::binary);
|
||||
/* Parse optional header */
|
||||
IMAGE_DOS_HEADER dos_header;
|
||||
binary_.seekg(0);
|
||||
binary_.read(reinterpret_cast<char*>(&dos_header), sizeof(dos_header));
|
||||
IMAGE_NT_HEADERS nt_headers;
|
||||
binary_.seekg(dos_header.e_lfanew);
|
||||
binary_.read(reinterpret_cast<char*>(&nt_headers), sizeof(nt_headers));
|
||||
/* Set base address */
|
||||
base_address_ = nt_headers.OptionalHeader.ImageBase;
|
||||
/* Set memory size */
|
||||
memory_size_ = nt_headers.OptionalHeader.SizeOfImage;
|
||||
|
||||
this->memory_.resize(memory_size_, 0);
|
||||
binary_.seekg(0);
|
||||
|
||||
this->map_sections();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> PEMemoryMapper::read_from_va(uint64_t va, size_t size) const
|
||||
{
|
||||
uint64_t offset = va - this->base_address_;
|
||||
if (offset + size > this->memory_size_)
|
||||
{
|
||||
return { };
|
||||
}
|
||||
return std::vector<uint8_t>(this->memory_.begin() + offset, this->memory_.begin() + offset + size);
|
||||
}
|
||||
|
||||
void PEMemoryMapper::write_to_va(uint64_t va, const std::vector<uint8_t>& data)
|
||||
{
|
||||
uint64_t offset = va - this->base_address_;
|
||||
if (offset + data.size() > this->memory_size_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::copy(data.begin(), data.end(), this->memory_.begin() + offset);
|
||||
}
|
||||
|
||||
bool PEMemoryMapper::is_va_mapped(uint64_t va) const
|
||||
{
|
||||
uint64_t offset = va - this->base_address_;
|
||||
if (offset >= this->memory_.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t* PEMemoryMapper::get_data_pointer(uint64_t va)
|
||||
{
|
||||
uint64_t offset = va - this->base_address_;
|
||||
if (offset >= this->memory_.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return this->memory_.data() + offset;
|
||||
}
|
||||
|
||||
std::vector<uint8_t>& PEMemoryMapper::get_memory()
|
||||
{
|
||||
return this->memory_;
|
||||
}
|
||||
|
||||
uintptr_t PEMemoryMapper::sigscan(const char* pattern)
|
||||
{
|
||||
auto base = this->memory_.data();
|
||||
std::string signature = this->hex_to_bytes(pattern);
|
||||
u_char first = static_cast<u_char>(signature.at(0));
|
||||
u_char* end = (base + memory_size_) - signature.length();
|
||||
for (; base < end; ++base)
|
||||
{
|
||||
if (*base != first)
|
||||
continue;
|
||||
u_char* bytes = base;
|
||||
auto sig = (u_char*)signature.c_str();
|
||||
for (; *sig; ++sig, ++bytes)
|
||||
{
|
||||
if (*sig == '?')
|
||||
continue;
|
||||
if (*bytes != *sig)
|
||||
goto end;
|
||||
}
|
||||
return (uintptr_t)base;
|
||||
end:;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::string PEMemoryMapper::hex_to_bytes(std::string hex)
|
||||
{
|
||||
std::string bytes;
|
||||
std::erase_if(hex, isspace);
|
||||
for (uint32_t i = 0; i < hex.length(); i += 2)
|
||||
{
|
||||
if (static_cast<u_char>(hex[i]) == '?')
|
||||
{
|
||||
bytes += '?';
|
||||
i -= 1;
|
||||
continue;
|
||||
}
|
||||
u_char byte = static_cast<u_char>(std::strtol(hex.substr(i, 2).c_str(), nullptr, 16));
|
||||
bytes += byte;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void PEMemoryMapper::map_sections()
|
||||
{
|
||||
// Read DOS Header
|
||||
IMAGE_DOS_HEADER dos_header = { };
|
||||
if (!read_struct(dos_header, 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (dos_header.e_magic != IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Read NT Headers
|
||||
DWORD pe_offset = dos_header.e_lfanew;
|
||||
DWORD signature = 0;
|
||||
if (!read_struct(signature, pe_offset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (signature != IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Read File Header
|
||||
IMAGE_FILE_HEADER file_header = { };
|
||||
if (!read_struct(file_header, pe_offset + sizeof(DWORD)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Read and verify Optional Header
|
||||
size_t optional_header_offset = pe_offset + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
|
||||
WORD magic = 0;
|
||||
if (!read_struct(magic, optional_header_offset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle PE32 vs PE32+
|
||||
if (magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
{
|
||||
IMAGE_OPTIONAL_HEADER32 optional_header = { };
|
||||
if (!read_struct(optional_header, optional_header_offset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
base_address_ = optional_header.ImageBase;
|
||||
memory_size_ = optional_header.SizeOfImage;
|
||||
}
|
||||
else if (magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
IMAGE_OPTIONAL_HEADER64 optional_header = { };
|
||||
if (!read_struct(optional_header, optional_header_offset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
base_address_ = optional_header.ImageBase;
|
||||
memory_size_ = optional_header.SizeOfImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate memory with proper size checks
|
||||
if (memory_size_ == 0 || memory_size_ > MAX_REASONABLE_SIZE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
memory_.resize(memory_size_, 0);
|
||||
|
||||
// Calculate section headers offset
|
||||
size_t section_headers_offset = pe_offset +
|
||||
sizeof(DWORD) +
|
||||
sizeof(IMAGE_FILE_HEADER) +
|
||||
file_header.SizeOfOptionalHeader;
|
||||
|
||||
// Map each section
|
||||
for (int i = 0; i < file_header.NumberOfSections; i++)
|
||||
{
|
||||
IMAGE_SECTION_HEADER section_header = { };
|
||||
if (!read_struct(section_header, section_headers_offset + (i * sizeof(IMAGE_SECTION_HEADER))))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate section header
|
||||
if (section_header.VirtualAddress >= memory_size_ ||
|
||||
section_header.Misc.VirtualSize > memory_size_ ||
|
||||
section_header.VirtualAddress + section_header.Misc.VirtualSize > memory_size_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate correct sizes
|
||||
size_t virtual_size = section_header.Misc.VirtualSize;
|
||||
if (virtual_size == 0)
|
||||
{
|
||||
virtual_size = section_header.SizeOfRawData;
|
||||
}
|
||||
|
||||
size_t copy_size = min(static_cast<size_t>(section_header.SizeOfRawData), virtual_size);
|
||||
|
||||
// Validate raw data
|
||||
if (section_header.PointerToRawData + copy_size > get_file_size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy section data
|
||||
binary_.seekg(section_header.PointerToRawData);
|
||||
binary_.read(reinterpret_cast<char*>(memory_.data() + section_header.VirtualAddress),
|
||||
copy_size);
|
||||
}
|
||||
}
|
||||
48
pe_mapper.hpp
Normal file
48
pe_mapper.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <Windows.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
class PEMemoryMapper
|
||||
{
|
||||
public:
|
||||
PEMemoryMapper( const std::string& path );
|
||||
|
||||
|
||||
std::vector<uint8_t> read_from_va( uint64_t va, size_t size ) const;
|
||||
void write_to_va( uint64_t va, const std::vector<uint8_t> &data );
|
||||
bool is_va_mapped( uint64_t va ) const;
|
||||
uint8_t* get_data_pointer( uint64_t va );
|
||||
std::vector<uint8_t>& get_memory( );
|
||||
uintptr_t sigscan( const char* pattern );
|
||||
|
||||
template<typename T>
|
||||
bool read_struct(T& structure, size_t offset) {
|
||||
binary_.seekg(offset);
|
||||
binary_.read(reinterpret_cast<char*>(&structure), sizeof(T));
|
||||
return binary_.good();
|
||||
}
|
||||
|
||||
size_t get_file_size() {
|
||||
auto current_pos = binary_.tellg();
|
||||
binary_.seekg(0, std::ios::end);
|
||||
size_t size = binary_.tellg();
|
||||
binary_.seekg(current_pos);
|
||||
return size;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T read( uint64_t va ) const
|
||||
{
|
||||
return *reinterpret_cast<T *>( this->read_from_va( va, sizeof( T ) ).data( ) );
|
||||
}
|
||||
private:
|
||||
static constexpr size_t MAX_REASONABLE_SIZE = 1ULL << 31;
|
||||
|
||||
std::ifstream binary_;
|
||||
uint64_t base_address_;
|
||||
uint64_t memory_size_;
|
||||
std::vector<uint8_t> memory_;
|
||||
std::string hex_to_bytes( std::string hex );
|
||||
void map_sections( );
|
||||
};
|
||||
42
utils.cpp
Normal file
42
utils.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "utils.hpp"
|
||||
#include <string>
|
||||
#include <Windows.h>
|
||||
|
||||
bool utils::DevicePathToDosPath(const char *devicePath, char *dosPath, size_t dosPathSize)
|
||||
{
|
||||
char drive[3] = "A:";
|
||||
char driveLetter[4];
|
||||
char deviceName[MAX_PATH];
|
||||
char path[MAX_PATH];
|
||||
|
||||
for (char letter = 'A'; letter <= 'Z'; ++letter)
|
||||
{
|
||||
drive[0] = letter;
|
||||
if (QueryDosDeviceA(drive, deviceName, MAX_PATH))
|
||||
{
|
||||
size_t len = strlen(deviceName);
|
||||
if (len < MAX_PATH && _strnicmp(devicePath, deviceName, len) == 0)
|
||||
{
|
||||
snprintf(dosPath, dosPathSize, "%c:%s", letter, devicePath + len);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void utils::swap(const char **a, const char **b)
|
||||
{
|
||||
const char *temp = *a;
|
||||
*a = *b;
|
||||
*b = temp;
|
||||
}
|
||||
|
||||
void utils::shuffle(const char **arr, size_t n)
|
||||
{
|
||||
for (size_t i = n - 1; i > 0; --i)
|
||||
{
|
||||
size_t j = rand() % (i + 1);
|
||||
swap(&arr[i], &arr[j]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user