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}``

### Misc - Serial - 50pts

• Tools needed
• nc
• curious mind

### 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)

'''
# 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)

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

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

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

time.sleep(.01)``````

• 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``

• Splash screen
• Start a new case

1. Start a new case

1

2

3