---
# System prepended metadata

title: UVT-CTF Writeup Queue

---

# UVT-CTF Writeup Queue

## Block construction - Crypto - 150 Points - 46 Solves

### Challenge Description + files
"Sir, sir! This is a construction site." You look up at what you thought was a building being constructed, but you realize it is a construction bot. "Sir please move aside. I had to have these blocks in order since last week, but some newbie construction bot shuffled them." "I can move aside, " you tell the bot, "but I might be able to help you out."

Can you help the bot get the blocks in order?
[block_construction.zip](https://braekerctf.ctfd.io/files/538251405f576c059908d0407752d1ee/block_construction.zip?token=eyJ1c2VyX2lkIjo2ODksInRlYW1faWQiOjM5NCwiZmlsZV9pZCI6NzV9.ZduAGA.o2Bdb6MbbhO55hF0AcPK_iA2SsI)

### Introduction
This challenge uses AES in ECB mode to encrypt every byte of the flag. We solve it by exploiting the weakness of the ECB mode, **repeating plaintext generates repeating ciphertext**.

### Recon
In the `block_construction.zip` there are 2 files, `block_construction.py` and `ciphertext`. The file `block_construction.py` contains a script that encrypts the flag with AES in ECB mode and writes the encrypted flag in `ciphertext`.

For the ciphertext to be generated each character from the flag is padded with each character from `rand_printable` and then encrypted with AES in ECB mode with a random key (32 bytes).

```python
with open('ciphertext_test.txt','w') as fout:
    for x in flag:
        for y in rand_printable:
            fout.write(encrypt(x + (y*31)).decode())
```

The list `rand_printable` is formed from printable characters that are shuffled with a time based seed. 

```python
# len(printable) = 100
random.seed(int(time()))
rand_printable = [x for x in printable]
random.shuffle(rand_printable)
```

### Solution
The solution is divided in two main parts:
#### Finding the index of the flag characters from `rand_printable`

``` python
l = []
with open("ciphertext", 'r') as fin:
    text = fin.read()
    text = binascii.unhexlify(text)
    for i in range(0, len(text), 3200):
        for j in range(0, 3200, 32):
            if text[(i + j):(i + j + 16)] == text[(i + j + 16):(i + j + 32)]:
                l.append(j // 32)
                break
```

AES in ECB mode encrypts a 32 bytes text with a 32 bytes key by splitting the text in two blocks of 16 bytes and then encrypts them with the same key. This means that if we have a text such that `text[0:16] == text[16:32]`  then `ciphertext[0:16] == ciphertext[16:32]`.
We can use this to our advantage. We can find the index of the flag characters in `rand_printable` by checking where the flag characters are equal with the character from the padding.

#### Recreating the `rand_printable` list and getting the flag
To get the same shuffle we need to find the exact time the program generated the ciphertext.
We can see this by looking when it was last modified.
![image](https://hackmd.io/_uploads/HkrV06i3p.png)
Then we can use a site like https://www.epochconverter.com to get the exact number we need.
![Pasted image 20240227211629](https://hackmd.io/_uploads/S1RvRpi26.png)
Finally we use the indexes to print the flag.

```python
for i in l:
    print(rand_printable[c], end='')
```

### Flag
**brck{EZP3n9u1nZ}**