metasploit, x86/alpha_mixed and Windows 7 are killing me

Yes, I know this is kind of a dramatic title but this will probably damage my sanity (or what remains of it…)

I’ve been studying some egghunting methods as a part of a you-know-what-kick-ass-course and at a certain point, due to some bad characters filtering we had to encode the payload. To be on the safe side, the egghunter was encoded with x86/alpha_mixed.

We have our own test machine on the course lab, which runs Windows Vista… but I had to do it in my own lab running Windows 7, of course. <– the typical smart-ass :)

After getting enough access violations to stop a train I decided to check out what the f**k was happening under the hood. I haven’t found a solution yet but I have isolated the root of the problem. If anybody gets any further please let me know on the comments!

The thing goes like this: the decoding stub, as any other self-{referencing, decoding, modifying} (that is, motherfucka code), needs some kind of GetEIP in order to  find its own position in memory. There are a couple of ways to achieve this, so let’s check what the source code of the encoder has to say:

– from the source code of x86/alpha_mixed (SVN 11713) –

# We need to create a GetEIP stub for the exploit
if (not reg)
     if(datastore['AllowWin32SEH'] and datastore['AllowWin32SEH'].to_s =~ /^(t|y|1)/i)
           reg = 'ECX'
           off = 0
           res = Rex::Arch::X86.geteip_fpu(state.badchars)    <-- probably SEH wasn't allowed
           if (not res)                                       <-- and a FSTENV GetPC is used
           raise RuntimeError, "Unable to generate geteip code"

On Vista+ SEH GetPC are incredible difficult to write due to additional SEH checks.
It looks like the only option left for Vista/Win7 is to use the GetEIP_FPU (FSTENV) method.

This FSTENV GetEIP is awesome for two reasons: it’s really small (only 7 bytes) and it doesn’t introduce any null chars into the payload. On the other side, it uses some obscure x87 (yes, the original arithmetic co-processor) assembler, which makes it not exactly straightforward ;)

$+0    FLDZ ; loads 0x00 onto the stack
$+2    FSTENV SS:[ESP - 0x0C] ; save the environment at ESP - 0x0C
; since the environment is an structure and the address of FLDZ
; is stored at offsec 0x0C on it, now this address is at ESP
$+6    POP ECX ; ECX contains now the address $+0

However, the code of the x86/alpha_mixed decoder stub is different. I guess this is an enhanced version of it.
Here an screenshot of the problematic code (click to enlarge)

As you can see there are two fundamental differences:

  • The instruction FLDZ has been replaced for FCMOVNB ST, ST(6)
  • The FSTENV instruction has its parameter on the data segment (DS) and not in the stack… o.O

The screenshot was taken after the execution of FSTENV (see EIP reg). At this time the address of $+0 should be on top of the stack, ready to be popped to ECX (forget the previous pop/push ebp, they don’t change the stack, is some kind of code interleaving)

But the value at ESP is far from being within the main executable memory space. Actually is 0x8xxxxxxx, that is, *inside the windows kernel*.

This value is popped into ECX and slightly modified by the following instructions until it reaches the *quite properly* commented as “offending instruction” where the access violation occurs as we try to write into kernel space.

As mentioned at the beginning, this code is working without problems in Windows Vista Ultimate but it’s causing this fault on Windows 7. If you know what happens here, please let me know in the comments, I’ll much appreciate it!

UPDATE: corelanc0d3r pointed out in twitter that this could be an issue on AMD processors. It makes sense, since FSTENV GetPC depends on obscure x87 assembler instructions. It could be a slightly different implementation on AMD. Thanks Peter!


5 thoughts on “metasploit, x86/alpha_mixed and Windows 7 are killing me

  1. Would you happen to have an Intel based computer you could test this out on to see if it really is AMD that’s causing the problem? Because it would make sense if FSTENV GetEIP relies on a coprocessor that AMDs don’t have.

  2. Hi kevin,

    I did test this, indeed. The machines on the course remote lab were Intel based and this exactly chunk of ASM instructions worked flawlessly. So I would say it’s safe to assume that this is an Intel-only method.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s