commit 4910159077ddac676d8798fb8b46273d9cbe2ea6 Author: Cracked5pider Date: Sat Jun 18 01:18:28 2022 +0200 init commit diff --git a/Include/Common.h b/Include/Common.h new file mode 100644 index 0000000..ccfdd2e --- /dev/null +++ b/Include/Common.h @@ -0,0 +1,11 @@ +#ifndef EKKO_COMMON_H +#define EKKO_COMMON_H + +#include +#include + +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) +#define NtCurrentThread() ( ( HANDLE ) ( LONG_PTR ) -2 ) +#define NtCurrentProcess() ( ( HANDLE ) ( LONG_PTR ) -1 ) + +#endif diff --git a/Include/Ekko.h b/Include/Ekko.h new file mode 100644 index 0000000..db22336 --- /dev/null +++ b/Include/Ekko.h @@ -0,0 +1,15 @@ +#ifndef EKKO_EKKO_H +#define EKKO_EKKO_H + +#include + +typedef struct +{ + DWORD Length; + DWORD MaximumLength; + PVOID Buffer; +} USTRING ; + +VOID EkkoObf( DWORD SleepTime ); + +#endif diff --git a/README.md b/README.md new file mode 100644 index 0000000..35511b3 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ + +# Ekko + +A small sleep obfuscation technique that uses `CreateTimerQueueTimer` to queue up the ROP chain + +### Credit +- [Austin Hudson (@SecIdiot)](https://twitter.com/ilove2pwn_) https://suspicious.actor/2022/05/05/mdsec-nighthawk-study.html diff --git a/Src/Ekko.c b/Src/Ekko.c new file mode 100644 index 0000000..bb0b708 --- /dev/null +++ b/Src/Ekko.c @@ -0,0 +1,112 @@ +#include +#include + +VOID EkkoObf( DWORD SleepTime ) +{ + CONTEXT CtxThread = { 0 }; + + CONTEXT RopProtRW = { 0 }; + CONTEXT RopMemEnc = { 0 }; + CONTEXT RopDelay = { 0 }; + CONTEXT RopMemDec = { 0 }; + CONTEXT RopProtRX = { 0 }; + CONTEXT RopSetEvt = { 0 }; + + HANDLE hTimerQueue = NULL; + HANDLE hNewTimer = NULL; + HANDLE hEvent = NULL; + PVOID ImageBase = NULL; + DWORD ImageSize = 0; + DWORD OldProtect = 0; + + // Can be randomly generated + CHAR KeyBuf[ 16 ]= { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }; + USTRING Key = { 0 }; + USTRING Img = { 0 }; + + PVOID NtContinue = NULL; + PVOID SysFunc032 = NULL; + + hEvent = CreateEventW( 0, 0, 0, 0 ); + hTimerQueue = CreateTimerQueue(); + + NtContinue = GetProcAddress( GetModuleHandleA( "Ntdll" ), "NtContinue" ); + SysFunc032 = GetProcAddress( LoadLibraryA( "Advapi32" ), "SystemFunction032" ); + + ImageBase = GetModuleHandleA( NULL ); + ImageSize = ( ( PIMAGE_NT_HEADERS ) ( ImageBase + ( ( PIMAGE_DOS_HEADER ) ImageBase )->e_lfanew ) )->OptionalHeader.SizeOfImage; + + Key.Buffer = KeyBuf; + Key.Length = Key.MaximumLength = 16; + + Img.Buffer = ImageBase; + Img.Length = Key.MaximumLength = ImageSize; + + if ( CreateTimerQueueTimer( &hNewTimer, hTimerQueue, RtlCaptureContext, &CtxThread, 0, 0, WT_EXECUTEINTIMERTHREAD ) ) + { + WaitForSingleObject( hEvent, 0x32 ); + + memcpy( &RopProtRW, &CtxThread, sizeof( CONTEXT ) ); + memcpy( &RopMemEnc, &CtxThread, sizeof( CONTEXT ) ); + memcpy( &RopDelay, &CtxThread, sizeof( CONTEXT ) ); + memcpy( &RopMemDec, &CtxThread, sizeof( CONTEXT ) ); + memcpy( &RopProtRX, &CtxThread, sizeof( CONTEXT ) ); + memcpy( &RopSetEvt, &CtxThread, sizeof( CONTEXT ) ); + + // VirtualProtect( ImageBase, ImageSize, PAGE_READWRITE, &OldProtect ); + RopProtRW.Rsp -= 8; + RopProtRW.Rip = VirtualProtect; + RopProtRW.Rcx = ImageBase; + RopProtRW.Rdx = ImageSize; + RopProtRW.R8 = PAGE_READWRITE; + RopProtRW.R9 = &OldProtect; + + // SystemFunction032( &Key, &Img ); + RopMemEnc.Rsp -= 8; + RopMemEnc.Rip = SysFunc032; + RopMemEnc.Rcx = &Img; + RopMemEnc.Rdx = &Key; + + // WaitForSingleObject( hTargetHdl, SleepTime ); + RopDelay.Rsp -= 8; + RopDelay.Rip = WaitForSingleObject; + RopDelay.Rcx = NtCurrentProcess(); + RopDelay.Rdx = SleepTime; + + // SystemFunction032( &Key, &Img ); + RopMemDec.Rsp -= 8; + RopMemDec.Rip = SysFunc032; + RopMemDec.Rcx = &Img; + RopMemDec.Rdx = &Key; + + // VirtualProtect( ImageBase, ImageSize, PAGE_EXECUTE_READWRITE, &OldProtect ); + RopProtRX.Rsp -= 8; + RopProtRX.Rip = VirtualProtect; + RopProtRX.Rcx = ImageBase; + RopProtRX.Rdx = ImageSize; + RopProtRX.R8 = PAGE_EXECUTE_READWRITE; + RopProtRX.R9 = &OldProtect; + + // SetEvent( hEvent ); + RopSetEvt.Rsp -= 8; + RopSetEvt.Rip = SetEvent; + 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 ); + + puts( "[INFO] Wait for hEvent" ); + + WaitForSingleObject( hEvent, INFINITE ); + + puts( "[INFO] Finished waiting for event" ); + } + + DeleteTimerQueue( hTimerQueue ); +} diff --git a/Src/Main.c b/Src/Main.c new file mode 100644 index 0000000..4572436 --- /dev/null +++ b/Src/Main.c @@ -0,0 +1,15 @@ + +#include +#include + +int main( ) +{ + puts( "[*] Ekko Sleep Obfuscation by C5pider" ); + + do + // Start Sleep Obfuscation + EkkoObf( 4 * 1000 ); + while ( TRUE ); + + return 0; +} \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..1971d80 --- /dev/null +++ b/makefile @@ -0,0 +1,20 @@ + +CCX64 := x86_64-w64-mingw32-gcc +CCX86 := i686-w64-mingw32-gcc + +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 + +OUTX64 := Ekko.x64.exe + +all: x64 + +x64: + @ echo Compile executable... + @ $(CCX64) Src/*.c -o $(OUTX64) $(CFLAGS) $(LFLAGS) -IInclude + +clean: + @ rm -rf bin/*.exe \ No newline at end of file