commit 24d0444837137f573c3d3025f89ee58467ba7d4f Author: TALON SCHMELER <20681600+waryas@users.noreply.github.com> Date: Wed Nov 26 01:46:55 2025 +0100 Add files via upload diff --git a/exploit.cpp b/exploit.cpp new file mode 100644 index 0000000..8c0e110 --- /dev/null +++ b/exploit.cpp @@ -0,0 +1,901 @@ +#include "exploit.hpp" +#include "utils.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 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{}; + auto start = const_cast(pattern); + auto end = const_cast(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(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; +} \ No newline at end of file diff --git a/exploit.hpp b/exploit.hpp new file mode 100644 index 0000000..080f169 --- /dev/null +++ b/exploit.hpp @@ -0,0 +1,95 @@ +#pragma once +#include +#include + + +#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{}; + +}; \ No newline at end of file diff --git a/internal-render-hook.cpp b/internal-render-hook.cpp new file mode 100644 index 0000000..0c09799 --- /dev/null +++ b/internal-render-hook.cpp @@ -0,0 +1,1069 @@ +#include "internal-hook.hpp" +#include +#include +#include +#include +#include +#include "hde/mhde_wrapper.hpp" + +#include "ex/exploit.hpp" + + + + +struct FrameContext { + ID3D12CommandAllocator* allocator = nullptr; + D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle{}; + ID3D12Resource* backbuffer = nullptr; +}; + +struct Vertex { float x, y, z, u, v; }; + +struct original_prologue { + uint64_t len; + uint8_t bytes[32]; +}; + +struct present_ipc +{ + volatile bool lock = false; + volatile bool active = false; + volatile uint64_t func = 0; + volatile uint64_t arg[8]{}; + IDXGISwapChain* swapchain = 0; + ID3D12CommandQueue* queue = 0; + volatile uint64_t spoofhelper = 0; + volatile uint64_t rbx = 0; + volatile uint64_t r14 = 0; + volatile uint64_t result = 0; + volatile bool virtualfunc = false; + volatile uint16_t index = false; + volatile uint64_t rdx = 0; + volatile uint64_t r8 = 0; + volatile uint64_t prologue16b = 0; + original_prologue orig_prologue{}; +}; +struct SyncBackEntry { + void* dst; + size_t size; + size_t offset; +}; + + + + +template +struct function_traits; + +template +struct function_traits { + using return_type = R; + using argument_types = std::tuple; +}; + +template +struct function_traits { + using return_type = R; + using argument_types = std::tuple; +}; + +template +struct function_traits { + using return_type = R; + using argument_types = std::tuple; +}; + +present_ipc* p_ipc = 0; + +template +constexpr bool tuple_convertible() { + if constexpr (sizeof...(Args) != std::tuple_size_v) { + return false; + } + else { + return ([](std::index_sequence) { + return (std::is_convertible_v> && ...); + })(std::make_index_sequence>{}); + } +} + + +template +constexpr uint64_t to_u64(T&& value) { + if constexpr (std::is_integral_v> && sizeof(T) <= sizeof(uint64_t)) { + return static_cast(value); + } + else { + return reinterpret_cast(value); + } +} + +static inline void set_original_prologue(const uint8_t* p) +{ + static std::unordered_map cache; + + if (auto it = cache.find(p); it != cache.end()) + { + p_ipc->func += it->second.len; + p_ipc->orig_prologue = it->second; + + return; + } + + cache[p] = {}; + CMHDE mhde; + auto len = mhde.Disassemble(p); + while (len < 14) + len += mhde.Disassemble(p + len); + + cache[p].len = len; + memcpy(cache[p].bytes, p, len); + *(uint32_t*)&cache[p].bytes[len] = 0x862ff41; + + + p_ipc->func += len; + p_ipc->orig_prologue = cache[p]; + + return; +} + +// Displacement finder with caching +static inline uint64_t find_valid_disp_cached(const uint8_t* p) +{ + static std::unordered_map cache; + + if (auto it = cache.find(p); it != cache.end()) + { + return it->second; + } + + for (size_t i = 0; i < 30; ++i) + { + //mov rax,QWORD PTR [rax+?32] + if (i + 6 < 30 && p[i] == 0x48 && p[i + 1] == 0x8B && p[i + 2] == 0x80) + { + int32_t disp = *reinterpret_cast(p + i + 3); + if (disp > 0 && disp % 8 == 0) + { + cache[p] = static_cast(disp); + return disp; + } + } + //mov rax,QWORD PTR [rax+?] + if (i + 3 < 30 && p[i] == 0x48 && p[i + 1] == 0x8B && p[i + 2] == 0x40) + { + int8_t disp = static_cast(p[i + 3]); + if (disp > 0 && disp % 8 == 0) + { + cache[p] = static_cast(disp); + return disp; + } + } + //jmp qword ptr [rax+?] + if (i + 3 < 30 && p[i] == 0xFF && p[i + 1] == 0x60) + { + int8_t disp = static_cast(p[i + 2]); + if (disp > 0 && disp % 8 == 0) + { + cache[p] = static_cast(disp); + return disp; + } + } + //jmp qword ptr [rax+?32] + if (i + 6 < 30 && p[i] == 0xFF && p[i + 1] == 0xA0) + { + int32_t disp = *reinterpret_cast(&p[i + 2]); + if (disp > 0 && disp % 8 == 0) + { + cache[p] = static_cast(disp); + return disp; + } + } + } + + cache[p] = 0; + return 0; +} + + +template +uint64_t ipc_call(CExploit& ex, Func fn, Args&&... args) +{ + + static_assert(sizeof...(Args) <= 8, "Too many arguments"); + + using Return = typename function_traits::return_type; + constexpr bool is_struct_return = + std::is_class_v && + std::is_trivially_copyable_v && + !std::is_void_v && + !std::is_integral_v; + + // If a struct is returned, enforce that the last argument is Return* + if constexpr (is_struct_return) { + static_assert(sizeof...(Args) >= 1, "Missing struct return output pointer"); + using LastArg = std::tuple_element_t...>>; + static_assert(std::is_pointer_v, "Last argument must be a pointer to struct return type"); + static_assert(std::is_same_v>, Return>, + "Last argument must be a pointer to the return type struct"); + } + + static std::vector sync_entries; + sync_entries.clear(); + size_t cursor = 0; + + if constexpr (std::is_member_function_pointer_v) { + using expected_args = typename function_traits::argument_types; + if constexpr (!is_struct_return) { + static_assert(tuple_convertible(), + "ipc_call: arguments not convertible to member function signature"); + } + static_assert(sizeof(fn) <= sizeof(uint64_t), "Member function pointer too large"); + + p_ipc->func = 0; + p_ipc->virtualfunc = 1; + auto b = *reinterpret_cast(&fn); + p_ipc->index = find_valid_disp_cached(reinterpret_cast(b)); + } + else if constexpr (std::is_pointer_v) { + using expected_args = typename function_traits::argument_types; + static_assert(tuple_convertible(), + "ipc_call: arguments not convertible to function signature"); + + p_ipc->virtualfunc = 0; + p_ipc->func = std::bit_cast(fn); + } + else { + static_assert([] { return false; }(), "Unsupported function type in ipc_call"); + } + + uint64_t* dest = const_cast(p_ipc->arg); + size_t i = 0; + + auto process_arg = [&](auto&& arg) { + using T = std::decay_t; + + if constexpr (std::is_pointer_v) { + using Pointee = std::remove_pointer_t; + + if constexpr (std::is_trivially_copyable_v) { + size_t size = 0; + if constexpr (std::is_same_v || std::is_same_v) { + size = std::strlen(arg) + 1; + } + else if constexpr (std::is_same_v || std::is_same_v) { + size = (std::wcslen(arg) + 1) * sizeof(wchar_t); + } + else if constexpr (std::is_same_v) { + size = sizeof(Vertex) * 4; + } + else if constexpr (std::is_same_v) { + size = sizeof(D3D11_INPUT_ELEMENT_DESC) * 2; + } + else { + size = sizeof(Pointee); + } + + + uint8_t* local_base = reinterpret_cast(ex.get_LocalSharedMemory()) + PAD_DATA + cursor; + uint8_t* remote_base = reinterpret_cast(ex.get_RemoteSharedMemory()) + PAD_DATA + cursor; + + std::memcpy(local_base, arg, size); + dest[i++] = reinterpret_cast(remote_base); + + if constexpr (!std::is_const_v) { + sync_entries.push_back(SyncBackEntry{ + const_cast(static_cast(arg)), size, cursor + }); + } + + cursor += size; + } + else { + dest[i++] = reinterpret_cast(arg); // non-trivial, pass raw pointer + } + } + else if constexpr (std::is_lvalue_reference_v && std::is_trivially_copyable_v) { + size_t size = sizeof(T); + + if constexpr (sizeof(T) <= 8) { + auto dst = &dest[i++]; + std::memset(dst, 0, 8); + std::memcpy(dst, &arg, 8); + } + else { + uint8_t* local_base = reinterpret_cast(ex.get_LocalSharedMemory()) + PAD_DATA + cursor; + uint8_t* remote_base = reinterpret_cast(ex.get_RemoteSharedMemory()) + PAD_DATA + cursor; + + std::memcpy(local_base, &arg, size); + dest[i++] = reinterpret_cast(remote_base); + + cursor += size; + } + } + else { + if constexpr (sizeof(std::forward(arg)) <= 8) { + auto dst = &dest[i++]; + std::memset(dst, 0, 8); + std::memcpy(dst, &arg, 8); + } + else { + dest[i++] = (uint64_t)(std::forward(arg)); + } + } + }; + + (process_arg(std::forward(args)), ...); + p_ipc->prologue16b = 0; + p_ipc->active = 1; + + while (!p_ipc->prologue16b) + { + _mm_pause(); + } + + if (*(uint16_t*)(p_ipc->func) != p_ipc->prologue16b) + { + printf("Hook detected at 0x%llx, jitting it\n", p_ipc->func); + set_original_prologue((uint8_t*)p_ipc->func); + p_ipc->prologue16b = 0xB00B; + } + else { + p_ipc->prologue16b = 0xDEAD; + } + + + while (p_ipc->active) { + _mm_pause(); + } + for (const auto& entry : sync_entries) { + void* src = reinterpret_cast(ex.get_LocalSharedMemory()) + PAD_DATA + entry.offset; + std::memcpy(entry.dst, src, entry.size); + } + + return p_ipc->result; +} + + + +uint32_t GetQueueIndexFromSwapchain() +{ + WNDCLASSW wc = {}; + wc.lpfnWndProc = DefWindowProcW; + wc.hInstance = GetModuleHandleW(nullptr); + wc.lpszClassName = L"_2"; + RegisterClassW(&wc); + HWND hwnd = CreateWindowW(wc.lpszClassName, L"_2", WS_OVERLAPPEDWINDOW, 0, 0, 1, 1, nullptr, nullptr, nullptr, nullptr); + + DXGI_SWAP_CHAIN_DESC1 sd = {}; + sd.Width = 1; + sd.Height = 1; + sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.BufferCount = 2; + sd.SampleDesc.Count = 1; + sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + + IDXGIFactory4* factory = nullptr; + CreateDXGIFactory1(IID_PPV_ARGS(&factory)); + + ID3D12Device* device = nullptr; + D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device)); + + D3D12_COMMAND_QUEUE_DESC cqDesc = {}; + ID3D12CommandQueue* queue = nullptr; + device->CreateCommandQueue(&cqDesc, IID_PPV_ARGS(&queue)); + + + IDXGISwapChain1* swapChain1 = nullptr; + factory->CreateSwapChainForHwnd(queue, hwnd, &sd, nullptr, nullptr, &swapChain1); + + IDXGISwapChain3* swapChain = nullptr; + swapChain1->QueryInterface(IID_PPV_ARGS(&swapChain)); + + + uint64_t val = (uint64_t)queue; + uint64_t base = (uint64_t)swapChain; + uint32_t index = 0; + for (uint32_t i = 0; i < 0x40; ++i) + { + if (*(uint64_t*)(base + 8 * i) == val) + { + index = i; + break; + } + } + + swapChain->Release(); + swapChain1->Release(); + queue->Release(); + device->Release(); + factory->Release(); + DestroyWindow(hwnd); + UnregisterClassW(wc.lpszClassName, wc.hInstance); + + return index; +} + + + + + + + +void __attribute__((noinline)) shellcode_present_hook(void) { + + MAGIC_ASM + + __asm { + movabs r10, 0xdeadbeefdeadbeef + mov QWORD PTR[r10 + 0x50], rcx + mov QWORD PTR[r10 + 0x88], rdx + mov QWORD PTR[r10 + 0x90], r8 +#ifdef DIRECTX12 + add rcx, 0x138 + mov rcx, QWORD PTR[rcx] + mov QWORD PTR[r10 + 0x58], rcx +#endif + begin_lock : + mov al, BYTE PTR[r10] + cmp al, 0x1 + jne short fin + mov al, BYTE PTR[r10 + 0x1] + cmp al, 0x1 + jne short begin_lock + sub rsp, 0x48 + mov QWORD PTR[r10 + 0x68], rbx + mov QWORD PTR[r10 + 0x70], r14 + mov rcx, QWORD PTR[r10 + 0x10] + mov rdx, QWORD PTR[r10 + 0x18] + mov r8, QWORD PTR[r10 + 0x20] + mov r9, QWORD PTR[r10 + 0x28] + mov r11, QWORD PTR[r10 + 0x30] + mov QWORD PTR[rsp + 0x20], r11 + mov r11, QWORD PTR[r10 + 0x38] + mov QWORD PTR[rsp + 0x28], r11 + mov r11, QWORD PTR[r10 + 0x40] + mov QWORD PTR[rsp + 0x30], r11 + mov r11, QWORD PTR[r10 + 0x48] + mov QWORD PTR[rsp + 0x38], r11 + cmp BYTE PTR[r10 + 0x80], 0x1 + je short vcall + mov rbx, QWORD PTR[r10 + 0x8] + mov r11w, WORD PTR[rbx] + mov WORD PTR[r10 + 0x98], r11w + wait : + mov r11w, WORD PTR[r10 + 0x98] + cmp r11w, 0xb00b + je short jit + cmp r11w, 0xdead + jne short wait + jmp short execute + jit : + lea rbx, [rip + jit_space] + vmovups ymm0, YMMWORD PTR[r10 + 0xa8] + vmovups YMMWORD PTR[rbx], ymm0 + vzeroupper + execute : + lea r14, [rip + ret_addr] + jmp QWORD PTR[r10 + 0x60] + vcall : + xor r11, r11 + mov r11w, WORD PTR[r10 + 0x82] + mov rbx, QWORD PTR[rcx] + mov rbx, QWORD PTR[rbx + r11 * 1] + mov QWORD PTR[r10 + 0x8], rbx + mov r11w, WORD PTR[rbx] + mov WORD PTR[r10 + 0x98], r11w + jmp short wait + ret_addr : + pop rbx + movabs r10, 0xdeadbeefdeadbeef + mov rbx, QWORD PTR[r10 + 0x68] + mov r14, QWORD PTR[r10 + 0x70] + mov QWORD PTR[r10 + 0x78], rax + mov BYTE PTR[r10 + 0x1], 0x0 + add rsp, 0x48 + jmp short begin_lock + fin : + mov rcx, QWORD PTR [r10 + 0x50] + mov rdx, QWORD PTR [r10 + 0x88] + mov r8, QWORD PTR [r10 + 0x90] + .byte 0xE9 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + jit_space : + } + + MAGIC_ASM + MAGIC_ASM +} + + + +size_t install_hook_present(CProcess& process, CExploit& exploit, int offset) { + + p_ipc = (present_ipc*)(exploit.get_LocalSharedMemory() + PAD_PRESENT_IPC); + memset(p_ipc, 0, sizeof(*p_ipc)); + + auto shell = get_shell(&shellcode_present_hook); + shellcode obfuscated_shellcode{}; + + obfuscated_shellcode.code = prepend_junk_ops(shell.code, shell.len, (std::rand() % 10) + 7, &obfuscated_shellcode.len); + +#ifdef DIRECTX12 + auto index = GetQueueIndexFromSwapchain(); + *(uint32_t*)(&obfuscated_shellcode.code[0x1c + 3 + (obfuscated_shellcode.len - shell.len)]) = index * 8; +#endif + + for (size_t i = 0; i <= obfuscated_shellcode.len - 8; ) { + if (*(uint64_t*)(obfuscated_shellcode.code + i) == 0xdeadbeefdeadbeef) { + *(uint64_t*)(obfuscated_shellcode.code + i) = exploit.get_RemoteSharedMemory() + PAD_PRESENT_IPC; + i += 8; + } + else + ++i; + } + + uintptr_t dh64_present = exploit.ReadU64(process.discord_base + process.present_tramp_offset); + + uintptr_t dh64_rwx = dh64_present & 0xFFFFFFFFFFFFF000; + + uint32_t distance_to_present_tramp = dh64_present - (dh64_rwx + offset + obfuscated_shellcode.len); + + if (distance_to_present_tramp < 0x10000) { + memcpy(obfuscated_shellcode.code + obfuscated_shellcode.len - 4, &distance_to_present_tramp, sizeof(uint32_t)); + + exploit.WriteData(dh64_rwx + offset, obfuscated_shellcode.code, obfuscated_shellcode.len); + exploit.WriteU64(process.discord_base + process.present_tramp_offset, dh64_rwx + offset); + } + while (!p_ipc->swapchain) { + _mm_pause(); + } + p_ipc->spoofhelper = process.discord_base + process.spoofcall_offset; + return obfuscated_shellcode.len; +} + +#include +#pragma comment(lib, "d3dcompiler.lib") + +#define BEGIN(id) \ + LARGE_INTEGER _##id##_start, _##id##_freq; \ + QueryPerformanceFrequency(&_##id##_freq); \ + QueryPerformanceCounter(&_##id##_start); + +#define END(id) \ + LARGE_INTEGER _##id##_end; \ + QueryPerformanceCounter(&_##id##_end); \ + double _##id##_time = double(_##id##_end.QuadPart - _##id##_start.QuadPart) / double(_##id##_freq.QuadPart); \ + printf(#id " took %.6f ms\n", _##id##_time*1000); + + +void RenderThread(CExploit& exploit,D2DSharedRenderer& renderer, const wchar_t* shared_tex_name, HANDLE begin_event, HANDLE done_event) { + + typedef void (WINAPI* RtlCopyMemory_t)(void* Destination, const void* Source, size_t Length); + RtlCopyMemory_t RtlCopyMemory = (RtlCopyMemory_t)GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlCopyMemory"); + + typedef HRESULT(WINAPI* D3DCreateBlob_t)(SIZE_T Size, ID3DBlob** ppBlob); + D3DCreateBlob_t D3DCreateBlob = (D3DCreateBlob_t)GetProcAddress(LoadLibraryA("d3dcompiler_47.dll"), "D3DCreateBlob"); + + static struct dx12 { + ID3D12Device* device = nullptr; + ID3D12GraphicsCommandList* cmdList = nullptr; + ID3D12RootSignature* rootSig = nullptr; + ID3D12PipelineState* pso = nullptr; + ID3D12DescriptorHeap* srvHeap = nullptr; + ID3D12DescriptorHeap* rtvHeap = nullptr; + ID3D12Resource* sharedTex = nullptr; + HANDLE sharedHandle = nullptr; + ID3D12Resource* vertexBuffer = nullptr; + D3D12_VERTEX_BUFFER_VIEW vertexBufferView = {}; + UINT rtvDescriptorSize = 0; + UINT backbufferCount = 0; + FrameContext* frames = nullptr; + bool initialized = false; + } dx12; + static bool isDx11 = false; + + static struct dx11 { + bool initialized = false; + ID3D11Buffer* vertexBuffer = nullptr; + ID3D11VertexShader* vs = nullptr; + ID3D11PixelShader* ps = nullptr; + ID3D11InputLayout* inputLayout = nullptr; + ID3D11ShaderResourceView* srv = nullptr; + ID3D11SamplerState* sampler = nullptr; + ID3D11BlendState* blend = nullptr; + ID3D11Texture2D* sharedTex = nullptr; + ID3D11Device1* device = nullptr; + ID3D11DeviceContext1* ctx = nullptr; + + } dx11; + + struct D3D11StateBackup { + ID3D11RenderTargetView* rtv = nullptr; + ID3D11BlendState* blend = nullptr; + FLOAT blendFactor[4]{}; + UINT sampleMask = 0; + D3D11_VIEWPORT viewport{}; + UINT numViewports = 1; + ID3D11InputLayout* inputLayout = nullptr; + ID3D11Buffer* vertexBuffer = nullptr; + UINT stride = 0, offset = 0; + D3D11_PRIMITIVE_TOPOLOGY topology{}; + ID3D11VertexShader* vs = nullptr; + ID3D11PixelShader* ps = nullptr; + ID3D11ShaderResourceView* srv = nullptr; + ID3D11SamplerState* sampler = nullptr; + }; + + while (1) + { + WaitForSingleObject(begin_event, INFINITE); + + p_ipc->lock = 1; + + if (!isDx11) { + if (dx12.initialized == false) { + ipc_call(exploit, &IDXGISwapChain::GetDevice, p_ipc->swapchain, __uuidof(ID3D12Device), (void**)&dx12.device); + + + if (!dx12.device) { + isDx11 = true; + p_ipc->lock = 0; + SetEvent(done_event); + Sleep(0); + + continue; + } + DXGI_SWAP_CHAIN_DESC desc = {}; + ipc_call(exploit, &IDXGISwapChain::GetDesc, p_ipc->swapchain, &desc); + dx12.backbufferCount = desc.BufferCount; + dx12.frames = new FrameContext[dx12.backbufferCount]; + ipc_call(exploit, &ID3D12Device::OpenSharedHandleByName, dx12.device, shared_tex_name, GENERIC_ALL, &dx12.sharedHandle); + ipc_call(exploit, &ID3D12Device::OpenSharedHandle, dx12.device, dx12.sharedHandle, __uuidof(**(&dx12.sharedTex)), IID_PPV_ARGS_Helper(&dx12.sharedTex)); + + D3D12_RESOURCE_DESC texDesc{}; + ipc_call(exploit, &ID3D12Resource::GetDesc, dx12.sharedTex, &texDesc); + + + D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; + srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + srvHeapDesc.NumDescriptors = 1; + srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + ipc_call(exploit, &ID3D12Device::CreateDescriptorHeap, dx12.device, &srvHeapDesc, IID_PPV_ARGS(&dx12.srvHeap)); + + + D3D12_CPU_DESCRIPTOR_HANDLE heap{}; + ipc_call(exploit, &ID3D12DescriptorHeap::GetCPUDescriptorHandleForHeapStart, dx12.srvHeap, &heap); + + + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Format = texDesc.Format; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + ipc_call(exploit, &ID3D12Device::CreateShaderResourceView, dx12.device, dx12.sharedTex, &srvDesc, heap); + + D3D12_DESCRIPTOR_HEAP_DESC rtvDesc = {}; + rtvDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtvDesc.NumDescriptors = dx12.backbufferCount; + ipc_call(exploit, &ID3D12Device::CreateDescriptorHeap, dx12.device, &rtvDesc, IID_PPV_ARGS(&dx12.rtvHeap)); + dx12.rtvDescriptorSize = ipc_call(exploit, &ID3D12Device::GetDescriptorHandleIncrementSize, dx12.device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + D3D12_CPU_DESCRIPTOR_HANDLE rtvStart{}; + + ipc_call(exploit, &ID3D12DescriptorHeap::GetCPUDescriptorHandleForHeapStart, dx12.rtvHeap, &rtvStart); + + + for (UINT i = 0; i < dx12.backbufferCount; i++) { + FrameContext& ctx = dx12.frames[i]; + ipc_call(exploit, &ID3D12Device::CreateCommandAllocator, dx12.device, D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&ctx.allocator)); + ipc_call(exploit, &IDXGISwapChain::GetBuffer, p_ipc->swapchain, (uint64_t)i, IID_PPV_ARGS(&ctx.backbuffer)); + ctx.rtvHandle = rtvStart; + ipc_call(exploit, &ID3D12Device::CreateRenderTargetView, dx12.device, ctx.backbuffer, nullptr, ctx.rtvHandle); + rtvStart.ptr += dx12.rtvDescriptorSize; + } + + + Vertex quad[] = { + { -1.0f, -1.0f, 0.0f, 0.0f, 1.0f }, + { -1.0f, 1.0f, 0.0f, 0.0f, 0.0f }, + { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f }, + }; + + D3D12_HEAP_PROPERTIES heapProps = { D3D12_HEAP_TYPE_UPLOAD }; + D3D12_RESOURCE_DESC resDesc = {}; + resDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + resDesc.Width = sizeof(quad); + resDesc.Height = 1; + resDesc.DepthOrArraySize = 1; + resDesc.MipLevels = 1; + resDesc.SampleDesc.Count = 1; + resDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + ipc_call(exploit, &ID3D12Device::CreateCommittedResource, dx12.device, &heapProps, D3D12_HEAP_FLAG_NONE, &resDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&dx12.vertexBuffer)); + + void* p = 0; + ipc_call(exploit, &ID3D12Resource::Map, dx12.vertexBuffer, 0, nullptr, &p); + ipc_call(exploit, RtlCopyMemory, p, quad, sizeof(quad)); + ipc_call(exploit, &ID3D12Resource::Unmap, dx12.vertexBuffer, 0, nullptr); + memset((void*)&p_ipc->arg[0], 0, sizeof(p_ipc->arg)); + dx12.vertexBufferView.BufferLocation = ipc_call(exploit, &ID3D12Resource::GetGPUVirtualAddress, dx12.vertexBuffer); + + dx12.vertexBufferView.StrideInBytes = sizeof(Vertex); + dx12.vertexBufferView.SizeInBytes = sizeof(quad); + + const char* g_vsSrc = + "struct VS_INPUT { float4 pos : POSITION; float2 tex : TEXCOORD0; };" + "struct VS_OUTPUT { float4 pos : SV_POSITION; float2 tex : TEXCOORD0; };" + "VS_OUTPUT main(VS_INPUT input) {" + " VS_OUTPUT output;" + " output.pos = input.pos;" + " output.tex = input.tex;" + " return output;" + "}"; + + const char* g_psSrc = + "Texture2D tex0 : register(t0);" + "SamplerState samp0 : register(s0);" + "struct VS_OUTPUT { float4 pos : SV_POSITION; float2 tex : TEXCOORD0; };" + "float4 main(VS_OUTPUT input) : SV_Target {" + "return tex0.Sample(samp0, input.tex);" + "}"; + + ID3DBlob* local_vs = nullptr, * local_ps = nullptr, * local_sig = nullptr; + ID3DBlob* vs = nullptr, * ps = nullptr, * sig = nullptr; + D3DCompile(g_vsSrc, strlen(g_vsSrc), nullptr, nullptr, nullptr, "main", "vs_5_0", 0, 0, &local_vs, nullptr); + D3DCompile(g_psSrc, strlen(g_psSrc), nullptr, nullptr, nullptr, "main", "ps_5_0", 0, 0, &local_ps, nullptr); + + + ipc_call(exploit, D3DCreateBlob, local_vs->GetBufferSize(), &vs); + memcpy((void*)(exploit.get_LocalSharedMemory() + PAD_DATA), local_vs->GetBufferPointer(), local_vs->GetBufferSize()); + ipc_call(exploit, RtlCopyMemory, (void*)ipc_call(exploit, &ID3DBlob::GetBufferPointer, vs), (void*)(exploit.get_RemoteSharedMemory() + PAD_DATA), local_vs->GetBufferSize()); + + ipc_call(exploit, D3DCreateBlob, local_ps->GetBufferSize(), &ps); + memcpy((void*)(exploit.get_LocalSharedMemory() + PAD_DATA), local_ps->GetBufferPointer(), local_ps->GetBufferSize()); + ipc_call(exploit, RtlCopyMemory, (void*)ipc_call(exploit, &ID3DBlob::GetBufferPointer, ps), (void*)(exploit.get_RemoteSharedMemory() + PAD_DATA), local_ps->GetBufferSize()); + + D3D12_DESCRIPTOR_RANGE range = { D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0 }; + D3D12_ROOT_PARAMETER param = {}; + param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + param.DescriptorTable.NumDescriptorRanges = 1; + param.DescriptorTable.pDescriptorRanges = ⦥ + param.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + D3D12_STATIC_SAMPLER_DESC samp = {}; + samp.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + samp.AddressU = samp.AddressV = samp.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samp.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + samp.ShaderRegister = 0; + + D3D12_ROOT_SIGNATURE_DESC sigDesc = {}; + sigDesc.NumParameters = 1; + sigDesc.pParameters = ¶m; + sigDesc.NumStaticSamplers = 1; + sigDesc.pStaticSamplers = &samp; + sigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + D3D12SerializeRootSignature(&sigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &local_sig, nullptr); + + ipc_call(exploit, D3DCreateBlob, local_sig->GetBufferSize(), &sig); + memcpy((void*)(exploit.get_LocalSharedMemory() + PAD_DATA), local_sig->GetBufferPointer(), local_sig->GetBufferSize()); + void* remote_sig_ptr = (void*)ipc_call(exploit, &ID3DBlob::GetBufferPointer, sig); + ipc_call(exploit, RtlCopyMemory, remote_sig_ptr, (void*)(exploit.get_RemoteSharedMemory() + PAD_DATA), local_sig->GetBufferSize()); + ipc_call(exploit, &ID3D12Device::CreateRootSignature, dx12.device, (uint64_t)0, remote_sig_ptr, local_sig->GetBufferSize(), IID_PPV_ARGS(&dx12.rootSig)); + + strcpy((char*)(exploit.get_LocalSharedMemory() + PAD_DATA + 0x300), "POSITION"); + strcpy((char*)(exploit.get_LocalSharedMemory() + PAD_DATA + 0x300 + 9), "TEXCOORD"); + + D3D12_INPUT_ELEMENT_DESC layout[] = { + { (char*)(exploit.get_RemoteSharedMemory() + PAD_DATA + 0x300), 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { (char*)(exploit.get_RemoteSharedMemory() + PAD_DATA + 0x309), 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + memcpy((void*)(exploit.get_LocalSharedMemory() + PAD_DATA + 0x312), layout, sizeof(layout)); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = dx12.rootSig; + psoDesc.VS = { (void*)ipc_call(exploit, &ID3DBlob::GetBufferPointer, vs), local_vs->GetBufferSize() }; + psoDesc.PS = { (void*)ipc_call(exploit, &ID3DBlob::GetBufferPointer, ps), local_ps->GetBufferSize() }; + + psoDesc.BlendState = {}; + psoDesc.BlendState.AlphaToCoverageEnable = true; + //psoDesc.BlendState.IndependentBlendEnable = true; + psoDesc.BlendState.RenderTarget[0].BlendEnable = true; + + psoDesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; + psoDesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; + psoDesc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; + psoDesc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; + psoDesc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; + psoDesc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; + psoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + psoDesc.SampleMask = UINT_MAX; + + { + D3D12_RASTERIZER_DESC& desc = psoDesc.RasterizerState; + desc.FillMode = D3D12_FILL_MODE_SOLID; + desc.CullMode = D3D12_CULL_MODE_NONE; + desc.FrontCounterClockwise = FALSE; + desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + desc.DepthClipEnable = true; + desc.MultisampleEnable = FALSE; + desc.AntialiasedLineEnable = FALSE; + desc.ForcedSampleCount = 0; + desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + } + { + D3D12_DEPTH_STENCIL_DESC& desc = psoDesc.DepthStencilState; + desc.DepthEnable = false; + desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + desc.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; + desc.StencilEnable = false; + desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP; + desc.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; + desc.BackFace = desc.FrontFace; + + } + psoDesc.InputLayout = { (D3D12_INPUT_ELEMENT_DESC*)(exploit.get_RemoteSharedMemory() + PAD_DATA + 0x312), _countof(layout) }; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = DXGI_FORMAT_B8G8R8A8_UNORM; + psoDesc.SampleDesc.Count = 1; + psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + ipc_call(exploit, &ID3D12Device::CreateGraphicsPipelineState, dx12.device, &psoDesc, IID_PPV_ARGS(&dx12.pso)); + ipc_call(exploit, &ID3DBlob::Release, vs); + ipc_call(exploit, &ID3DBlob::Release, ps); + ipc_call(exploit, &ID3DBlob::Release, sig); + local_vs->Release(); local_ps->Release(); local_sig->Release(); + ipc_call(exploit, &ID3D12Device::CreateCommandList, dx12.device, (uint64_t)0, D3D12_COMMAND_LIST_TYPE_DIRECT, dx12.frames[0].allocator, nullptr, IID_PPV_ARGS(&dx12.cmdList)); + ipc_call(exploit, &ID3D12GraphicsCommandList::Close, dx12.cmdList); + + dx12.initialized = true; + + + } + + UINT frameIdx = ipc_call(exploit, &IDXGISwapChain3::GetCurrentBackBufferIndex, (IDXGISwapChain3*)p_ipc->swapchain); + + + FrameContext& ctx = dx12.frames[frameIdx]; + ipc_call(exploit, &ID3D12CommandAllocator::Reset, ctx.allocator); + ipc_call(exploit, &ID3D12GraphicsCommandList::Reset, dx12.cmdList, ctx.allocator, dx12.pso); + + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = ctx.backbuffer; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + ipc_call(exploit, &ID3D12GraphicsCommandList::ResourceBarrier, dx12.cmdList, (uint64_t)1, &barrier); + ipc_call(exploit, &ID3D12GraphicsCommandList::OMSetRenderTargets, dx12.cmdList, (uint64_t)1, &ctx.rtvHandle, (uint64_t)0, nullptr); + + DXGI_SWAP_CHAIN_DESC desc = {}; + ipc_call(exploit, &IDXGISwapChain::GetDesc, p_ipc->swapchain, &desc); + D3D12_VIEWPORT viewport = { 0, 0, (float)desc.BufferDesc.Width, (float)desc.BufferDesc.Height, 0.0f, 1.0f }; + D3D12_RECT scissor = { 0, 0, (LONG)desc.BufferDesc.Width, (LONG)desc.BufferDesc.Height }; + ipc_call(exploit, &ID3D12GraphicsCommandList::RSSetViewports, dx12.cmdList, (uint64_t)1, &viewport); + ipc_call(exploit, &ID3D12GraphicsCommandList::RSSetScissorRects, dx12.cmdList, (uint64_t)1, &scissor); + + + ipc_call(exploit, &ID3D12GraphicsCommandList::SetGraphicsRootSignature, dx12.cmdList, dx12.rootSig); + ipc_call(exploit, &ID3D12GraphicsCommandList::SetPipelineState, dx12.cmdList, dx12.pso); + ipc_call(exploit, &ID3D12GraphicsCommandList::SetDescriptorHeaps, dx12.cmdList, (uint64_t)1, &dx12.srvHeap); + ipc_call(exploit, &ID3D12GraphicsCommandList::IASetPrimitiveTopology, dx12.cmdList, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + ipc_call(exploit, &ID3D12GraphicsCommandList::IASetVertexBuffers, dx12.cmdList, (uint64_t)0, (uint64_t)1, &dx12.vertexBufferView); + D3D12_GPU_DESCRIPTOR_HANDLE gpuheap{}; + ipc_call(exploit, &ID3D12DescriptorHeap::GetGPUDescriptorHandleForHeapStart, dx12.srvHeap, &gpuheap); + ipc_call(exploit, &ID3D12GraphicsCommandList::SetGraphicsRootDescriptorTable, dx12.cmdList, (uint64_t)0, gpuheap); + ipc_call(exploit, &ID3D12GraphicsCommandList::DrawInstanced, dx12.cmdList, (uint64_t)4, (uint64_t)1, (uint64_t)0, (uint64_t)0); + + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + ipc_call(exploit, &ID3D12GraphicsCommandList::ResourceBarrier, dx12.cmdList, (uint64_t)1, &barrier); + ipc_call(exploit, &ID3D12GraphicsCommandList::Close, dx12.cmdList); + ipc_call(exploit, &ID3D12CommandQueue::ExecuteCommandLists, p_ipc->queue, (uint64_t)1, (ID3D12CommandList* const*)&dx12.cmdList); + } + else { + if (dx11.initialized == false) { + + ipc_call(exploit, &IDXGISwapChain::GetDevice, p_ipc->swapchain, __uuidof(ID3D11Device1), (void**)&dx11.device); + if (!dx11.device) { + MessageBoxA(nullptr, "This is neither DX12 or DX11 game?", "Error", MB_OK); + } + + + // Quad vertices + Vertex quad[] = { + { -1.0f, -1.0f, 0.0f, 0.0f, 1.0f }, + { -1.0f, 1.0f, 0.0f, 0.0f, 0.0f }, + { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f }, + }; + + D3D11_BUFFER_DESC vbDesc = {}; + vbDesc.Usage = D3D11_USAGE_IMMUTABLE; + vbDesc.ByteWidth = sizeof(quad); + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + memcpy((void*)(exploit.get_LocalSharedMemory() + PAD_DATA + 0x200), quad, sizeof(quad)); + D3D11_SUBRESOURCE_DATA vbData = { (void*)(exploit.get_RemoteSharedMemory() + PAD_DATA + 0x200) }; + ipc_call(exploit, &ID3D11Device1::CreateBuffer, dx11.device, &vbDesc, &vbData, &dx11.vertexBuffer); + + + const char* vsSrc = + "struct VS_INPUT { float4 pos : POSITION; float2 tex : TEXCOORD0; };" + "struct VS_OUTPUT { float4 pos : SV_POSITION; float2 tex : TEXCOORD0; };" + "VS_OUTPUT main(VS_INPUT input) {" + " VS_OUTPUT output;" + " output.pos = input.pos;" + " output.tex = input.tex;" + " return output;" + "}"; + + // Pixel shader sampling from tex0 + const char* psSrc = + "Texture2D tex0 : register(t0);" + "SamplerState samp0 : register(s0);" + "struct VS_OUTPUT { float4 pos : SV_POSITION; float2 tex : TEXCOORD0; };" + "float4 main(VS_OUTPUT input) : SV_Target {" + " return tex0.Sample(samp0, input.tex);" + "}"; + + ID3DBlob* local_vs = nullptr, * local_ps = nullptr; + ID3DBlob* vs = nullptr, * ps = nullptr; + D3DCompile(vsSrc, strlen(vsSrc), nullptr, nullptr, nullptr, "main", "vs_5_0", 0, 0, &local_vs, nullptr); + D3DCompile(psSrc, strlen(psSrc), nullptr, nullptr, nullptr, "main", "ps_5_0", 0, 0, &local_ps, nullptr); + + ipc_call(exploit, D3DCreateBlob, local_vs->GetBufferSize(), &vs); + memcpy((void*)(exploit.get_LocalSharedMemory() + PAD_DATA), local_vs->GetBufferPointer(), local_vs->GetBufferSize()); + ipc_call(exploit, RtlCopyMemory, (void*)ipc_call(exploit, &ID3DBlob::GetBufferPointer, vs), (void*)(exploit.get_RemoteSharedMemory() + PAD_DATA), local_vs->GetBufferSize()); + + ipc_call(exploit, D3DCreateBlob, local_ps->GetBufferSize(), &ps); + memcpy((void*)(exploit.get_LocalSharedMemory() + PAD_DATA), local_ps->GetBufferPointer(), local_ps->GetBufferSize()); + ipc_call(exploit, RtlCopyMemory, (void*)ipc_call(exploit, &ID3DBlob::GetBufferPointer, ps), (void*)(exploit.get_RemoteSharedMemory() + PAD_DATA), local_ps->GetBufferSize()); + + strcpy((char*)(exploit.get_LocalSharedMemory() + PAD_DATA + 0x300), "POSITION"); + strcpy((char*)(exploit.get_LocalSharedMemory() + PAD_DATA + 0x300 + 9), "TEXCOORD"); + + D3D11_INPUT_ELEMENT_DESC layout[] = { + { (char*)(exploit.get_RemoteSharedMemory() + PAD_DATA + 0x300), 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { (char*)(exploit.get_RemoteSharedMemory() + PAD_DATA + 0x309), 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + memcpy((void*)(exploit.get_LocalSharedMemory() + PAD_DATA + 0x312), layout, sizeof(layout)); + + + + ipc_call(exploit, &ID3D11Device1::CreateInputLayout, dx11.device, layout, _countof(layout), (void*)ipc_call(exploit, &ID3DBlob::GetBufferPointer, vs), ipc_call(exploit, &ID3DBlob::GetBufferSize, vs), &dx11.inputLayout); + ipc_call(exploit, &ID3D11Device1::CreateVertexShader, dx11.device, (void*)ipc_call(exploit, &ID3DBlob::GetBufferPointer, vs), ipc_call(exploit, &ID3DBlob::GetBufferSize, vs), nullptr, &dx11.vs); + ipc_call(exploit, &ID3D11Device1::CreatePixelShader, dx11.device, (void*)ipc_call(exploit, &ID3DBlob::GetBufferPointer, ps), ipc_call(exploit, &ID3DBlob::GetBufferSize, ps), nullptr, &dx11.ps); + + ipc_call(exploit, &ID3D11Device1::OpenSharedResourceByName, dx11.device, L"Global\\BlueSharedTex", DXGI_SHARED_RESOURCE_READ, __uuidof(ID3D11Texture2D), (void**)&dx11.sharedTex); + local_vs->Release(); + local_ps->Release(); + D3D11_TEXTURE2D_DESC texDesc = {}; + ipc_call(exploit, &ID3D11Texture2D::GetDesc, dx11.sharedTex, &texDesc); + + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Format = texDesc.Format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + + ipc_call(exploit, &ID3D11Device1::CreateShaderResourceView, dx11.device, dx11.sharedTex, &srvDesc, &dx11.srv); + + D3D11_SAMPLER_DESC samp = {}; + samp.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samp.AddressU = samp.AddressV = samp.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + ipc_call(exploit, &ID3D11Device1::CreateSamplerState, dx11.device, &samp, &dx11.sampler); + + // Alpha blending + D3D11_BLEND_DESC b = {}; + b.RenderTarget[0].BlendEnable = TRUE; + b.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; + b.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + b.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + b.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + b.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; + b.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + b.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + ipc_call(exploit, &ID3D11Device1::CreateBlendState, dx11.device, &b, &dx11.blend); + ipc_call(exploit, &ID3D11Device1::GetImmediateContext1, dx11.device, &dx11.ctx); + dx11.initialized = true; + } + D3D11StateBackup s{}; + { + //ipc_call(exploit, &ID3D11DeviceContext1::OMGetRenderTargets, dx11.ctx, 1, &s.rtv, nullptr); + //ipc_call(exploit, &ID3D11DeviceContext1::OMGetBlendState, dx11.ctx, &s.blend, s.blendFactor, &s.sampleMask); + //ipc_call(exploit, &ID3D11DeviceContext1::RSGetViewports, dx11.ctx, &s.numViewports, &s.viewport); + ipc_call(exploit, &ID3D11DeviceContext1::IAGetInputLayout, dx11.ctx, &s.inputLayout); + ipc_call(exploit, &ID3D11DeviceContext1::IAGetVertexBuffers, dx11.ctx, 0, 1, &s.vertexBuffer, &s.stride, &s.offset); + ipc_call(exploit, &ID3D11DeviceContext1::IAGetPrimitiveTopology, dx11.ctx, &s.topology); + //ipc_call(exploit, &ID3D11DeviceContext1::VSGetShader, dx11.ctx, &s.vs, nullptr, nullptr); + //ipc_call(exploit, &ID3D11DeviceContext1::PSGetShader, dx11.ctx, &s.ps, nullptr, nullptr); + //ipc_call(exploit, &ID3D11DeviceContext1::PSGetShaderResources, dx11.ctx, 0, 1, &s.srv); + //ipc_call(exploit, &ID3D11DeviceContext1::PSGetSamplers, dx11.ctx, 0, 1, &s.sampler); + } + + ID3D11Texture2D* backbuffer = nullptr; + ID3D11RenderTargetView* rtv = nullptr; + ipc_call(exploit, &IDXGISwapChain::GetBuffer, p_ipc->swapchain, 0, IID_PPV_ARGS(&backbuffer)); + ipc_call(exploit, &ID3D11Device1::CreateRenderTargetView, dx11.device, backbuffer, nullptr, &rtv); + ipc_call(exploit, &ID3D11Texture2D::Release, backbuffer); + + float blendFactor[4] = { 0 }; + D3D11_VIEWPORT vp = { 0, 0, (FLOAT)1920, (FLOAT)1080, 0.0f, 1.0f }; + ipc_call(exploit, &ID3D11DeviceContext1::OMSetRenderTargets, dx11.ctx, 1, &rtv, nullptr); + ipc_call(exploit, &ID3D11DeviceContext1::OMSetBlendState, dx11.ctx, dx11.blend, blendFactor, 0xFFFFFFFF); + ipc_call(exploit, &ID3D11DeviceContext1::RSSetViewports, dx11.ctx, 1, &vp); + + UINT stride = sizeof(Vertex), offset = 0; + + ipc_call(exploit, &ID3D11DeviceContext1::IASetInputLayout, dx11.ctx, dx11.inputLayout); + ipc_call(exploit, &ID3D11DeviceContext1::IASetVertexBuffers, dx11.ctx, (uint64_t)0, (uint64_t)1, &dx11.vertexBuffer, &stride, &offset); + ipc_call(exploit, &ID3D11DeviceContext1::IASetPrimitiveTopology, dx11.ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + ipc_call(exploit, &ID3D11DeviceContext1::VSSetShader, dx11.ctx, dx11.vs, nullptr, 0); + ipc_call(exploit, &ID3D11DeviceContext1::PSSetShader, dx11.ctx, dx11.ps, nullptr, 0); + ipc_call(exploit, &ID3D11DeviceContext1::PSSetShaderResources, dx11.ctx, 0, 1, &dx11.srv); + ipc_call(exploit, &ID3D11DeviceContext1::PSSetSamplers, dx11.ctx, 0, 1, &dx11.sampler); + + ipc_call(exploit, &ID3D11DeviceContext1::Draw, dx11.ctx, 4, 0); + ipc_call(exploit, &ID3D11RenderTargetView::Release, rtv); + + { + // ipc_call(exploit, &ID3D11DeviceContext1::OMSetRenderTargets, dx11.ctx, 1, &s.rtv, nullptr); + // ipc_call(exploit, &ID3D11DeviceContext1::OMSetBlendState, dx11.ctx, s.blend, s.blendFactor, s.sampleMask); + // ipc_call(exploit, &ID3D11DeviceContext1::RSSetViewports, dx11.ctx, s.numViewports, &s.viewport); + ipc_call(exploit, &ID3D11DeviceContext1::IASetInputLayout, dx11.ctx, s.inputLayout); + ipc_call(exploit, &ID3D11DeviceContext1::IASetVertexBuffers, dx11.ctx, 0, 1, &s.vertexBuffer, &s.stride, &s.offset); + ipc_call(exploit, &ID3D11DeviceContext1::IASetPrimitiveTopology, dx11.ctx, s.topology); + // ipc_call(exploit, &ID3D11DeviceContext1::VSSetShader, dx11.ctx, s.vs, nullptr, 0); + // ipc_call(exploit, &ID3D11DeviceContext1::PSSetShader, dx11.ctx, s.ps, nullptr, 0); + // ipc_call(exploit, &ID3D11DeviceContext1::PSSetShaderResources, dx11.ctx, 0, 1, &s.srv); + // ipc_call(exploit, &ID3D11DeviceContext1::PSSetSamplers, dx11.ctx, 0, 1, &s.sampler); + } + + { + if (s.rtv) ipc_call(exploit, &ID3D11RenderTargetView::Release, s.rtv); + if (s.blend) ipc_call(exploit, &ID3D11BlendState::Release, s.blend); + if (s.inputLayout) ipc_call(exploit, &ID3D11InputLayout::Release, s.inputLayout); + if (s.vertexBuffer) ipc_call(exploit, &ID3D11Buffer::Release, s.vertexBuffer); + if (s.vs) ipc_call(exploit, &ID3D11VertexShader::Release, s.vs); + if (s.ps) ipc_call(exploit, &ID3D11PixelShader::Release, s.ps); + if (s.srv) ipc_call(exploit, &ID3D11ShaderResourceView::Release, s.srv); + if (s.sampler) ipc_call(exploit, &ID3D11SamplerState::Release, s.sampler); + } + + } + SetEvent(done_event); + p_ipc->lock = 0; + if (GetAsyncKeyState(VK_F1)) + break; + } +} \ No newline at end of file diff --git a/pe_mapper.cpp b/pe_mapper.cpp new file mode 100644 index 0000000..d33e225 --- /dev/null +++ b/pe_mapper.cpp @@ -0,0 +1,232 @@ +#include "pe_mapper.hpp" +#include + +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(&dos_header), sizeof(dos_header)); + IMAGE_NT_HEADERS nt_headers; + binary_.seekg(dos_header.e_lfanew); + binary_.read(reinterpret_cast(&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 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(this->memory_.begin() + offset, this->memory_.begin() + offset + size); +} + +void PEMemoryMapper::write_to_va(uint64_t va, const std::vector& 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& 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(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(hex[i]) == '?') + { + bytes += '?'; + i -= 1; + continue; + } + u_char byte = static_cast(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(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(memory_.data() + section_header.VirtualAddress), + copy_size); + } +} diff --git a/pe_mapper.hpp b/pe_mapper.hpp new file mode 100644 index 0000000..341af67 --- /dev/null +++ b/pe_mapper.hpp @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +class PEMemoryMapper +{ +public: + PEMemoryMapper( const std::string& path ); + + + std::vector read_from_va( uint64_t va, size_t size ) const; + void write_to_va( uint64_t va, const std::vector &data ); + bool is_va_mapped( uint64_t va ) const; + uint8_t* get_data_pointer( uint64_t va ); + std::vector& get_memory( ); + uintptr_t sigscan( const char* pattern ); + + template + bool read_struct(T& structure, size_t offset) { + binary_.seekg(offset); + binary_.read(reinterpret_cast(&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 + T read( uint64_t va ) const + { + return *reinterpret_cast( 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 memory_; + std::string hex_to_bytes( std::string hex ); + void map_sections( ); +}; \ No newline at end of file diff --git a/utils.cpp b/utils.cpp new file mode 100644 index 0000000..b467d17 --- /dev/null +++ b/utils.cpp @@ -0,0 +1,42 @@ +#include "utils.hpp" +#include +#include + +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]); + } +} \ No newline at end of file diff --git a/utils.hpp b/utils.hpp new file mode 100644 index 0000000..faef4fc --- /dev/null +++ b/utils.hpp @@ -0,0 +1,9 @@ +#pragma once +#include + +namespace utils +{ + bool DevicePathToDosPath( const char *devicePath, char *dosPath, size_t dosPathSize ); + void swap( const char** a, const char** b ); + void shuffle( const char** arr, size_t n ); +} \ No newline at end of file