Skip to content

Commit

Permalink
PostNordpolen I
Browse files Browse the repository at this point in the history
  • Loading branch information
NicolaiSoeborg committed Dec 18, 2024
1 parent 8058cbc commit 548a08b
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
24 changes: 24 additions & 0 deletions 2024/NC3 Jule CTF 2024/PostNordpolen I/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# PostNordpolen I

Et krypto-system hvor AES-CTR mode bruges.

## Solve

Efter et antal krypteringer vil `CODEBOOK.next()` løbe tør og gamle værdier genbruges - altså nonce reuse!

### AES-CTR

I CounterMode benytter man `AES(key, Nonce||Counter++)` til at skabe et pseudorandom stream af bytes, kaldet et _keystream_ ("ks").
Så længe man holder _key_ hemmelig, vil _ks_ kunne bruges som et one-time pad og data krypteres ved at XOR'es med KS.

Hvis _nonce_ ("number used only once") genbruges under samme nøgle, så vil to beskeder blive krypteret med samme keystream, hvilket vil sige hvis man XOR de to ciphertekst sammen får man:

`CT1 ⊕ CT2 => (MSG1 ⊕ KS) ⊕ (MSG2 ⊕ KS) => MSG1 ⊕ MSG2 ⊕ (KS ⊕ KS) => MSG1 ⊕ MSG2 ⊕ \x00 => MSG1 ⊕ MSG2`

Altså de to _KS_ går ud med hinanden og hvis man kender MSG1, kan mange regne MSG2 ud.

Vi benytter dette til at modtage det krypterede flag og derefter kryptere et stort antal beskeder indeholdende "AAA…", når nonce genbruges vil `FLAG_ENC ⊕ ENC(AAA…) ⊕ AAA…` indeholde det dekrypterede flag.

## Flag

Se [solve.py](solve.py)
3 changes: 3 additions & 0 deletions 2024/NC3 Jule CTF 2024/PostNordpolen I/solve.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from pwn import *

def xor(a, b):
return bytes([x ^ y for x, y in zip(a, b)])

r = remote('10.10.106.188', 1337)
r.readuntil(b"> ")
r.sendline(b"1")
Expand Down
62 changes: 62 additions & 0 deletions 2024/NC3 Jule CTF 2024/PostNordpolen II/solve.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from pwn import *

def xor(a, b):
return bytes([x ^ y for x, y in zip(a, b)])

r = remote('10.10.164.170', 1337)
r.readuntil(b"> ")

letter = 1
while letter <= 1000:
if letter % 64 == 0: print(f"{letter=}")
r.sendline(b"1")
r.readuntil(b'\nDu har 1 brev klar til udlevering: ')
ENC_FLAG = bytes.fromhex(r.readuntil(b'\n')[:-1].decode())
r.readuntil(b"> ")
letter += 1

print(f"{letter=}")

ct0 = ENC_FLAG[0:16]
ct1 = ENC_FLAG[16:32]
ct2 = ENC_FLAG[32:48]
ct3 = ENC_FLAG[48:64]
ct4 = ENC_FLAG[64:80]

def ENC(msg: bytes) -> bytes:
""" returns result of ENC(key, msg) """
global letter
r.sendline(b"2")
r.readuntil(b"Besked: ")
r.sendline(b'AAAA')
r.readuntil(b"Adresse: ")
r.sendline(b"")
r.readuntil(b"IV: ")

assert len(msg) == 16, msg
r.sendline(msg.hex().encode())

r.readuntil(b"afsendt til : ")
CRIB = f"[BREV {letter}] AAAA".encode()
result = xor(CRIB, bytes.fromhex(r.readuntil(b'\n')[:-1].decode()))

r.readuntil(b"> ")
letter += 1
return result


ks0 = xor(ct0, b'[BREV 1000] NC3{')

ks1 = ENC(ks0)
pt1 = xor(ct1, ks1)

ks2 = ENC(ks1)
pt2 = xor(ct2, ks2)

ks3 = ENC(ks2)
pt3 = xor(ct3, ks3)

ks4 = ENC(ks3)
pt4 = xor(ct4, ks4)

print(b'NC3{' + pt1 + pt2 + pt3 + pt4)

0 comments on commit 548a08b

Please sign in to comment.