From 86bcc094faf4cfbfb896d5362f615ff8690bac4d Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Sun, 12 Feb 2017 22:43:28 +1030 Subject: [PATCH] Port debug scripts to new API --- .gitignore | 2 ++ README.md | 8 +++--- dbg_dump.py => dbg/dump.py | 10 +++---- dbg_pdb.py => dbg/fastboot.py | 10 ++++++- dbg_load.py => dbg/load.py | 10 +++---- dbg_speedrun.py => dbg/speedrun.py | 11 -------- dbg_teleporter.py => dbg/teleporter.py | 6 ++-- dbg_fastboot.py | 39 -------------------------- libsynacor/bytecode.py | 8 +++++- notes.md | 6 ++-- synacor.py | 5 ++++ 11 files changed, 43 insertions(+), 72 deletions(-) rename dbg_dump.py => dbg/dump.py (86%) rename dbg_pdb.py => dbg/fastboot.py (81%) rename dbg_load.py => dbg/load.py (84%) rename dbg_speedrun.py => dbg/speedrun.py (87%) rename dbg_teleporter.py => dbg/teleporter.py (89%) delete mode 100644 dbg_fastboot.py diff --git a/.gitignore b/.gitignore index 98bb947..ba27fb4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ /tools/ackermann.o /tools/venv /tools/*.pdf + +__pycache__ diff --git a/README.md b/README.md index 29d6345..be48290 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # synacor.py -My sort-of-OOP, ~~poorly-documented~~concise response to the Synacor challenge +My OOP, ~~poorly-documented~~ ~~concise~~ working response to the Synacor challenge ## Debug commands @@ -12,15 +12,15 @@ This will execute the file `.py` with `dbg_args[0]` set to `` and ` + ./synacor.py For example, to load the `dumps/init` state to skip the self-test and decryption, run: - ./synacor.py dbg_load dumps/init + ./synacor.py challenge.bin dbg/load dumps/init Dump files are stored in Python [pickle](https://docs.python.org/3/library/pickle.html) format, so if you want to inspect the memory in a hex editor, for example, it will be necessary to extract a raw memory dump: diff --git a/dbg_dump.py b/dbg/dump.py similarity index 86% rename from dbg_dump.py rename to dbg/dump.py index 89acbb2..0b562f7 100644 --- a/dbg_dump.py +++ b/dbg/dump.py @@ -1,5 +1,5 @@ # synacor.py - An implementation of the Synacor Challenge -# Copyright © 2016 RunasSudo +# Copyright © 2016–2017 RunasSudo # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -20,10 +20,10 @@ if len(dbg_args) < 2: print('Usage: .{} '.format(dbg_args[0])) else: model = { - 'SYN_PTR': SYN_PTR, - 'SYN_MEM': SYN_MEM, - 'SYN_REG': SYN_REG, - 'SYN_STK': SYN_STK + 'SYN_PTR': cpu.SYN_PTR, + 'SYN_MEM': cpu.SYN_MEM, + 'SYN_REG': cpu.SYN_REG, + 'SYN_STK': cpu.SYN_STK } with open(dbg_args[1], 'wb') as f: diff --git a/dbg_pdb.py b/dbg/fastboot.py similarity index 81% rename from dbg_pdb.py rename to dbg/fastboot.py index aa9dc03..41c7750 100644 --- a/dbg_pdb.py +++ b/dbg/fastboot.py @@ -14,4 +14,12 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -DBG_FLAG = True +# Emulate 06bb +for R1 in range(0x17b4, 0x7562): + R0 = cpu.SYN_MEM[R1] + R0 ^= pow(R1, 2, 32768) + R0 ^= 0x4154 + cpu.SYN_MEM[R1] = R0 + +# Jump past self-test +cpu.SYN_PTR = 0x0377 diff --git a/dbg_load.py b/dbg/load.py similarity index 84% rename from dbg_load.py rename to dbg/load.py index 0e46501..a2d4c8f 100644 --- a/dbg_load.py +++ b/dbg/load.py @@ -1,5 +1,5 @@ # synacor.py - An implementation of the Synacor Challenge -# Copyright © 2016 RunasSudo +# Copyright © 2016–2017 RunasSudo # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -22,7 +22,7 @@ else: with open(dbg_args[1], 'rb') as f: model = pickle.load(f) - SYN_PTR = model['SYN_PTR'] - SYN_MEM = model['SYN_MEM'] - SYN_REG = model['SYN_REG'] - SYN_STK = model['SYN_STK'] + cpu.SYN_PTR = model['SYN_PTR'] + cpu.SYN_MEM = model['SYN_MEM'] + cpu.SYN_REG = model['SYN_REG'] + cpu.SYN_STK = model['SYN_STK'] diff --git a/dbg_speedrun.py b/dbg/speedrun.py similarity index 87% rename from dbg_speedrun.py rename to dbg/speedrun.py index a1dccf9..6807120 100644 --- a/dbg_speedrun.py +++ b/dbg/speedrun.py @@ -97,16 +97,5 @@ take mirror use mirror """ -# Read code into memory -SYN_PTR = 0 -with open('challenge.bin', 'rb') as data: - while True: - byteData = data.read(2) - if len(byteData) < 2: - break - SYN_MEM[SYN_PTR] = struct.unpack('. # Set R7 to 6486 -SYN_REG[7] = 0x6486 +cpu.SYN_REG[7] = 0x6486 # Patch instructions 1571 to 1579 inclusive with nop's -SYN_MEM[0x1571:0x157a] = [21] * 9 +cpu.SYN_MEM[0x1571:0x157a] = [21] * 9 print('Patched. Ready to run "use teleporter".') diff --git a/dbg_fastboot.py b/dbg_fastboot.py deleted file mode 100644 index 44b686b..0000000 --- a/dbg_fastboot.py +++ /dev/null @@ -1,39 +0,0 @@ -# synacor.py - An implementation of the Synacor Challenge -# Copyright © 2017 RunasSudo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -import pickle - -# Read code into memory -SYN_MEM = [0] * 32768 - -with open('challenge.bin', 'rb') as data: - i = 0 - while True: - byteData = data.read(2) - if len(byteData) < 2: - break - SYN_MEM[i] = struct.unpack(' dumps/init.asm @@ -232,7 +232,7 @@ Running the algorithm, the correct value is revealed to be `0x6486`. Now we simp I've implemented this as a debug function to prepare the teleporter: - > .dbg_teleporter + > .dbg/teleporter Patched. Ready to run "use teleporter". > use teleporter @@ -284,4 +284,4 @@ Given that you've made it this far (You didn't cheat, did you? I did warn you at Now that we've solved the puzzle, the only thing left is to write a [tool-assisted speed-run](https://github.com/RunasSudo/synacor.py/blob/master/dbg_speedrun.py) to completely break any given instance of the challenge in 5 seconds. - time python -u synacor.py dbg_speedrun | head -n 849 + time python -u synacor.py challenge.bin dbg/speedrun | head -n 849 diff --git a/synacor.py b/synacor.py index db96583..1d23249 100755 --- a/synacor.py +++ b/synacor.py @@ -23,5 +23,10 @@ cpu = CPU() with open(sys.argv[1], 'rb') as data: cpu.SYN_MEM = memory_from_file(data) +if len(sys.argv) > 2: + dbg_args = sys.argv[2:] + with open(dbg_args[0] + '.py', 'r') as f: + exec(f.read(), globals(), locals()) + while True: cpu.step()