Money Money Money
Even after "The Event", money is still the key to beat your opponents. Our scouts found an old banking server which should contain information about the accounts and the money they contain, but this old computer used to use perforated cards. Our engineers were able to create an interface to use it on modern technology, but they are not able to break the security system to get the data.
When connecting, the following information is given :
Initializing 256 bytes RAM... Loading security module into memory...Done Welcome to the truc machine Please insert program card
When entering the example data, the output is “Hello”. Decoding the example data gives a PNG image :
The image contains all black, except on some lines where there is a white pixel. As the description tells, this machine uses punched cards. Looking at the sample image data, we can deduce that the sequence “white-black-black” is the “Print data” opcode. As there are 72 “black-black-black” instructions (which is the ASCII code for ‘H’), this opcode is an “increment value” instruction.
Finding the other instructions is just a mater of time, and there is a total of five instructions that work on a 256 bytes array (pretty much like a brainfuck application)
B-B-B : Increment pointed value B-B-W : Decrement pointed value B-W-B : Increment pointer B-W-W : Decrement pointer W-B-B : Print pointed value
Once you found out which instruction is what (There were a lot of error strings displayed to help), you were able to create an image which would dump the whole memory and display it :
That image would give you the flag :
af5811e325cde9b06c697e61fecb8a094e8e1a85d4231aba1c10c70ca20cdd0f894d121221d0dde4af70a5023a129de2e202192dd7b536eec9965fa99d12b5e1
Source code
[code language=”python”]
import SocketServer, base64
from PIL import Image
from StringIO import StringIO
class MachineHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.request.sendall(‘Initializing 256 bytes RAM…n’)
self.request.sendall(‘Loading security module into memory…’)
memory = bytearray(‘x00’*(256-len(flag))+flag)
self.request.sendall(‘Donen’)
self.request.sendall(‘Welcome to the truc machinen’)
self.request.sendall(‘Please insert program cardn’)
data = self.request.recv(200).strip()
try:
image = self.decodeImage(data)
ops = self.parseImage(image)
self.request.sendall(self.executeOps(ops, memory))
except Exception, e:
self.request.sendall(e.message)
def decodeImage(self, data):
try:
imageData = StringIO(base64.b64decode(data))
image = Image.open(imageData)
if image.size[0]!=3:
raise IOError(“Image width must be equal to 3”)
colors = [c[1] for c in image.getcolors()]
if len(colors)>2:
raise IOError(“Image must be only two colors”)
if 0 not in colors:
raise IOError(“Image must contain #00 color”)
return image
except Exception, e:
raise e
def parseImage(self, image):
i=0
ops = []
try:
for i in range(image.size[1]):
tmp = (image.getpixel((0,i))>0) << 2
tmp += (image.getpixel((1,i))>0) << 1
tmp += (image.getpixel((2,i))>0)
ops.append(tmp)
except Exception, e:
raise e
return ops
def executeOps(self, ops, memory, pt=0):
output=””
for op in ops:
if op == 0:
memory[pt] += 1
elif op == 1:
memory[pt] -= 1
elif op == 2:
if pt == 255:
raise ValueError(“Pointer out of range”)
else:
pt += 1
elif op == 3:
if pt == 0:
raise ValueError(“Pointer out of range”)
else:
pt -= 1
elif op == 4:
output += chr(memory[pt])
else:
raise ValueError(“Unknown opcode”)
return output
if __name__ == ‘__main__’:
flag = open(‘./flag’).read()
HOST, PORT = “0.0.0.0”, 7777
SocketServer.ThreadingTCPServer.allow_reuse_address = True
server = SocketServer.ThreadingTCPServer((HOST, PORT), MachineHandler)
server.serve_forever()
[/code]