Skip to content

Commit

Permalink
aesy challenge writeup
Browse files Browse the repository at this point in the history
  • Loading branch information
Pharisaeus authored and XeR committed Apr 13, 2020
1 parent c83b24c commit 17d84d0
Showing 1 changed file with 55 additions and 0 deletions.
55 changes: 55 additions & 0 deletions 2020-04-12-ByteBanditsCTF/aesy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# AESy (crypto, 471p)

In the task we can access a server, which allow us to encrypt messages, and also send encrypted messages to Alice.
We also get the ciphertext of encrypted flag.

If we send message to Alice two things can happen:

1. Either the response contains `!`, if we send a valid message we created using the system
2. Or the response contains `?`, if we send broken message

If we look closely at encrypted messages and their length, we can see that:

1. There is one additional block present all the time
2. The block length is 16 bytes
3. Our inputs cause doubled response length

This all lead us to conclusions that we have some CBC encryption there and that our inputs are hex-encoded before encryption.

We can confirm the CBC hypothesis by sending carefully forged message to Alice:

1. Encrypt `aaaaaaa`, which should become 14 bytes hex-encoded, and thus padding would be `\2\2`
2. Flip last byte of the first block (which we expect to be IV) by `^2^1`, which should flip the last byte of plaintext, after decryption, into `\1` which is valid padding

For such message we get back `!` and not `?`, which confirms our hypothesis.
This also means we have a classic CBC padding oracle.

We create oracle function:

```python
def oracle(s, ct):
data = receive_until_match(s, "Enter your choice:\n")
send(s, "2")
data = receive_until_match(s, "Enter the ciphertext\(hex-encoded\):\n")
send(s, ct)
response = receive_until_match(s, "\n\n")
return '??' not in response
```

And we run the solver:

```python
def main():
port = 7004
host = "crypto.byteband.it"
s = nc(host, port)
data = receive_until_match(s, "Enter your choice:\n")
print(data)
send(s, "3")
data = receive_until_match(s, "Here is your ciphertext\(hex-encoded\):\n")
flag = receive_until(s, "\n")[:-1]
print('flag', flag)
print(oracle_padding_recovery(flag, lambda ct: oracle(s, ct)))
```

After a while we get back hex-encoded flag: `flag{th3_0racl3_0nly_gu1de$_7he_1337}`

0 comments on commit 17d84d0

Please sign in to comment.