A Brief History of Exploitation - Derbycon 4.0

Sept. 29, 2014, 10:22 a.m.

 

This past weekend I gave a stable talk at Derbycon 4.0 where I talked about the history of binary exploitation. It was pretty high-level, but my goal was to let people know that this stuff isn't all that hard, and even though you can't really learn it in school there are definitely plenty of resources available online to teach yourself. Here's the presentation:

http://prezi.com/kyppbl8z_wvs/a-brief-history-of-exploitation-derbycon-40/

I'll watch for the video, and will post that whenever it hits youtube.

Quick and Dirty IPv6 Range Enumeration

Aug. 29, 2013, 12:30 p.m.

 

I recently had to write a bit of code to enumerate all IPv6 addresses in a given range. The syntax allows for the use of "*" and "-", where "*" is semantically equivalent to "0-ffff". Here's my quick and dirty solution. I also thought it was interesting because I used some python constructs you don't see very often and a recursive generator, expand_part().

def expand_ipv6(addr_range):
    # first change all '*' portions to use '-'
    addr_range = map(lambda part: '0-ffff' if part == '*' else part,
                     addr_range.split(':'))
    addr_range.reverse() # stackify
    for addr in expand_part([], addr_range):
        yield ':'.join(addr) + '\n'

def expand_part(prefix, remainder):
    "recursively expand an address given a prefix (list) and remainder (stack)"
    current = remainder.pop()
    if '-' not in current:
        # if the current part is not a range, add to the prefix and continue
        if remainder:
            for addr in expand_part(prefix + [current], remainder[:]):
                yield addr
        else:
            yield prefix + [current]
    else:
        # expand the range
        current = current.split('-')
        for i in xrange(int(current[0], 16), int(current[1], 16)+1):
            if remainder:
                for addr in expand_part(prefix + [hex(i)[2:]], remainder[:]):
                    yield addr
            else:
                yield prefix + [hex(i)[2:]]

Generators are important because a range could expand to a HUGE number of IPv6 addresses and you wouldn't want to try to generate them all and store them in memory. Just one "*" yields 65,536 addresses, and using multiple "*" or "-" ranges means you're multiplying that number.

Ghost in the Shellcode 2013 - Kiss Writeup

Feb. 19, 2013, 6:24 p.m.

 

This was the first problem, and only worth 50 points. I think it should have probably been worth more than that, and apparently only 18 teams solved it.

The guys of 0xbadf00d have already done a pretty good job of eplaining the problem, so I'll try to focus on explaining the steps that our team went through to figure it out.

We started with the html file given, and quickly located the original to search for differences. While we were doing that I think someone tried calling the unfortunate person who happened to get Bryan Cantrill's old phone number (oops, sorry). The only differences really were spaces added at the end of some lines. We briefly thought about Whitespace, but it was quickly dismissed as there are no tabs in the file provided.

Here's where we made a mistake that ended up costing us a pretty significant amount of time. We found the difference in length of each line, resulting in the following:

>>> diffs = [len(a)-len(b) for a, b in zip(gits_version, original)]
>>> diffs
[2, 0, 4, 6, 8, 4, 9, 4, 9, 8, 7, 9, 0, 3, 4, 5, 4, 7, 9, 0, 3, 1, 8, 7, 5,
1, 0, 6, 6, 1, 1, 9, 6, 7, 0, 4, 1, 3, 0, 2, 3, 8, 4, 2, 5, 7, 6, 9, 3, 4,
0, 3, 0, 3, 2, 3, 4, 4, 0, 5, 0, 5, 1, 9, 5, 9, 5, 4, 4, 3, 4, 5, 6, 1, 0,
4, 5, 8, 6, 4, 2, 6, 5, 0, 3, 3, 2, 7, 6, 1, 6, 8, 5, 7, 2, 9, 7, 5, 0, 5,
9, 1, 8, 7, 6, 0, 9, 2, 4, 5, 6, 5, 8, 9, 2, 7, 3, 7, 8, 0, 8, 8, 5, 1, 9,
1, 5, 5, 6, 4, 6, 5, 6, 0, 0, 5, 8, 0, 6, 3, 2, 6, 1, 6, 1, 1, 1, 5, 6, 8,
3, 0, 7, 5, 4, 6, 0, 6, 4, 7, 2, 7, 1, 6, 1, 7, 7, 8, 5, 9, 3, 3, 5, 5, 1,
1, 4, 8, 2, 1, 9, 9, 0, 5, 9, 1, 6, 9, 2, 3, 5, 5, 5, 0, 0, 3, 3, 9, 7, 0,
7, 5, 7, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0]

In hindsight, the -1 should have been an indicator that we screwed something up. We spent a some time trying to make sense of these numbers. Were they offsets for characters in each line? Could they be directly converted to ASCII somehow? After trying a few of these, we tried getting rid of the extra stuff and turning that into a nice long base-10 number. From that, we turned the number into hex, and finally an ascii string.

>>> num = int(''.join(map(str, diffs[:-63])))
>>> num
2046849498790345479031875106611967041302384257693403032344050519595443456104
5864265033276168572975059187609245658927378088519155646560058063261611156830
75460647271617785933551148219905916923555003397075722L
>>> hexstr = hex(num)
>>> hexstr
'0x687474703a2f2f656e2bc9ec6d8c9c8218cf44ef872f1791de5e929e203374ed39aee6260
5e46a6770ce83f2b333fbd5f6b200f4852e818bbbc1505ac3a75433d4cbbeb0e573234d61737
36163687573657474730aL'
>>> binascii.unhexlify(hexstr[2:-1])
'http://en+\xc9\xecm\x8c\x9c\x82\x18\xcfD\xef\x87/\x17\x91\xde^\x92\x9e 3t
\xed9\xae\xe6&\x05\xe4jgp\xce\x83\xf2\xb33\xfb\xd5\xf6\xb2\x00\xf4\x85.\x81
\x8b\xbb\xc1PZ\xc3\xa7T3\xd4\xcb\xbe\xb0\xe5s#Massachusetts\n'

Well... that's close. It looks like it was supposed to be a Wikipedia link. After some bitching in IRC (and lots of attempts at XOR-ing to find whatever was obfuscating the rest of our link), we finally realized we needed to disregard the original file, and instead only count the number of spaces at the end of each line in the GitS version. Repeating the same process with the new counts gave us the full http://en.wikipedia.org/wiki/List_of_burn_centers_in_the_United_States#Massachusetts link. The key was "Boston Medical Center". We spent way too long for those 50 points.