Tunnels
06/10/2022
By: HELLOPERSON
Tags: misc HSCTF-2022Problem Description:
Catch b40m1k3
Notice how we can represent this problem using numbers. For each of the middle 6 numbers, the value of it can be split between the 2 values next to it on the next round, but for the edges, all of it goes to the one next to it, because it has 1 neighbor. Let’s write some code to simulate the problem:
start = [1, 1, 1, 1, 1, 1, 1, 1]
nex = [1, 1, 1, 1, 1, 1, 1, 1]
a = [1, 1, 2, 3, 4, 5, 6, 6]
for j in range(8):
start[a[j]] = 0
sum = 0
for i in range(8):
if i == 0:
nex[0] = start[1]/2
elif i == 7:
nex[7] = start[6]/2
elif i == 1:
nex[1] = start[0] + start[2]/2
elif i == 6:
nex[6] = start[7] + start[5]/2
else:
nex[i] = start[i-1]/2 + start[i+1]/2
sum += nex[i]
print(nex)
print(sum)
for i in range(8):
start[i] = nex[i]
print(200*(1-(sum/8)))
Cool! Now that we have code to simulate it, and is pretty fast, let’s bash all possible meaningful inputs (half of the inputs are equivalent). This gives us 4*8^7 possibilities to bash.
start = [1, 1, 1, 1, 1, 1, 1, 1]
nex = [1, 1, 1, 1, 1, 1, 1, 1]
old = 0
for i in range(4):
for j in range(8):
for k in range(8):
for l in range(8):
for m in range(8):
for n in range(8):
for o in range(8):
for p in range(8):
start = [1, 1, 1, 1, 1, 1, 1, 1]
nex = [1, 1, 1, 1, 1, 1, 1, 1]
a = [i, j, k, l, m, n, o, p]
for q in range(8):
start[a[q]] = 0
sum = 0
for r in range(8):
if r == 0:
nex[0] = start[1]/2
elif r == 7:
nex[7] = start[6]/2
elif r == 1:
nex[1] = start[0] + start[2]/2
elif r == 6:
nex[6] = start[7] + start[5]/2
else:
nex[r] = start[r-1]/2 + start[r+1]/2
sum += nex[r]
for s in range(8):
start[s] = nex[s]
c = (200*(1-(sum/8)))
if c > old:
print(a)
print(c)
old = c
c = 0
After a few minutes, the program spits out [3, 6, 1, 4, 4, 1, 6, 3], with an average value of 179.6875. This appears to be the optimal solution.
Plugging it into some pwntools code, we can wait for the ~2.5% chance that we will succeed.
from pwn import *
io = remote("tunnels.hsctf.com", 1337)
io.recvline()
success = 0
guesses = input() # input guess sequence e.g. "12345678"
for j in range(200):
io.recvline()
print("TRIAL: %d" % j)
for i in range(8):
io.sendline(guesses[i].encode())
r = io.recvline()
if b"incorrect" not in r:
success += 1
break
print("success rate: " + str(success/200))
print(io.recv())
After a few minutes of running this in a loop, we find the flag in the console: flag{b4om1k3_15_4_v3ry_1nt3r35t1ng_p3r50n_924972020}