Volga CTF. Ppc300 Mathproblem - right up
Task:
mathproblem
nc mathproblem.2015.volgactf.ru 8888
After connect we see following:
Greetings, neonate! Let us check if you can solve one particular problem!<br>
You're given a set of integer numbers x0,x1,...,xn and y. Using parenthesis '(' and ')' and regular arithmetic operations '*','/','+','-' over integer numbers you need to find a mathematical expression that involves each and every xi and evaluates to y. Sending the correct expression advances you to the next round.
E.g. if the problem says '137 421 700 746 equals 1395' your solution may look like this '(700-421)*(746/137)'.
N.b. Division operation is done according to regular integer division rules, so 746/137 == 5 and (700-421)*(746/137) != (700-421)*746/137.
Code:
import math
import socket
import itertools
from time import sleep
def mathpr():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("mathproblem.2015.volgactf.ru", 8888))
data = s.recv(1024)
print data
while 1:
sleep(0.1)
data = s.recv(1024)
print data
var = data.split('Solve!\n')
var = var[1].split(' equals ')
nums = var[0].split(' ')
for n in range(4):
nums[n] = int(nums[n], 10)
res = var[1]
num = list(itertools.permutations([nums[0], nums[1], nums[2], nums[3]]))
ops = list(itertools.product(['+', '-', '*', '/'], repeat=3))
por = list(itertools.permutations([0, 1, 2]))
print res
print num
print ops
print por
for n in num:
for o in ops:
for p in por:
curN = list(n)
curO = list(o)
curP = list(p)
for i in range(3):
curOpNum = curP.index(0)
n1 = curN[curOpNum]
n2 = curN[curOpNum + 1]
resN = 0
if curO[curOpNum] == '*':
resN = n1 * n2
if curO[curOpNum] == '/':
if n2 == 0:
break
resN = n1 / n2
if curO[curOpNum] == '-':
resN = n1 - n2
if curO[curOpNum] == '+':
resN = n1 + n2
curN[curOpNum] = resN
curN.pop(curOpNum + 1)
curO.pop(curOpNum)
curP.pop(curOpNum)
for b in range(len(curP)):
curP[b] -= 1
if int(res) == int(curN[0]):
numZero = list(p).index(0)
resres = '(' + str(n[numZero]) + o[numZero] + str(n[numZero + 1]) + ')'
numOne = list(p).index(1)
if math.fabs(numOne - numZero) == 2:
resres2 = '(' + str(n[numOne]) + o[numOne] + str(n[numOne + 1]) + ')'
if (numOne > numZero):
resres = resres + o[list(p).index(2)] + resres2
else:
resres = resres2 + o[list(p).index(2)] + resres
else:
if (numOne > numZero):
resres = '(' + resres + o[numOne] + str(n[numOne + 1]) + ')'
else:
resres = '(' + str(n[numOne]) + o[numOne] + resres + ')'
numTwo = list(p).index(2)
if (numTwo > numOne):
resres = '(' + resres + o[numTwo] + str(n[numTwo + 1]) + ')'
else:
resres = '(' + str(n[numTwo]) + o[numTwo] + resres + ')'
print resres
s.send(resres)
s.close()
print mathpr()
Earch round it prints next:
# Round 8. Solve!
# 152 680 796 862 equals 796
#
# 796
#
# [(152, 680, 796, 862), (152, 680, 862, 796), (152, 796, 680, 862), (152, 796, 862, 680), (152, 862, 680, 796), (152, 862, 796, 680), (680, 152, 796, 862), (680, 152, 862, 796), (680, 796, 152, 862), (680, 796, 862, 152), (680, 862, 152, 796), (680, 862, 796, 152), (796, 152, 680, 862), (796, 152, 862, 680), (796, 680, 152, 862), (796, 680, 862, 152), (796, 862, 152, 680), (796, 862, 680, 152), (862, 152, 680, 796), (862, 152, 796, 680), (862, 680, 152, 796), (862, 680, 796, 152), (862, 796, 152, 680), (862, 796, 680, 152)]
# [('+', '+', '+'), ('+', '+', '-'), ('+', '+', '*'), ('+', '+', '/'), ('+', '-', '+'), ('+', '-', '-'), ('+', '-', '*'), ('+', '-', '/'), ('+', '*', '+'), ('+', '*', '-'), ('+', '*', '*'), ('+', '*', '/'), ('+', '/', '+'), ('+', '/', '-'), ('+', '/', '*'), ('+', '/', '/'), ('-', '+', '+'), ('-', '+', '-'), ('-', '+', '*'), ('-', '+', '/'), ('-', '-', '+'), ('-', '-', '-'), ('-', '-', '*'), ('-', '-', '/'), ('-', '*', '+'), ('-', '*', '-'), ('-', '*', '*'), ('-', '*', '/'), ('-', '/', '+'), ('-', '/', '-'), ('-', '/', '*'), ('-', '/', '/'), ('*', '+', '+'), ('*', '+', '-'), ('*', '+', '*'), ('*', '+', '/'), ('*', '-', '+'), ('*', '-', '-'), ('*', '-', '*'), ('*', '-', '/'), ('*', '*', '+'), ('*', '*', '-'), ('*', '*', '*'), ('*', '*', '/'), ('*', '/', '+'), ('*', '/', '-'), ('*', '/', '*'), ('*', '/', '/'), ('/', '+', '+'), ('/', '+', '-'), ('/', '+', '*'), ('/', '+', '/'), ('/', '-', '+'), ('/', '-', '-'), ('/', '-', '*'), ('/', '-', '/'), ('/', '*', '+'), ('/', '*', '-'), ('/', '*', '*'), ('/', '*', '/'), ('/', '/', '+'), ('/', '/', '-'), ('/', '/', '*'), ('/', '/', '/')]
# [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
# (((862/680)/152)+796)
After 30 rounds:
# That's incredible! You've passed! Here's your flag: {you_count_as_fast_as_a_calculator}
# Farewell!