├── .gitignore ├── README.md ├── LICENSE └── nEkko.nim /.gitignore: -------------------------------------------------------------------------------- 1 | /nEkko.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nEkko 2 | A nim port of C5pider's Ekko project. 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, pruno7 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /nEkko.nim: -------------------------------------------------------------------------------- 1 | import winim/lean 2 | import ptr_math 3 | type 4 | USTRING* = object 5 | Length*: DWORD 6 | MaximumLength*: DWORD 7 | Buffer*: PVOID 8 | 9 | # proc printf(formatstr: cstring) {.importc: "printf", varargs, 10 | # header: "".} 11 | 12 | proc nEkko(sleepTime: DWORD) = 13 | var 14 | ctxThread: CONTEXT 15 | ropProtRW: CONTEXT 16 | ropMemEnc: CONTEXT 17 | ropDelay: CONTEXT 18 | ropMemDec: CONTEXT 19 | ropProtRX: CONTEXT 20 | ropSetEvt: CONTEXT 21 | 22 | hTimerQueue: HANDLE = CreateTimerQueue() 23 | hNewTimer: HANDLE 24 | hEvent: HANDLE = CreateEventW(cast[LPSECURITY_ATTRIBUTES](0), cast[WINBOOL](NULL), cast[WINBOOL](NULL), nil) 25 | 26 | imageBase: PVOID = cast[PVOID](GetModuleHandleA(NULL)) 27 | imageSize: PVOID = cast[PVOID](cast[PIMAGE_NT_HEADERS](imageBase + cast[PIMAGE_DOS_HEADER](imageBase).e_lfanew).OptionalHeader.SizeOfImage) 28 | oldProtect: DWORD 29 | 30 | keyBuf: array[16, char] = [char 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'] 31 | 32 | keyString: USTRING 33 | imgString: USTRING 34 | 35 | ntContinue: PVOID = GetProcAddress(GetModuleHandleA( "Ntdll" ),"NtContinue") 36 | sysFunc032: PVOID = GetProcAddress(LoadLibraryA( "Advapi32" ), "SystemFunction032") 37 | virtualProt: PVOID = GetProcAddress(LoadLibraryA( "Kernel32" ), "VirtualProtect") 38 | waitFor: PVOID = GetProcAddress(LoadLibraryA( "Kernel32" ), "WaitForSingleObject") 39 | 40 | keyString.Buffer = cast[PVOID](&keyBuf) 41 | keyString.Length = 16 42 | keyString.MaximumLength = 16 43 | 44 | imgString.Buffer = imageBase 45 | imgString.Length = cast[DWORD](imageSize) 46 | imgString.MaximumLength = cast[DWORD](imageSize) 47 | 48 | 49 | # printf("%-20s : 0x%-016p\n", "imageBase", imageBase) 50 | # printf("%-20s : 0x%-016p\n", "imageSize", imageSize) 51 | # printf("%-20s : 0x%-016p\n", "ntContinue", ntContinue) 52 | # printf("%-20s : 0x%-016p\n", "sysFunc032", sysFunc032) 53 | # printf("%-20s : 0x%-016p\n", "virtualProt", virtualProt) 54 | # printf("%-20s : 0x%-016p\n", "waitFor", waitFor) 55 | # printf("%-20s : 0x%-016p\n", "imgString.Buffer", imgString.Buffer) 56 | 57 | if (CreateTimerQueueTimer(cast[PHANDLE](&hNewTimer), hTimerQueue, cast[WAITORTIMERCALLBACK](RtlCaptureContext), &ctxThread, 0, 0, WT_EXECUTEINTIMERTHREAD)): 58 | WaitForSingleObject(hEvent, 0x32) 59 | copymem(&ropProtRW, &ctxThread, sizeof(CONTEXT)) 60 | copymem(&ropMemEnc, &ctxThread, sizeof(CONTEXT)) 61 | copymem(&ropDelay, &ctxThread, sizeof(CONTEXT)) 62 | copymem(&ropMemDec, &ctxThread, sizeof(CONTEXT)) 63 | copymem(&ropProtRX, &ctxThread, sizeof(CONTEXT)) 64 | copymem(&ropSetEvt, &ctxThread, sizeof(CONTEXT)) 65 | 66 | # VirtualProtect( ImageBase, ImageSize, PAGE_READWRITE, &OldProtect ); 67 | ropProtRW.Rsp -= 8 68 | ropProtRW.Rip = cast[DWORD64](virtualProt) 69 | ropProtRW.Rcx = cast[DWORD64](imageBase) 70 | ropProtRW.Rdx = cast[DWORD64](imageSize) 71 | ropProtRW.R8 = PAGE_READWRITE 72 | ropProtRW.R9 = cast[DWORD64](&oldProtect) 73 | # SystemFunction032( &Key, &Img ); 74 | ropMemEnc.Rsp -= 8; 75 | ropMemEnc.Rip = cast[DWORD64](sysFunc032) 76 | ropMemEnc.Rcx = cast[DWORD64](&imgString) 77 | ropMemEnc.Rdx = cast[DWORD64](&keyString) 78 | # WaitForSingleObject( hTargetHdl, SleepTime ); 79 | ropDelay.Rsp -= 8; 80 | ropDelay.Rip = cast[DWORD64](waitFor) 81 | ropDelay.Rcx = cast[DWORD64](cast[HANDLE](cast[LONG_PTR](-1))) 82 | ropDelay.Rdx = cast[DWORD64](sleepTime) 83 | # SystemFunction032( &Key, &Img ); 84 | ropMemDec.Rsp -= 8; 85 | ropMemDec.Rip = cast[DWORD64](sysFunc032) 86 | ropMemDec.Rcx = cast[DWORD64](&imgString) 87 | ropMemDec.Rdx = cast[DWORD64](&keyString) 88 | # VirtualProtect( ImageBase, ImageSize, PAGE_EXECUTE_READWRITE, &OldProtect ); 89 | ropProtRX.Rsp -= 8; 90 | ropProtRX.Rip = cast[DWORD64](virtualProt) 91 | ropProtRX.Rcx = cast[DWORD64](imageBase) 92 | ropProtRX.Rdx = cast[DWORD64](imageSize) 93 | ropProtRX.R8 = PAGE_EXECUTE_READWRITE 94 | ropProtRX.R9 = cast[DWORD64](&oldProtect) 95 | # SetEvent( hEvent ); 96 | ropSetEvt.Rsp -= 8; 97 | ropSetEvt.Rip = cast[DWORD64](SetEvent) 98 | ropSetEvt.Rcx = cast[DWORD64](hEvent) 99 | echo ("[INFO] Queue timers") 100 | 101 | CreateTimerQueueTimer(cast[PHANDLE](&hNewTimer), hTimerQueue, cast[WAITORTIMERCALLBACK](ntContinue), &ropProtRW, 100, 0, WT_EXECUTEINTIMERTHREAD) 102 | CreateTimerQueueTimer(cast[PHANDLE](&hNewTimer), hTimerQueue, cast[WAITORTIMERCALLBACK](ntContinue), &ropMemEnc, 200, 0, WT_EXECUTEINTIMERTHREAD) 103 | CreateTimerQueueTimer(cast[PHANDLE](&hNewTimer), hTimerQueue, cast[WAITORTIMERCALLBACK](ntContinue), &ropDelay, 300, 0, WT_EXECUTEINTIMERTHREAD) 104 | CreateTimerQueueTimer(cast[PHANDLE](&hNewTimer), hTimerQueue, cast[WAITORTIMERCALLBACK](ntContinue), &ropMemDec, 400, 0, WT_EXECUTEINTIMERTHREAD) 105 | CreateTimerQueueTimer(cast[PHANDLE](&hNewTimer), hTimerQueue, cast[WAITORTIMERCALLBACK](ntContinue), &ropProtRX, 500, 0, WT_EXECUTEINTIMERTHREAD) 106 | CreateTimerQueueTimer(cast[PHANDLE](&hNewTimer), hTimerQueue, cast[WAITORTIMERCALLBACK](ntContinue), &ropSetEvt, 600, 0, WT_EXECUTEINTIMERTHREAD) 107 | 108 | echo("[INFO] Wait for hEvent") 109 | WaitForSingleObject(hEvent, INFINITE); 110 | echo ("[INFO] Finished waiting for event") 111 | 112 | DeleteTimerQueue(hTimerQueue) 113 | when isMainModule: 114 | echo "[*] nEkko Sleep Obfuscation by pruno, Nim port of C5pider's Ekko project" 115 | while true: 116 | nEkko(4 * 1000) --------------------------------------------------------------------------------