“He wrote everything. You just forgot he was there.”
This challenge is a keystroke log disguised as a plain hex dump. The goal is to reconstruct what was typed and extract the flag.
dump.hex contains PC keyboard scancodes (Set 1):
< 0x80press + 0x80
0x1E (press a) and 0x9E (release a)You’ll also see modifier scancodes such as Shift:
0x2A / 0xAA0x36 / 0xB60x3A (toggle on press)So the “scribe” wrote everything — we just need to decode it.
shift = True/Falsecaps = True/False (toggled by Caps Lock press)>= 0x80), except Shift releases which matter for state.unshift map for normal typingshifted map for Shift held (symbols / uppercase)0x0E) by removing the last output character.nexus{...} and pick the real flag (there are decoys).Save as solve.py next to dump.hex and run with Python 3.
import re
from pathlib import Path
# Scancode Set 1 lookup tables (common keys)
unshift = {
0x02:'1',0x03:'2',0x04:'3',0x05:'4',0x06:'5',0x07:'6',0x08:'7',0x09:'8',0x0A:'9',0x0B:'0',
0x0C:'-',0x0D:'=',
0x0F:'\t',
0x10:'q',0x11:'w',0x12:'e',0x13:'r',0x14:'t',0x15:'y',0x16:'u',0x17:'i',0x18:'o',0x19:'p',
0x1A:'[',0x1B:']',0x1C:'\n',
0x1E:'a',0x1F:'s',0x20:'d',0x21:'f',0x22:'g',0x23:'h',0x24:'j',0x25:'k',0x26:'l',
0x27:';',0x28:"'",0x29:'`',0x2B:'\\',
0x2C:'z',0x2D:'x',0x2E:'c',0x2F:'v',0x30:'b',0x31:'n',0x32:'m',
0x33:',',0x34:'.',0x35:'/',0x39:' '
}
shifted = {
0x02:'!',0x03:'@',0x04:'#',0x05:'$',0x06:'%',0x07:'^',0x08:'&',0x09:'*',0x0A:'(',0x0B:')',
0x0C:'_',0x0D:'+',
0x0F:'\t',
0x10:'Q',0x11:'W',0x12:'E',0x13:'R',0x14:'T',0x15:'Y',0x16:'U',0x17:'I',0x18:'O',0x19:'P',
0x1A:'{',0x1B:'}',0x1C:'\n',
0x1E:'A',0x1F:'S',0x20:'D',0x21:'F',0x22:'G',0x23:'H',0x24:'J',0x25:'K',0x26:'L',
0x27:':',0x28:'"',0x29:'~',0x2B:'|',
0x2C:'Z',0x2D:'X',0x2E:'C',0x2F:'V',0x30:'B',0x31:'N',0x32:'M',
0x33:'<',0x34:'>',0x35:'?',0x39:' '
}
def decode(scancodes):
out = []
shift = False
caps = False
for b in scancodes:
# Shift press/release
if b in (0x2A, 0x36):
shift = True
continue
if b in (0xAA, 0xB6):
shift = False
continue
# Caps Lock toggles on press
if b == 0x3A:
caps = not caps
continue
# Ignore releases
if b >= 0x80:
continue
# Backspace
if b == 0x0E:
if out:
out.pop()
continue
# Choose table by shift state
table = shifted if shift else unshift
ch = table.get(b, '')
# Caps Lock affects letters (caps XOR shift behavior)
if ch.isalpha():
ch = ch.upper() if (caps ^ shift) else ch.lower()
out.append(ch)
return ''.join(out)
raw = Path("dump.hex").read_text().split()
sc = [int(x, 16) for x in raw]
text = decode(sc)
print(text)
flags = re.findall(r"nexus\{[^}\n\r]+\}", text)
print("\nFound flags:", flags)
Running the solver on the provided dump yields three nexus{...} strings:
nexus{n0t_th3_f14g_k33p_l00k1ng_babe} (decoy)nexus{f4k3_fl4g_f0r_th3_l0lz_gg_wp} (decoy)nexus{1_c4ptur3d_k3y5_wh1l3_w4tch1ng_m3551}nexus{1_c4ptur3d_k3y5_wh1l3_w4tch1ng_m3551}