Weekly Reading List for 2/1/14

Previews for BSides SF 2014

A couple of new articles have been posted with previews of this year’s BSides San Francisco. Akamai has a preview of several talks and Tripwire previews a day in the life of an information security researcher.

Application Whitelist Bypass

@infosecsmith2 guest posts over at Room362 about using IEexec.exe to bypass application whitelisting.

Custom Wordlists

Chief Monkey over at IT Security Toolbox reports on a tool called SmeegeScrape that allows you to build a wordlist from the contents of a system. He reports on it in the context of a forensics task, but it seems like it would be a great option for penetration testing as well.

Encryption with Plausible Deniability

Michael Mimoso at ThreatPost describes a new encryption mechanism called ‘Honey Encryption’. The idea is that an attacker can get a plausible decryption output from a wrong password, making it harder to know if a decryption was valid when performing offline attacks.

The reading list is a little short this week – it’s been crazy.


Weekly Reading List for 1/25/14

This week, we’re focusing on binary exploitation and reversing. (Thanks to Ghost in the Shellcode for making me feel stupid with all their binary pwning challenges!)

Basic Shellcode Examples

Gal Badishi has a great set of Basic Shellcode Examples. It’s almost two years old, but a good primer into how basic shellcode works. x86 hasn’t changed (yes, I’m ignoring x64 for now), so still quite a relevant resource for those of us who have leaned on msfvenom/msfpayload for our payload needs.

Project Shellcode

Going beyond the basic, Project Shellcode is a site full of resources for crafting and understanding shellcode. Based on training classes used at BlackHat 2012, they walk through all the steps in writing shellcode.

x86 Assembly Guide

If the shellcode above looked like Greek, perhaps it’s time for an x86 assembly primer/refresher. UVA’s CS department has you covered with their x86 Assembly Guide, used in their CS216 class. It also has some useful reference to how the instructions work.

GNU Debugger Tutorial

If you want to observe the behavior of a running program, you’re going to want a debugger. If you’re running on Linux and haven’t spent the $1200 for IDA pro, you’re probably using the GNU Debugger, better known as GDB. RMS (no, not that RMS) has a great gdb tutorial.


Ghost in the Shellcode 2014

A quick Ghost in the Shellcode 2014 summary. Great CTF, but you better know your binary exploitation. I’m pretty happy with the overall 27th finish Shadow Cats managed. Here’s a summary of our team writeups, the first 3 by me, the last one by Dan.


Ghost in the Shellcode 2014: Radioactive

Radioactive was a crypto challenge that executed arbitrary python code, if you could apply a correct cryptographic tag. Source was provided, and the handler is below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!python
class RadioactiveHandler(SocketServer.BaseRequestHandler):
  def handle(self):
    key = open("secret", "rb").read()
    cipher = AES.new(key, AES.MODE_ECB)

    self.request.send("Waiting for command:\n")
    tag, command = self.request.recv(1024).strip().split(':')
    command = binascii.a2b_base64(command)
    pad = "\x00" * (16 - (len(command) % 16))
    command += pad

    blocks = [command[x:x+16] for x in xrange(0, len(command), 16)]
    cts = [str_to_bytes(cipher.encrypt(block)) for block in blocks]
    for block in cts:
      print ''.join(chr(x) for x in block).encode('hex')

    command = command[:-len(pad)]

    t = reduce(lambda x, y: [xx^yy for xx, yy in zip(x, y)], cts)
    t = ''.join([chr(x) for x in t]).encode('hex')

    match = True
    print tag, t
    for i, j in zip(tag, t):
      if i != j:
        match = False

    del key
    del cipher

    if not match:
      self.request.send("Checks failed!\n")
    eval(compile(command, "script", "exec"))

    return

So, it looks for a tag:command pair, where the tag is hex-encoded and the command is base64 encode. The command must be valid python, passed through compile and eval, so you’ll need to send a response back to yourself via self.request.send.

So how’s the tag calculated? Every 16-byte block of the command is encrypted in AES-ECB mode (so, two identical plaintexts == two identical ciphertexts) and then the encrypted blocks are xored together, producing the final tag. My first thought was to generate a plaintext such that len(plain) % 16 == 0, then repeat it twice, so the XORs will cancel out and give a tag of 00…00. Unfortunately, the padding must be at least one byte long, and my plaintext cannot contain null bytes.

So, we were also provided some sample code. One such example, decoded from its base64 representation, turns out to be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!python
import os

self.request.send("Send command to eval: \n")
cmd = self.request.recv(1024).strip()


good = True
for b in cmd:
	if b not in '0123456789+-=/%^* ()':
		good = False

if good:
	self.request.send(str(eval(cmd)) + "\n")
else:
	self.request.send("???\n")

It turns out the line good = False (and two trailing newlines) are their own 16-byte block. We can append “good = True \n\n” to reset the value of true, and append it a 2nd time to get our tag to come out correctly. Then we can simply provide self.request.send(open('key').read()) when we receive our “Send command to eval:” prompt. And this got our flag, but it turns out there are two simpler solutions.

Alternate solution 1

Provide your own code as a multiple of 16. Provide it again. This gives you a tag of 00…00. But we know this doesn’t work. So instead, append one of the code samples provided, and use the tag for that, as 0{16} ^ known_tag = known_tag.

Alternate solution 2

Start your input with : followed by whatever base-64 encoded code you want. If you provide no tag at all, then the loop for tag comparison is never checked, leaving match=True. (This was probably an accident in the design of the problem, possibly inteding to provide constant-time tag comparison. As a side note, that tag comparison is not even constant time, even for strings of the proper length.)


Ghost in the Shellcode 2014: Lugkist

Lugkist was an interesting “trivia” challenge. We were told “it’s not crypto”, but it sure looked like a crypto challenge. We had a file like:

Find the key.

GVZSNG
AXZIOG
YNAISG
ASAIUG
IVPIOK
AXPIVG
PVZIUG
AXLIEG

Always 6 letters, but no other obvious pattern. I did notice that the 4th character always was S or I and the final character G or K, but couldn’t make anything of that. I realized the full character set was ‘AEGIKLONPSUTVYXZ’. Searching for this string revealed nothing, but searching for the characters space separated revealed that this was the same character set as used by the codes for the original Game Genie. And Game Genie codes were 6 characters long.

So, they’re Game Genie codes. What now? Well, there’s a handy (NES Game Genie Technical Notes)[http://tuxnes.sourceforge.net/gamegenie.html] that tells us how the characters decode. Turns out the characters are an alphabetical hexadecimal (there are 16 of them) but not in alphabetical order. Decoding the resulting hex was useless. The technical notes also tell us how to decode the address and data from the codes. Giving that a try doesn’t reveal anything obvious, but it was noteworthy that the data values were all within the normal printable ASCII range. The addresses seemed randomly ordered, but were contiguous. Maybe sorting by address and taking the values as characters to build a string?

“Power overwhelming? Back in my day cheats did not have spaces.”

Full translation code (in python) is below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!python
codes = 'APZLGITYEOXUKSVN'
xlate = {c: i for i,c in enumerate(codes)}

def numeric(s):
  return [xlate[x] for x in s]

def address(s):
  n = numeric(s)
  return (0x8000 +
      ((n[3] & 7) << 12) |
      ((n[5] & 7) << 8) |
      ((n[4] & 8) << 8) |
      ((n[2] & 7) << 4) |
      ((n[1] & 8) << 4) |
      (n[4] & 7) |
      (n[3] & 8))

def data(s):
  n = numeric(s)
  return (((n[1] & 7) << 4) |
          ((n[0] & 8) << 4) |
          (n[0] & 7) |
          (n[5] & 8))

prev_addr = 0
addrs = []
addr_dict = {}
with open('lugkist.2') as f:
  for l in f:
    l = l.strip()
    a = address(l)
    #print 'A: %04x [%04x]' % (a, a-prev_addr)
    prev_addr = a
    addrs.append(a)
    addr_dict[a] = l

chars = []
for x in sorted(addrs):
  chars.append(chr(data(addr_dict[x])))

print ''.join(chars)