script me
https://gyazo.com/28cfe5bf6b048f41614630019a2c915f
Problem:
Can you understand the language and answer the questions to retrieve the flag? Connect to the service with nc 2018shell2.picoctf.com 8672
Hint:
Maybe try writing a python script?
code:sh
Rules:
Example:
(()) + () = () + (()) = (()())
Let's start with a warmup.
() + (()()) = ???
解読のために人に読みやすい形に変換する
()の中に()があるものを数字に置き換えていく
((((())))) => 5
(((()))(())) => (32)
三十二ではなく、3と2
適当に高を括って、()のネストが9より多いことはないと想定した
code:main.py
def decode(s):
s = s.replace('()', '1')
for i in range(1, 10):
if ('(' + str(i) + ')') not in s:
break
s = s.replace('(' + str(i) + ')', str(i+1))
return s
def encode(s):
for i in range(1, 10):
s = s.replace(str(i), ('(' * i) + (')' * i))
return s
absorbする側 と される側 を判定するcompare(left, right)が大切
調査の結果、(と)の数によって強弱が判定されていたっぽい
e.g. (((123)421)62)
A = (123), B = (A421), C = (B62)
Aは3、Bは2、Cは1のネストにいるので、それぞれに加算していく
()を除くと456 643 73となり、一番大きい7が強さとなる
数字が大きい方が小さい方を吸収する
数字が同じ場合はcombineする
code:compare.py
def compare(left, right):
if left == right:
return 'same'
l_power = calc_power(left)
r_power = calc_power(right)
if l_power > r_power:
return 'left'
if l_power < r_power:
return 'right'
return 'same'
def calc_power(statement):
count = 0
power = 0
for c in statement:
if c == '(':
count = count + 1
elif c == ')':
count = count - 1
else:
power = max(power, int(c) + count)
return power
長過ぎる標準出力を受け取るのにめっちゃ手こずった...
https://gyazo.com/0a975ccc368cd37501318e6750425241
出題が長すぎて、問題が2回に分けられて送られてきていた
気づかないままずっと施行していたら、最後の問題だけ解けないという場面に遭遇してしまった
最終的には結構ゴリ押した
=> が入っていない
(と)が入っている
(()) + () = () + (()) = (()())が入っていない
Exampleの行がごまかすのが面倒だった
= ???を含んでいたらそこで問題完結と見做す
code:script_me.py
from netcat import Netcat
from compare import compare
def decode(s):
s = s.replace('()', '1')
for i in range(1, 10):
if ('(' + str(i) + ')') not in s:
break
s = s.replace('(' + str(i) + ')', str(i+1))
return s
def encode(s):
for i in range(1, 10):
s = s.replace(str(i), ('(' * i) + (')' * i))
return s
def main():
nc = Netcat('2018shell2.picoctf.com', 8672)
code = ''
for i in range(15):
lines = nc.read().decode('utf-8').split('\n')
statement = []
for line in lines:
if ('Expected => ' in line):
print('\nExpected => ' + decode(line.lstrip('Expected => ').replace(' ', '').replace('\n', '')))
continue
if ('Actual => ' in line):
print('Actual => ' + decode(line.lstrip('Actual => ').replace(' ', '').replace('\n', '')))
continue
if (' => ' not in line) and ('(' in line) and (')' in line) and ('(()) + () = () + (()) = (()())' not in line):
print(line + '\n')
code = code + line
continue
print(line)
if ' = ???' not in code:
continue
code = code.rstrip(' = ???')
statement = decode(code).split(' + ')
code = ''
if len(statement) == 1:
continue
left_stack = ''
while len(statement) != 1:
left = statement.pop(0)
stronger = compare(left, right)
left = encode(left)
right = encode(right)
calculated = ''
if stronger == 'same':
calculated = right
left_stack = left_stack + left
elif stronger == 'left':
calculated = left:-1 + right + ')' elif stronger == 'right':
calculated = '(' + left_stack + left + right1: left_stack = ''
statement0 = decode(calculated) # print(decode(left) + ' + ' + decode(right) + ' (' + stronger + ') = ' + statement0) print(left_stack + encode(statement0)) nc.write(left_stack + encode(statement0)) nc.close()
if __name__ == '__main__':
main()
$ python3 script_me.py
Flag: picoCTF{5cr1pt1nG_l1k3_4_pRo_0970eb2d}