Created
September 20, 2023 13:03
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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