Created
May 4, 2020 16:23
-
-
Save SiD3W4y/619f90ae182564efe65864f9d08e8ad9 to your computer and use it in GitHub Desktop.
keykoolol solving script (FCSC quals 2020)
This file contains hidden or 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
import sys | |
import binascii | |
from pwn import * | |
# AES stuff | |
Sbox = ( | |
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, | |
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, | |
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, | |
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, | |
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, | |
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, | |
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, | |
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, | |
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, | |
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, | |
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, | |
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, | |
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, | |
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, | |
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, | |
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, | |
) | |
InvSbox = ( | |
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, | |
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, | |
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, | |
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, | |
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, | |
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, | |
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, | |
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, | |
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, | |
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, | |
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, | |
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, | |
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, | |
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, | |
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, | |
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D, | |
) | |
xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1) | |
Rcon = ( | |
0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, | |
0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, | |
0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, | |
0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39, | |
) | |
def i128_to_matrix(state): | |
result = [] | |
for i in range(4): | |
line = [] | |
for j in range(4): | |
line.append(state[(i*4)+j]) | |
result.append(line) | |
return result | |
def matrix_to_i128(mat): | |
state = [] | |
for l in mat: | |
for e in l: | |
state.append(e) | |
return state | |
def shift_rows(s): | |
s[0][1], s[1][1], s[2][1], s[3][1] = s[1][1], s[2][1], s[3][1], s[0][1] | |
s[0][2], s[1][2], s[2][2], s[3][2] = s[2][2], s[3][2], s[0][2], s[1][2] | |
s[0][3], s[1][3], s[2][3], s[3][3] = s[3][3], s[0][3], s[1][3], s[2][3] | |
def inv_shift_rows(s): | |
s[0][1], s[1][1], s[2][1], s[3][1] = s[3][1], s[0][1], s[1][1], s[2][1] | |
s[0][2], s[1][2], s[2][2], s[3][2] = s[2][2], s[3][2], s[0][2], s[1][2] | |
s[0][3], s[1][3], s[2][3], s[3][3] = s[1][3], s[2][3], s[3][3], s[0][3] | |
def sub_bytes(s): | |
for i in range(4): | |
for j in range(4): | |
s[i][j] = Sbox[s[i][j]] | |
def inv_sub_bytes(s): | |
for i in range(4): | |
for j in range(4): | |
s[i][j] = InvSbox[s[i][j]] | |
def mix_single_column(a): | |
# please see Sec 4.1.2 in The Design of Rijndael | |
t = a[0] ^ a[1] ^ a[2] ^ a[3] | |
u = a[0] | |
a[0] ^= t ^ xtime(a[0] ^ a[1]) | |
a[1] ^= t ^ xtime(a[1] ^ a[2]) | |
a[2] ^= t ^ xtime(a[2] ^ a[3]) | |
a[3] ^= t ^ xtime(a[3] ^ u) | |
def mix_columns(s): | |
for i in range(4): | |
mix_single_column(s[i]) | |
def inv_mix_columns(s): | |
# see Sec 4.1.3 in The Design of Rijndael | |
for i in range(4): | |
u = xtime(xtime(s[i][0] ^ s[i][2])) | |
v = xtime(xtime(s[i][1] ^ s[i][3])) | |
s[i][0] ^= u | |
s[i][1] ^= v | |
s[i][2] ^= u | |
s[i][3] ^= v | |
mix_columns(s) | |
def add_round_key(s, k): | |
for i in range(4): | |
for j in range(4): | |
s[i][j] ^= k[i][j] | |
def aesenc(state, round_key): | |
state = i128_to_matrix(state) | |
rkey = i128_to_matrix(round_key) | |
shift_rows(state) | |
sub_bytes(state) | |
mix_columns(state) | |
add_round_key(state, rkey) | |
return matrix_to_i128(state) | |
def aesdec(state, round_key): | |
state = i128_to_matrix(state) | |
rkey = i128_to_matrix(round_key) | |
add_round_key(state, rkey) | |
inv_mix_columns(state) | |
inv_sub_bytes(state) | |
inv_shift_rows(state) | |
return matrix_to_i128(state) | |
def serial_copy(serial): | |
s = [] | |
for l in serial: | |
s.append([e for e in l]) | |
return s | |
def key_mix(input_serial): | |
serial = serial_copy(input_serial) | |
for i in range(0x20): | |
backup_key = serial[0].copy() | |
serial[0] = aesenc(serial[5], serial[0]) | |
serial[5] = aesenc(serial[4], serial[7]) | |
serial[4] = aesenc(serial[3], serial[7]) | |
serial[3] = aesenc(serial[2], serial[3]) | |
serial[2] = aesenc(serial[1], serial[6]) | |
serial[1] = aesenc(backup_key, serial[6]) | |
return serial | |
def key_unmix(input_serial): | |
serial = serial_copy(input_serial) | |
for i in range(0x20): | |
bck = aesdec(serial[1], serial[6]) | |
serial[1] = aesdec(serial[2], serial[6]) | |
s3_1 = aesdec(serial[4], serial[7]) | |
serial[2] = aesdec(serial[3], s3_1) | |
serial[3] = s3_1 | |
serial[4] = aesdec(serial[5], serial[7]) | |
serial[5] = aesdec(serial[0], bck) | |
serial[0] = bck | |
return serial | |
def username_expand(username, flip=0): | |
def transform(username, idx, output, count): | |
if len(username) == idx: | |
return | |
for i in range(0x10): | |
r3 = (((ord(username[idx]) + i) * 0xd) ^ 0x25) % 0xff | |
output[(i+count) % 0x10] ^= r3 | |
transform(username, idx+1, output, count+1) | |
output = [0] * 0x80 | |
transform(username, 0, output, 0) | |
output[0x7f] = flip | |
# Expand transform | |
for i in range(0x50): | |
output[i+0x10] = ((output[i] * 3) ^ 0xff) & 0xff | |
return output | |
def to_serial(s): | |
serial = [] | |
for i in range(8): | |
line = [] | |
for j in range(16): | |
line.append(s[(i*16)+j]) | |
serial.append(line) | |
return serial | |
# Serial stuff | |
def serial_for_user(username, flip=0): | |
expanded = to_serial(username_expand(username, flip)) | |
decrypted = matrix_to_i128(key_unmix(expanded)) | |
return binascii.hexlify(bytearray(decrypted)).decode("UTF-8") | |
serial_bin=binascii.unhexlify("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa88888888888888888888888888888888222222222222222222222222222222221111111111111111111111111111111133333333333333333333333333333333bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb00000000000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") | |
SERIAL = [] | |
for i in range(8): | |
line = [] | |
for j in range(16): | |
line.append(serial_bin[(i*16)+j]) | |
SERIAL.append(line) | |
if __name__ == '__main__': | |
p = remote("challenges2.france-cybersecurity-challenge.fr", 3000) | |
i = 0 | |
while True: | |
p.recvuntil("Give me two valid serials for username: ") | |
name = p.readline().strip() | |
log.info("{}: {}".format(i,name)) | |
i += 1 | |
p.sendline(serial_for_user(name)) | |
p.sendline(serial_for_user(name, 1)) | |
if i == 50: | |
break | |
print(p.interactive()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment