TCPサーバの接続情報と、サーバのプログラムserver.py
が与えられた。
server.py
は、以下の処理をするものだった。
flag
の暗号化結果を出力する。暗号化は以下の手順で行う。
key
を生成する。iv
を生成する。key
と、iv
を用いて初期化したカウンタを用い、平文をpad
関数で処理したものをAES.MODE_CTR
で暗号化する。iv
を連結する。unpad
関数で処理する。0
を出力する。発生しなければ1
を出力する。
今回の暗号化はAES.MODE_CTR
を用いているので、iv
によって決まる鍵をXORすることによって暗号化するはずである。
したがって、iv
を除く暗号文のあるバイトの値を変えても、他のバイトには影響を与えないはずである。
また、pad
関数やunpad
関数の性質はよくわからないが、データの後ろに加えるバイト数を値とするバイト列を加えるパディングを扱うと予想した。
この性質を利用すると、暗号文の最後のバイトだけを変えて全探索することで、平文が0x01になる暗号文を求めることができる。
するとこの位置の鍵もわかるので、次はこれを用いて暗号文の最後を0x02に復号される値に固定しつつ、暗号文の最後から2番目のバイトを変え、平文が0x02になる暗号文を求めることができる。
これを繰り返すことで、1ブロック分の鍵を求めることができる。
さらに最後のブロックを外して同様の処理を行うことで、他のブロックの鍵も求めることができる。
以下のプログラムを用いることで暗号文と鍵を求め、
Information to connect to a TCP server and a program of the server server.py
were given.
What server.py
does is:
flag
. The encryption is:
key
.iv
.pad
, using the key
and a counter initialized using the iv
.iv
before the ciphertext.unpad
.0
if any exception is thrown. Output 1
if no exception are thrown.
The encryption in this challenge uses AES.MODE_CTR
, so the encryption should be an exclusive-or with a key that depends on iv
.
This means that changing a byte in the ciphertext which is not in the iv
won't affect the other bytes.
Also, what the functions pad
and unpad
does is unknown, but I guessed that they deal with a padding where bytes whose values are the number of bytes to add are added after the data.
Using this property, we can obtain a ciphertext corresponding to a plaintext whose last byte is 0x01 by brute-forcing with changing the last byte of the ciphertext.
This will reveal the key for the byte, so we can use this to fix the last byte of the ciphertext to make its plaitext to be 0x02
and search for a the second last byte of ciphertext to make the plaintext to be 0x02.
Repeating this, we can reveal the key for the whole block.
Moreover, we can reveal the key for the other blocks by removing the last block and repeating this process.
I used this program to obtain the ciphertext and the key.
Then I used "XOR" on