# Child Encrypter - 2020 Defenit CTF (rev/crypto, 598p, 11 solved)## Introduction
Child Encrypter is a reverse and cryptography task.
A binary, and its output are provided.
The binary expects 3 arguments : the plaintext file, the output file, and a keyfile.
Running the binary twice with the same arguments will provide a differentoutput. When running, it generates and prints a nonce.
## Reverse engineering
The binary is statically linked. libc functions are already visible.
The function at `000014e7` opens and reads a file.
The binary reads the plaintext file and the key file. It then generates 0x10bytes from `/dev/urandom` which outputs cryptographically secure numbers. Thesebytes are the nonce.
The function at `000014a1` prints a hexadecimal dump of its first argument.
The function at `00001586` writes data to a file.
The two functions at `00001304` and `00001408` deal with the encryption.
The first function has reference to an array of 256 bytes. The values of thisarray are those found in the [AES S-Box](https://en.wikipedia.org/wiki/AES_s-box#Forward_S-box).
Using the test vector found on [Sam Trehnholme's Rijndael's key schedulearticle](http://www.samiam.org/key-schedule.html) shows that this functionexpands the key (second argument) to the AES state (first argument). The nonceis copied after the state.
```cstruct state {	unsigned char aes_state[0xB0];	unsigned char nonce[0x10];};```
The function at `00001408` is not an AES encryption, but it calls the functionat `00000e24` which is an AES encryption.
`00001408` is :```cchar block[0x10];char *end = buffer + size;int i = 0x10;
while(buffer != end) {	if(0x10 == i) {		memcpy(block, nonce, sizeof(block));		block[0x0F] = rand() % 10;
		aes_encrypt(block, state);		i = 0;	}
	*buffer ^= block[i];
	i++;	buffer++;}```
This binary encrypts the plaintext à la CTR mode, except there are 10 possiblecounter. The output is large enough to guarantee that every possible nonces arerepeated a few times.
## Cryptography
The first thing to do is to classify each block of 16 bytes and group themaccording to the key that was used to xor them.
A good way is to assume that the text is 7-bit ASCII (i.e. that the 8th bit ofevery char is always clear). This leaks the 8th bit of every byte of the keyused for each block. This information can be used to fingerprint the key usedfor a specific block.
When encrypting a block, the output is `out[i] = block[i] ^ key[rand() % 10]`.
If block `a` and `b` share the same key, then `out[a] ^ out[b] = block[a] ^block[b]`. This means that any block for a specific key can be decrypted if atleast one block of this group is known.
The flag format is `Defenit{...}`. It is safe to assume that `Defenit{` can befound in the clear text. This can help perform a known-plaintext attack of 8bytes.
For every group, xor `block[i]` with `block[0]` (with `i` > 0) and xor it with`Defenit{\0\0\0\0\0\0\0\0`. Repeat for each block, each group, and for eachrotation of the known plaintext until the xorred part appears readable.
```74 7b 00 00 00 00 00 00 00 00 44 65 66 65 6e 69  t{........Defeni << key7a 3a 28 28 61 2a 4f 1a 07 00 70 6f 70 75 6c 61  z:((a*O...popula << block```
Once a block is identified, continue to guess bytes of the key by looking at theplaintext.
```2e 20 46 4c 41 47 20 69 73 20 44 65 66 65 6e 69  . FLAG is Defeni << key20 61 6e 64 20 6d 6f 73 74 20 70 6f 70 75 6c 61   and most popula << block```
Once a block has been fully recovered, every block in this group can bedecrypted as explained above.
```20 61 6e 64 20 6d 6f 73 74 20 70 6f 70 75 6c 61   and most popula2e 20 46 4c 41 47 20 69 73 20 44 65 66 65 6e 69  . FLAG is Defeni73 20 6f 6e 65 20 6f 66 20 74 77 6f 20 62 6c 6f  s one of two blo72 20 6d 6f 64 65 20 74 75 72 6e 73 20 61 20 62  r mode turns a b6e 6f 77 6e 20 73 79 73 74 65 6d 61 74 69 63 20  nown systematic6e 70 75 74 2e 20 41 6c 6f 6e 67 20 77 69 74 68  nput. Along with69 6d 65 2c 20 61 6c 74 68 6f 75 67 68 20 61 6e  ime, although an```
The full plaintext comes from [Wikipedia's article on Block cipher mode ofoperation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR))
The rest of the text can be retrieved in a similar way.
The flag is present at the end of the file. Having only a few keys is enough toretrieve it.
**Flag**: `Defenit{AES_CTR_m0de_i5_g00d!}`
## Appendices
### sort.php
```php#!/usr/bin/php> 7);
	printf(" %s\n", bin2hex($b));	$offset += 0x10;}```
### xor.php
```php $block2) {	echo str_repeat(" ", 0x10);
	for($j = 0; $j < sizeof($block2); $j++) {		$x  = $key;		$x ^= hex2bin($block2[$j]);
		// uncomment for first part of the attack		// $x ^= hex2bin($block2[0]);
		assert(0x10 === strlen($x));		printf("%s", $x);	}}```
### flag.php
```php "ab4a6669b16a9209182ff68d05c728a0",	0b1001011110100110 => "8e2f26e642e5cabbaf1da843349ba65b",	0b1010010000101110 => "9546f0717a832c426c29a66aa7dfd473",	0b1100101000000101 => "e9b61c20ac52de1d245373586ff207d7",	0b1101110101001100 => "8aae71a8bfc123eb07c07014f8923c69",];
$offset = 0;foreach($blocks as $b) {	$index = 0;	for($i = 0; $i < strlen($b); $i++) {		$index <<= 1;		$index  |= ord($b[$i]) >> 7;	}
	$key = $keys[$index] ?? "054e93b81f572c31f2e3fc9ee995567e";	$key = hex2bin($key);
	echo $b ^ $key;}```