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
- home page - https://ctf.csaw.io
- Challenges - https://ctf.csaw.io/challenges
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
- Start a new case
- Add a host
- Adding new host
1
2
3
Step 1 - Load
- Add image file
- Select "ADD IMAGE FILE"
- Fill in
1
2
3
Title
- Subject
Copy of CSAW CTF
By elrey741 (Alex)
Copy of CSAW CTF
- 921