Skip to content

Instantly share code, notes, and snippets.

@TrebledJ
Created September 20, 2023 13:03
Show Gist options
  • Save TrebledJ/bea5665f3cd340997ff60e069558e80d to your computer and use it in GitHub Desktop.
Save TrebledJ/bea5665f3cd340997ff60e069558e80d to your computer and use it in GitHub Desktop.
Solve scripts for HITCON 2023 The Blade. Writeup: https://trebledj.github.io/posts/hitcon-2023-the-blade
# HITCON 2023 – The Blade
# Solve Script by TrebledJ
# WriteUp: https://trebledj.github.io/posts/hitcon-2023-the-blade
import string
###############
### Part 1. ###
###############
p = string.ascii_letters + string.digits + '+/'
assert len(p) == 64
# print(p)
permuted = 'Rp5v+AZmM8XWy1sgNhTB/oCzYVdPrGn6KD3Q9lke4qtFxHb0uUOcS2jIEJfL7aiw'[:64]
perm = [0] * 64 # Permutation .
rperm = [0] * 64 # Reverse permutation.
for i, c in enumerate(p):
j = permuted.index(c)
perm[i] = j
rperm[j] = i
###############
### Part 2. ###
###############
# Values obtained with `x/16wx 0x5555555d63e0`.
# Values before mapping.
dst = """
0x5555555d63e0: 0x76357052 0x6d5a412b 0x5758384d 0x67733179
0x5555555d63f0: 0x4254684e 0x7a436f2f 0x50645659 0x366e4772
0x5555555d6400: 0x5133444b 0x656b6c39 0x46747134 0x30624878
0x5555555d6410: 0x634f5575 0x496a3253 0x4c664a45 0x77696137
0x5555555d63e0: 0x04050607 0x00010203 0x0c0d0e0f 0x08090a0b
0x5555555d63f0: 0x14151617 0x10111213 0x1c1d1e1f 0x18191a1b
0x5555555d6400: 0x24252627 0x20212223 0x2d2e3a3b 0x28292a2c
0x5555555d6410: 0x405b5c5d 0x3c3d3e3f 0x7c7d7e7f 0x5e5f607b
0x5555555d63e0: 0x84858687 0x80818283 0x8c8d8e8f 0x88898a8b
0x5555555d63f0: 0x94959697 0x90919293 0x9c9d9e9f 0x98999a9b
0x5555555d6400: 0xa4a5a6a7 0xa0a1a2a3 0xacadaeaf 0xa8a9aaab
0x5555555d6410: 0xb4b5b6b7 0xb0b1b2b3 0xbcbdbebf 0xb8b9babb
0x5555555d63e0: 0xc4c5c6c7 0xc0c1c2c3 0xcccdcecf 0xc8c9cacb
0x5555555d63f0: 0xd4d5d6d7 0xd0d1d2d3 0xdcdddedf 0xd8d9dadb
0x5555555d6400: 0xe4e5e6e7 0xe0e1e2e3 0xecedeeef 0xe8e9eaeb
0x5555555d6410: 0xf4f5f6f7 0xf0f1f2f3 0xfcfdfeff 0xf8f9fafb
"""
# Values after mapping.
mpd = """
0x5555555d63e0: 0x2e616c58 0xe2cb3269 0xa002e0b3 0xc16b1c86
0x5555555d63f0: 0xd2799cec 0x74d9c29e 0x9f043b0c 0xed14031e
0x5555555d6400: 0xca978fa2 0x39a4d8da 0xaf7e645b 0x0f71930b
0x5555555d6410: 0x0a81fd99 0x3aef66b7 0xe1ff00ee 0x09ab75ad
0x5555555d63e0: 0x51158ddb 0xfb7b4ebb 0xaab260eb 0xb0aca58e
0x5555555d63f0: 0x2bc6a635 0x635cde42 0xbd24b1e3 0x3043d65f
0x5555555d6400: 0x7c6d8b17 0x8ca7d52a 0x59a92706 0x9d83fe10
0x5555555d6410: 0x41a880c0 0x25dc5ee7 0xc42d4ff9 0x164d2f6a
0x5555555d63e0: 0x896f5de8 0xfa94b61f 0x88c57f77 0xeab55a65
0x5555555d63f0: 0x3ff44847 0x11cff11b 0xe9626eb4 0x12e4badf
0x5555555d6400: 0x4b28d7d1 0x96cd1353 0x2c9b2944 0x33b8e67a
0x5555555d6410: 0x31d3b940 0x52f720f2 0x1a01a192 0xd034f554
0x5555555d63e0: 0xddbc19f3 0xfc8507be 0x4c7dc7d4 0x36f67298
0x5555555d63f0: 0x8ae55046 0x454a9ac3 0xc90e3c57 0xcc687667
0x5555555d6400: 0x840d90a3 0xf022bf26 0x91058770 0xae3d1dc8
0x5555555d6410: 0x553e3723 0x08732149 0x389578f8 0x1856ce82
"""
def mkbytes(s):
return [int(bs[2*(i+1):2*(i+2)], 16) for l in s.strip().split('\n') if l.strip() for bs in l.split(': ')[1].split() for i in range(4)]
dbytes = mkbytes(dst)
mbytes = mkbytes(mpd)
mp = [0]*256 # Value map.
rmp = [0]*256 # Reverse value map.
for a, b in zip(dbytes, mbytes):
mp[a] = b
rmp[b] = a
# Assert bijection.
assert len(mp) == len(rmp) == 256
def apply_rmp(bs):
"""Applies one iteration of the reverse map"""
return bytes([rmp[b] for b in bs])
def apply_rperm(bs):
"""Applies one iteration of reverse permutation"""
out = [0]*64
for i, j in enumerate(perm):
out[i] = bs[j]
return bytes(out)
def apply_mp(bs):
"""Applies one iteration of the forward map"""
return bytes([mp[b] for b in bs])
def apply_perm(bs):
"""Applies one iteration of forward permutation"""
out = [0]*64
for i, j in enumerate(perm):
out[j] = bs[i]
return bytes(out)
###############
### Part 3. ###
###############
"""
cb: b8 ef be ad de mov eax, 0xdeadbeef
d0: 44 01 e0 add eax, r12d
d3: 44 31 e8 xor eax, r13d
d6: c1 c8 0b ror eax, 0xb
d9: f7 d0 not eax
db: 44 31 f0 xor eax, r14d ; eax = ~(roll(0xb, (0xDEADBEEF + r12) ^ r13)) ^ r14
de: 3d ef be ad de cmp eax, 0x526851A7
"""
def ror(x, n):
left = x >> n
right = (x & (0xFFFFFFFF >> (32 - n))) << (32 - n)
return right | left
def neg(x):
assert x >= 0
return int(''.join('01'[c == '0'] for c in f'{x:032b}'), 2)
def shelldec(b):
"""Reverse shellcode encryption (decryption)."""
assert b >= 0
return ((ror(neg(b ^ r14), 32 - 0xb) ^ r13) - r12) % 2**32
r12 = 0x464c457f
r13 = 0x746f6f72
r14 = 0x31f3831f
byteorder = 'little'
encrypted = [0x526851a7, 0x31ff2785, 0xc7d28788, 0x523f23d3, 0xaf1f1055, 0x5c94f027, 0x797a3fcd, 0xe7f02f9f, 0x3c86f045, 0x6deab0f9, 0x91f74290, 0x7c9a3aed, 0xdc846b01, 0x743c86c, 0xdff7085c, 0xa4aee3eb,]
decrypted = [shelldec(u) for u in encrypted]
def shellenc(a):
"""Forward shellcode encryption."""
assert a >= 0
u32 = lambda x: x & 0xFFFFFFFF
return neg(ror(u32(a + r12) ^ r13, 0xb)) ^ r14
assert encrypted == [shellenc(v) for v in decrypted]
####################
### All Together ###
####################
bs = b''.join(u.to_bytes(4, byteorder) for u in decrypted)
for i in range(256):
bs = apply_rmp(bs)
bs = apply_rperm(bs)
assert bs == b'hitcon{<https://soundcloud.com/monstercat/noisestorm-crab-rave>}'
print(bs.decode())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment