Skip to content

Instantly share code, notes, and snippets.

@DavidBuchanan314
Created October 15, 2017 18:26
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save DavidBuchanan314/5bb693803e8fbb4951b4569f76d12160 to your computer and use it in GitHub Desktop.
# Solution to SquareCTF "Seventeen"
# echo -ne "sandflea\n\x00" | python 17.py
import re
import sys
def parse(data):
labels = {}
instructions = []
data = re.sub(r"/\*[^/]*?\*/", "", data.lower())
lines = data.split("\n")
for line in lines:
line = line.strip().split(":")
if len(line) == 1:
instruction = line[0]
else:
assert(len(line) == 2)
label, instruction = line
labels[label] = len(instructions)
if instruction:
instructions += instruction.strip().split(" ")
return instructions, labels
def evaluate(word):
assert(word not in opcodes)
if type(word) is int:
return word
assert(type(word) is str)
if word in labels:
return labels[word]
elif word in variables:
return variables[word]
elif word.isdigit():
return int(word)
else:
exit("Unable to evaluate: {}".format(word))
def getarg():
assert(stack)
return evaluate(stack.pop())
opcodes = [
"read_num",
"read_byte",
"add",
"sub",
"mod",
"store",
"xor",
"call",
"jump",
"vstore",
"vload",
"ifz",
"ifg",
"dup",
"print_byte",
"print_num",
"exit",
]
stack = []
vector = {} # vector is implemented as a dict
variables = {}
lastvar = None
pc = 0
instructions, labels = parse(open("passmgr.17", "r").read())
running = True
while running:
inst = instructions[pc]
#print(stack, repr(inst))
if inst in opcodes:
if inst == "read_num":
stack.append(int(input("NUM: ")))
elif inst == "read_byte":
#print(vector)
stack.append(sys.stdin.buffer.read(1)[0])
elif inst == "print_byte":
sys.stdout.buffer.write(bytes([getarg()]))
elif inst == "print_num":
sys.stdout.buffer.write(str(getarg()).encode())
elif inst == "add":
a = getarg()
b = getarg()
stack.append(a+b)
elif inst == "sub":
a = getarg()
b = getarg()
stack.append(b-a)
elif inst == "mod":
a = getarg()
b = getarg()
stack.append(b%a)
elif inst == "xor":
a = getarg()
b = getarg()
stack.append(b^a)
elif inst == "dup":
stack.append(stack[-1])
elif inst == "store":
varname = stack.pop() # ignore...
varval = getarg()
variables[lastvar] = varval
elif inst == "vstore":
vecval = getarg()
idx = getarg()
vector[idx] = vecval
elif inst == "vload":
stack.append(vector.get(getarg(), 0))
elif inst == "ifz":
la = getarg()
lb = getarg()
val = getarg()
if (val == 0):
pc = lb
else:
pc = la
continue # skip pc increment
elif inst == "ifg":
la = getarg()
lb = getarg()
val = getarg()
#a = getarg()
if (val > 0):
pc = lb
else:
pc = la
continue # skip pc increment
elif inst == "call":
newpc = getarg()
stack.append(pc+1)
pc = newpc
continue # skip pc increment
elif inst == "jump":
pc = getarg()
continue # skip pc increment
elif inst == "exit":
exit() # clean exit
else:
exit("UNIMPLEMENTED: " + inst)
else:
if inst not in labels and not inst.isdigit():
lastvar = inst
#if inst not in variables:
# print(inst)
stack.append(variables.get(inst, 0)) # default 0 ?
else:
stack.append(inst)
pc += 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment