CSAW CTF Challenges

slides: https://goo.gl/RqSpGc

CTF? 

  • WTF? (CTF Time)
  • flag format =
  • normal tools (kali has all these built in)
    • nc
    • telnet
    • nmap
flag{congr4tz_y0u_found_1t}

Format and First Challenge

Misc - Serial - 50pts

  • Tools needed
    • nc
    • curious mind
    • googlefoo

Step 0 (poke) ( "cause programming =)" )

nc misc.chal.csaw.io 4239
  • First thing first

 

  • Output:

 

 

  • Interesting
    • now?
8-1-1 even parity. Respond with '1' if you got the byte, '0' to retransmit.
01110011001

Step 1 (understand)

  • or wiki-fu - https://en.wikipedia.org/wiki/Parity_bit
  • so from earlier...
  •                              01110011001
  •                              ^                  ^ ^
  •                           start       parity stop
  • Start is always = 0 (ignore in calculations)
  • Stop is always = 1 (ignore in calculations)
  • Parity bit is always = depends (calculation dependent)

Step 2 (Python script)

  • Why?
  • credit - @blackmanta
  • game plan
    • connect
    • calculate
    • continue
  • Connect and libs
#!/usr/bin/env python3
import socket

# making connection
s = socket.socket()
s.connect(("misc.chal.csaw.io", 4239))

Step 2 cont...

  • nuances

 

 

  • Till when?

 

# used to skip the intro message and keep track of connection times
i = 0

# used to print out the flag
message = ''
# untill no more connection
while True:

    # connections first one is weird
    if i == 0:
        i += 1
        data = s.recv(1000).decode().split('\n')[1]
    else:
        i += 1
        data = s.recv(1000).decode()

Step 2 again...

  • Data? and etc
# check to see if data recieved
    if data:
        # check if parity is right
        stat = check(data.strip())
        print("Data: %s Sol = %s"% (data, stat))
        if stat == '1': message += chr(int(data.strip()[1:9], 2))
        s.send(stat.encode())

Step 2 - Big function

def check(string):

    # defining variables for parity checks
    parity = 0
    parityBit = 0

    # looping through and seeing if odd or even and parity bit
    for n,i in enumerate(string):
        if n == 0:
            n + 1
        elif n == len(string) - 2:
            parityBit = i
            break
        else:
            if i == '1':
                parity += 1

    # determining if parity is valid or not
    if parity%2 == 0:
        if parityBit == '0':

            # correct parity based off of parity bit
            return str(1)
        else:

            # incorrect parity based off of parity bit
            return str(0)
    else:
        if parityBit == '1':

            # correct parity based off of parity bit
            return str(1)
        else:

            # incorrect parity based off of parity bit
            return str(0)

Step 2...why...again...

  • one last thing...
elif not data:

        # end of connection
        print('amount of times connected = ' + str(i))
        print(message)
        s.close()
        break

Step 3 - Final Script

#!/usr/bin/env python3
import socket


def check(string):

    # defining variables for parity checks
    parity = 0
    parityBit = 0

    # looping through and seeing if odd or even and parity bit
    for n,i in enumerate(string):
        if n == 0:
            n + 1
        elif n == len(string) - 2:
            parityBit = i
            break
        else:
            if i == '1':
                parity += 1

    # determining if parity is valid or not
    if parity%2 == 0:
        if parityBit == '0':

            # correct parity based off of parity bit
            return str(1)
        else:

            # incorrect parity based off of parity bit
            return str(0)
    else:
        if parityBit == '1':

            # correct parity based off of parity bit
            return str(1)
        else:

            # incorrect parity based off of parity bit
            return str(0)


# making connection
s = socket.socket()
s.connect(("misc.chal.csaw.io", 4239))

# used to skip the intro message and keep track of connection times
i = 0

# used to print out the flag
message = ''

# untill no more connection
while True:

    # connections first one is weird
    if i == 0:
        i += 1
        data = s.recv(1000).decode().split('\n')[1]
    else:
        i += 1
        data = s.recv(1000).decode()

    # check to see if data recieved
    if data:
        # check if parity is right
        stat = check(data.strip())
        print("Data: %s Sol = %s"% (data, stat))
        if stat == '1': message += chr(int(data.strip()[1:9], 2))
        s.send(stat.encode())


    elif not data:

        # end of connection
        print('amount of times connected = ' + str(i))
        print(message)
        s.close()
        break

Misc - CVV - 100 pts

  • @arcanum
import socket
import time
import re

def lp(s, n, c='0'):
    return (n-len(s))*c + s

def rp(s, n, c):
    return s + (n-len(s))*c

