Coinslot (CSAW '16)
22 Sep 2016We qualified for the CSAW’16 finals at IIT Kanpur! /o/.
Here is a write-up for Coinslot automation challenge.
from pwn import *
import math
# All the denominations of notes/coins
denoms = ["10000", "5000", "1000", "500", "100", "50", "20", "10",
"5", "1", "0.5", "0.25", "0.1", "0.05", "0.01"]
# Integral denominations for ease in calculation
integral_denoms = ["10000", "5000", "1000", "500", "100", "50", "20",
"10","5", "1"]
# Float denoms
float_denoms = ["0.5", "0.25", "0.1", "0.05", "0.01"]
# Function to return the number of notes/coins required for each denomination
# Takes in an arbitrary value and returns a hash containing the key as the
# denomination and the number as the corresponding value.
# Eg. calculate_min(0.1) = {"0.1": 1}
def calculate_min(value):
result_hash = {}
# Separate the decimal and integral part.
split_num = str(value).split('.')
# Get the integral value.
int_val = int(split_num[0])
# Get the float value.
if len(split_num[1]) == 2:
float_val = int(split_num[1])
else:
float_val = int(split_num[1])*10
# For each integral denomination, calculate the number of coins/notes.
for i in integral_denoms:
if value >= int(i):
result_hash[i] = int_val/int(i)
int_val = int_val%int(i)
# For each float denomination, calculate the number of coins.
for i in float_denoms:
temp_i = int(float(i)*100)
if float_val >= temp_i:
result_hash[i] = float_val/temp_i
float_val = float_val%temp_i
return result_hash
# Connecting to remote.
r = remote("misc.chal.csaw.io", 8000)
# Parse the fist line which contains the amount to get the value.
val = float(r.recvline().replace("$", ""))
r.recvuntil("$10,000 bills:")
print "[+] Here we go."
# Count the number of times we solve the challenge.
count = 0
while 1:
# Calculate min function returns a hash containing the denoms as the key
# and number of notes/coins as values.
result_hash = calculate_min(val)
# For all keys
for i in denoms:
# If there exists a corresponding value
if i in result_hash:
r.sendline(str(result_hash[i]))
else:
r.sendline("0")
# Get dat flag at the 399th attempt
if count == 299:
line = r.recv(128)
print line
else:
line = r.recvuntil(":")
if "correct" in line:
# Receive the next amount from the server and set it to val
val = float(line.split("\n")[1].replace("$", ""))
print "[+] Solved: {}".format(str(count))
count += 1
We get the flag which is flag{started-from-the-bottom-now-my-whole-team-fucking-here}
. Stay tuned for more! :)