From 6e7258c89f0ad842d8dc9978cf65ad2a59698453 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Mon, 6 Feb 2017 17:21:44 +1030 Subject: [PATCH] Generate the final code! --- electric_boogaloo.md | 67 +++++++++++++++++++++++++++++++++++++++++ tools/generate_codes.py | 2 +- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/electric_boogaloo.md b/electric_boogaloo.md index 1d59cde..717de91 100644 --- a/electric_boogaloo.md +++ b/electric_boogaloo.md @@ -276,3 +276,70 @@ for i in range(len(data_69de)): ``` The result is `0b3b`. + +On to the final code, now: the vault lock. At `1679`, `R1` is computed as `([0f73] ^ [0f74]) ^ [0f75]`. Searching the code for references to these, we find: + + 1236 wmem 0f70 0016 // weight + 1239 wmem 0f71 0000 // counter + 123c wmem 0f72 0000 + 123f wmem 0f73 0000 + 1242 wmem 0f74 0000 + 1245 wmem 0f75 0000 + +It would be nice if these were just the intermediate weights of the orb, but alas the algorithm appears more complex than that. + +Nevertheless, unravelling the various functions which reference those memory addresses: + +```python +counter = 0 +data_0f73 = 0 +data_0f74 = 0 +data_0f75 = 0 + +# 08c8 +def rotatey_thing(R1, R2): + while R2 != 0: + R2 = (R2 + 0x7fff) % 0x8000 + R3 = R1 & 0x4000 + R1 = (R1 * 0x0002) % 0x8000 + if R3 == 0: + continue + R1 = R1 | 0x0001 + return R1 + +# 11a3 +def mutate(R1val, R2, R3): + return rotatey_thing(R1val, R2) ^ R3 + +# 1135 +def update(value, room): + global counter, data_0f73, data_0f74, data_0f75 + + if counter <= 0x752f: + counter += 1 + data_0f73 = mutate(data_0f73, counter + 2, room) + data_0f74 = mutate(data_0f74, counter * counter, room * room) + data_0f75 = mutate(data_0f75, 0x000d, (value * 9) * (value * 9)) + +update(0x0000, 0x0008) # north 1000 +update(0x0004, 0x0009) # east 1011 +update(0x0001, 0x000a) # east 1022 +update(0x000b, 0x0006) # north 0fde +update(0x0002, 0x0005) # west 0fcd +update(0x0004, 0x0009) # south 1011 +update(0x0001, 0x000a) # east 1022 +update(0x0012, 0x000b) # east 1033 +update(0x0001, 0x000a) # west 1022 +update(0x000b, 0x0006) # north 0fde +update(0x0001, 0x0002) # north 0f98 +update(0x0001, 0x0003) # east 0fa9 +print(data_0f73) +print(data_0f74) +print(data_0f75) + +result = (data_0f73 ^ data_0f74) ^ data_0f75 + +print('0x{:04x}'.format(result)) +``` + +And with that, we can now programmatically generate every code for any challenge binary! diff --git a/tools/generate_codes.py b/tools/generate_codes.py index f07717f..22f0a85 100755 --- a/tools/generate_codes.py +++ b/tools/generate_codes.py @@ -70,7 +70,7 @@ CODE_PARAMS = [ (0x1092, 0x650a, 0x7fff, 0x6eed), (0x6486, 0x650a, 0x7fff, 0x7239), # R1 is R8 from Ackermann (0x0b3b, 0x650a, 0x7fff, 0x73df), # R1 from the dots on the coins - # 1691 is a bit tricky + (0x7714, 0x653f, 0x0004, 0x74f6), # R1 based on solution to vaults ] for cp in CODE_PARAMS: