2.2 KiB
2.2 KiB
XMASSpirit
Now that elves have taken over Santa has lost so many letters from kids all over the world. However, there is one kid who managed to locate Santa and sent him a letter. It seems like the XMAS spirit is so strong within this kid. He was so smart that thought of encrypting the letter in case elves captured it. Unfortunately, Santa has no idea about cryptography. Can you help him read the letter?
Flag
HTB{4ff1n3_c1ph3r_15_51mpl3_m47h5}
- See letter.pdf
How to solve
- It's a known plaintext attack.
- The encryption works by applying
(a*byte+b)%nfor each byte of the pdf. - Where
aandbremain static across the whole file. - The PDFv5 Header is known (
00000000: 2550 4446 2d31 2e35 0a25 e2e3 cfd3 0a37 %PDF-1.5.%.....7) - Constraint 1: Factor
ahas to be a number between 1..256 while not sharing a common divisor with 256 - Constraitn 2: Factor
bhas to be a number between 1..256 - So it's possible to attack the encryption by iterating and trying to create a pair (a, b) that matches the entire encrypted pdf header.
def get_factors(ct, n=256):
''' find a and b for n and ct '''
# first generate a list of all numbers without common divisor with 256
nogcds = [ x for x in range(1, n) if gcd(x, n) == 1 ]
for b in range(1, n):
for a in nogcds:
for i, enc in enumerate(header):
candidate = (a * enc + b) % n
if candidate != ct[i]: break
if(i+1 == len(header)):
print(f'Solved: a={a},b={b}')
return (a,b)
print(f'No solution found.')
return (0,0)
- When the factors are found, simply create a lookup table of all values and substitute each byte in the ciphertext.
def decrypt(ct):
''' decrypt the file using the lookup table '''
res = b''
for byte in ct:
dec = lookup[byte]
res += bytes([dec])
return res
Notes
Encryption code analysis:
- Choose a
randintafrom1tomod, that is not divisible by mod. - Choose a
randintbfrom1tomod. - for each byte in
dt- calculate
(a * byte + b) % mod - append to output bytes
- calculate
- return bytes when done
s_next = (a * s_prev + b) mod pis a linear congruential generator prng