def luhn_digit(dstr):
    total = 0 # int
    
   
   for i in range(1, len(dstr)+1):
        cadd = int(dstr[len(dstr) - i]) * (i % 2 + 1)
        while cadd > 9: cadd -= 9
        total += cadd

   '''
    # or this
    total += sum(int(e) for e in dstr)
    for i in range(len(dstr)-1, -1, 2): # every other index, should be x2 instead of x1
        total+=int(dstr[i])
        if int(dstr[i]) > 4: total -= 9 # if digit*2 > 10 then subtract 9
    '''  

   return str(total*9 % 10) # or 10 minus the units digit

def luhn_sum(dstr): # int
    total = 0 # int

   for i in range(0, len(dstr)):
        cadd = int(dstr[len(dstr) - i - 1]) * (i % 2 + 1)
        while cadd > 9: cadd -= 9
        total += cadd
        

   return total % 10 # or 10 minus the units digit  

def card_number(cs, n): # card string, n
    #cnum += lp(str(n), 6) # make it different and new. Can't simply use number or else can be repeats

   chdig = cs.index('_') # arbitrarily change first one
    cs = cs[:chdig]+"#"+cs[chdig+1:]
    cs = cs.replace('_', '1') # '1' chosen arbitrarily
    #0123456789 ->
    #0246813579 for the 2x operation so this mapping is 1-1 and will always work

   for i in range(10): # brute force 10 possible digits
        cs_mod = cs.replace('#', str(i))
        if 0 == luhn_sum(cs_mod):
            return cs_mod

   raise Exception("Math error, should never happen")

print(luhn_digit("121"))
print(luhn_digit("34111111111111"))

ipstr = 'misc.chal.csaw.io' # IP or domain
portnum = 8308

csocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
csocket.connect((ipstr, portnum))

val = ""

DEFAULT_CARD_LENGTH = 16
UID_LENGTH = 6
PREFIX_LENGTH = 4

card_starts = {"Discover": ("6011",16), "American Express": ("34",15), "Visa": ("4",16), "MasterCard": ("51",16)}

n = 0
while 1:
        n += 1

       cardspec = ""

       print("-- Question "+str(n))
        data = csocket.recv(4096) # receive prompt
        
       print "RECEIVED:"+data

       cquery = re.findall(r"(?<=I need a new )[^!]*", data)
        if len(cquery): # creating a number
            cardspec = cquery[0]
            #cardspec = data[13:-2]
            print cardspec

           if cardspec.startswith("card that starts with "):
                cnum = re.findall(r"(?<=card that starts with )[^!]*", data)[0]
                cnum = rp(cnum, DEFAULT_CARD_LENGTH, '_')

           elif cardspec.startswith("card which ends with "):
                cnum = re.findall(r"(?<=card which ends with )[^!]*", data)[0]
                cnum = lp(cnum, DEFAULT_CARD_LENGTH - UID_LENGTH - PREFIX_LENGTH, '_')
                cnum = "6011"+lp(str(n), UID_LENGTH, '0')+cnum
            
           else: # brand of card
                cnum = card_starts[cardspec][0]
                cnum = rp(cnum, PREFIX_LENGTH, '2')
                cnum += lp(str(n), UID_LENGTH, '0')
                card_length = card_starts[cardspec][1]
                cnum = rp(cnum, card_length, '_')

           print cnum

           answer = card_number(cnum, n)

       else: # validating a number
            tnum = re.findall(r"(?<=I need to know if )[^ ]*", data)[0]
            answer = str( [0, 1] [luhn_sum(tnum)==0] )

           '''
            if len(re.findall(r"^(?:4[0-9]{12}(?:[0-9]{3})?|(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})$", data)) == 0:
                answer= '0' # regex for these 4 types of credit cards
            '''

           if int(tnum[0]) in []: # real CCN does not start with these digits
                answer = '0'
        
       tosend = answer
        print "SENDING: "+answer
        csocket.send(answer+"\n")

       time.sleep(.01)

Forensics - Best Router - 200 pts

  • Tools
    • tar
    • autopsy

Step 0 - Prep

  • Install

 

  • Run

 

  • Navigate - open a browser to this link
  • this should have been what you saw after executing
apt-get install autopsy
autopsy
============================================================================

                       Autopsy Forensic Browser 
                  http://www.sleuthkit.org/autopsy/
                             ver 2.24 

============================================================================
Evidence Locker: /tmp
Start Time: Mon Sep 25 18:50:46 2017
Remote Host: localhost
Local Port: 9999

Open an HTML browser on the remote host and paste this URL in it:

    http://localhost:9999/autopsy

Keep this process running and use <ctrl-c> to exit
  • tar
tar xzvf best_router.tar.gz

Step 1 - Load

  • Splash screen
  • Start a new case

Step 1 - Load

  1. Start a new case
  2. Add a host
  3. Adding new host

1

2

3

Step 1 - Load

  1. Add image file
  2. Select "ADD IMAGE FILE"
  3. Fill in

1

2

3

Title

  • Subject

CSAW CTF

By 49th Security Division

CSAW CTF

  • 737