Roman Hergenreder 4 months ago
parent
commit
ab7d3f8f8c
5 changed files with 96 additions and 0 deletions
  1. BIN
      Day 24/HV23
  2. 95 0
      Day 24/decode.py
  3. BIN
      Day 24/qr_code.png
  4. 1 0
      Day 24/s/STARTUP-SEQUENCE
  5. BIN
      Day 24/santas-shuffled-surprise.adf

BIN
Day 24/HV23


+ 95 - 0
Day 24/decode.py

@@ -0,0 +1,95 @@
+import struct
+from hackingscripts import util
+from PIL import Image
+from pyzbar.pyzbar import decode
+
+def bit_stream_to_qr(bit_stream, qr_size=(29, 32), pix_size=10):
+    img = Image.new("RGB", (qr_size[1] * pix_size, qr_size[0] * pix_size))
+    pix = img.load()
+
+    columns = ["" for r in range(qr_size[1])]
+    for i, b in enumerate(bit_stream):
+        columns[i % qr_size[1]] += b
+
+    for ci, column in enumerate(columns):
+        for ri, b in enumerate(column):
+            color = (0,0,0) if b == "1" else (255,255,255)
+            for xi in range(pix_size):
+                for yi in range(pix_size):
+                    pix[ci*pix_size+xi,ri*pix_size+yi] = color
+
+    return img
+
+def apply_scramble(data, loop_count, shift_direction, shift_type_1, shift_type_2):
+    for i in range(loop_count):
+        if shift_direction == 0:
+            if shift_type_1 != -1:
+                offset = 0x70 + shift_type_1
+                value = data[offset]
+                for x in range(0x1c+1):
+                    data[offset] = data[offset - 4]
+                    offset -= 4
+                data[offset + 4] = value
+            if shift_type_2 != -1:
+                offset = shift_type_2 * 4
+                value = data[offset]
+                for x in range(3+1):
+                    data[offset] = data[offset + 1]
+                    offset += 1
+                data[offset - 1] = value 
+        elif shift_direction == 1:
+            if shift_type_2 != -1:
+                offset = 3 + shift_type_2 * 4
+                value = data[offset]
+                for x in range(3+1):
+                    data[offset] = data[offset - 1]
+                    offset -= 1
+                data[offset + 1] = value
+            if shift_type_1 != -1:
+                offset = shift_type_1
+                value = data[offset]
+                for x in range(0x1c + 1):
+                    data[offset] = data[offset + 4]
+                    offset += 4
+                data[offset - 4] = value
+        else:
+            raise
+    return data
+
+def bytes_to_bit_stream(data, qr_size=(29, 32)):
+    bit_stream = ""
+    for v in data:
+        bit_stream += util.lpad(bin(v)[2:], 8, "0")
+    bit_stream = bit_stream[0:qr_size[0] * qr_size[1]]
+    return bit_stream
+
+if __name__ == "__main__":
+
+    with open("HV23", "rb") as f:
+        prog_data = f.read()
+
+    QR_DATA = bytearray(prog_data[0x8a3e:0x8a3e+0x70+7])
+    SCRAMBLE_DATA = prog_data[0x628:0x628+0x60]
+    NUM_SCRAMBLES = 0x18
+    assert len(SCRAMBLE_DATA) == NUM_SCRAMBLES * 4
+
+    scrambles = []
+    for scramble in range(0, NUM_SCRAMBLES*4, 4):
+        scramble_data = SCRAMBLE_DATA[scramble:scramble+4]
+        shift_type_2, shift_type_1, loop_count, shift_direction = struct.unpack("bbBB", scramble_data)
+        scrambles.append((loop_count, shift_direction, shift_type_1, shift_type_2))
+
+    data = QR_DATA
+    while True:
+        for scramble in scrambles:
+            data = apply_scramble(data, *scramble)
+            bit_stream = bytes_to_bit_stream(data)
+
+            # last 3 columns are all white? we might have a valid QR-code
+            if all(bit_stream[row*32+29:row*32+32] == "000" for row in range(29)):
+                img = bit_stream_to_qr(bit_stream)
+                decoded_objects = decode(img)
+                if decoded_objects:
+                    img.save(f"qr_code.png")
+                    print("[+] Flag:", decoded_objects[0].data.decode())
+                    exit()

BIN
Day 24/qr_code.png


+ 1 - 0
Day 24/s/STARTUP-SEQUENCE

@@ -0,0 +1 @@
+sys:HV23

BIN
Day 24/santas-shuffled-surprise.adf