Fukahi Tekiō 不可避適応: Bypassing Win 10/11 FPU "Issues" via Custom CALL/POP XOR Encoder

Fukahi Tekiō 不可避適応: Bypassing Win 10/11 FPU "Issues" via Custom CALL/POP XOR Encoder

Published: 2026-01-15

Author: JAKESWIZ

⛧ GitHub: fukahi-na-tekio ⛧


Introduction

This exploit technique was developed for the vulnserver TRUN buffer overflow vulnerability, but it can be applied to other exploits, especially for those new to ARM → x86/64 emulation exploitation.

The motivation came from wanting to run Windows exploitation demos on an ARM Mac (running Windows 11 AARCH64 with the Prism emulation layer) for a talk at Wild West Hackin' Fest in Denver.

The Problem

When exploiting buffer overflows on modern Windows systems (especially under ARM emulation), msfvenom's default encoder (shikata_ga_nai) crashes during shellcode execution:

eax=00000000 ebx=00000000 ecx=00000052 edx=02ff4a30 esi=55bd55d0 edi=00401848
eip=089ff959 esp=089ff924 ebp=00000000
089ff959 317012          xor     dword ptr [eax+12h],esi
Attempt to read from address 00000012

The decoder tries to dereference a register (EAX, EBP, or ESI) containing a near-null value.

Why This Happens

shikata_ga_nai uses a GetPC technique relying on FPU (Floating Point Unit) instructions:

fcmovb st, st(5)        ; Any FPU instruction
fnstenv [esp-0xc]       ; Save FPU state to stack
pop ebp                 ; Grab saved EIP from FPU state

On Windows 10/11 and under ARM emulation (Prism), the FPU instruction pointer field often returns zeros. When the decoder does pop ebp, it gets 0x00000000 and crashes.

The Solution: CALL/POP GetPC

Instead of relying on FPU quirks, use the reliable CALL/POP technique:

    jmp short call_label    ; Jump to the CALL
pop_label:
    pop esi                 ; ESI now contains address of encoded shellcode
    ; ... decoder logic ...
call_label:
    call pop_label          ; Pushes address of encoded shellcode, jumps back
    ; encoded shellcode starts here

When the CPU executes a CALL instruction, it pushes the address of the next instruction onto the stack. We immediately POP that address into a register. This is 100% reliable because CALL always pushes the return address — no FPU state involved.


Want to read more? Read more at:
www.churchofmalware.org

 

Back to blog