Monday, April 23, 2012

Architecture Independent Windows Shellcode

What's this? A non PowerShell-related blog post??? Unheard of! Today's post is more of a novelty but perhaps someone might benefit from it.

There may be times when you’d like to execute shellcode but don’t know the architecture of the processor that you’ll be running on. I’ve seen at least two techniques to solve this problem [1] [2]. Well, here’s yet another technique that is specific to Windows. The following shellcode will detect whether it’s running in pure 32-bit, pure 64-bit, or Wow64 mode:
On 64-bit processors in Windows, the GS segment register stores the pointer to the PEB (Process Environment Block) in GS:[0x60]. In Wow64 mode this is a DWORD value. In 32-bit mode, the GS segment register is not used and uses FS:[0x30] to point to the PEB.

1. Berend-Jan "SkyLined" Wever, w32-exec-calc-shellcode, http://code.google.com/p/w32-exec-calc-shellcode/

2. “isX64 Gem”, July 31, 2011, http://www.ragestorm.net/blogs/?p=376

6 comments:

  1. [BITS 32]
    wow64:
    ; Do wow64 stuff
    mov eax, [gs:0x60] ; load PEB address
    ---

    Since you are 32-bit code running on WOW64... shouldn't gs:0x60 be fs:0x30, instead?

    ReplyDelete
  2. Yes and no. I should have been more specific in my comment in that line of the assembly.

    There are actually two PEBs in Wow64 mode. In Wow64 mode, gs:0x60 points to the 64-bit PEB. fs:[0x30] points to the 32-bit PEB. In terms of shellcode, it's definitely going to be more useful to reference fs:[0x30] even in Wow64 mode.

    Check out the differences yourself in Windbg though. From a 64-bit debugger, run !peb. You'll see that the address from gs:[0x60] points to the 64-bit PEB. From a 32-bit Windbg, run !peb. You'll see that fs:[0x30] points you to the pure 32-bit PEB.

    Here's the beginning of the output that received:

    0:009:x86> !peb
    PEB at 000000007efdf000
    ...

    0:005> !peb
    PEB at 7efde000
    ...

    Both addresses are consistent with what was loaded in the shellcode. What's interesting is that trying to reference the GS segment register from within Windbg will fail. For example, `dd gs:[0x60] L1` points to nothing but executing the assembly instruction `mov eax, [gs:0x60]` works just fine. Just another peculiarity of Wow64 mode, I guess.

    ReplyDelete
  3. I don't have WinDBG here, but you got it right on your comment, but I still think your code is wrong. "wow64:" code runs the 32-bit mov but uses the wrong selector and register, if wow64 gets executed that means the code is running in virtual memory of a PE32 in WOW64. Should be the same code as in "bit32" but as GS is != 0 then *do the wow64 stuff too, in the same routine.

    ReplyDelete
  4. In fact, I think your code should be like this:

    mov eax, cs
    cmp eax, 23h
    je bits32
    ;do 64-bit stuff here
    ret

    bits32:
    mov ecx, gs
    jecxz pure32

    ;do 32-bit in WOW64 stuff here
    ret

    pure32:
    ;do 32-bit not in WOW64 stuff here
    ret

    ReplyDelete
    Replies
    1. That's certainly one way to do it. Quite elegant, actually. Thanks for sharing that technique.

      Putting aside the respective PEB loading instructions in each section (wow64, bits32, bits64), what about my code is wrong? Have you tried it? I'm sorry but I don't fully understand the wording from your previous comment.

      I appreciate you picking apart my code, though. :D

      Delete
  5. There are several methods you can use. It depends on the function as well.

    ReplyDelete