# Coinslot (CSAW '16)

We 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)
# Get the float value.
if len(split_num) == 2:
float_val = int(split_num)
else:
float_val = int(split_num)*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").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! :)