-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
134 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,139 @@ | ||
--- | ||
title: "numbers go brrr 2" | ||
description: "task" | ||
points: 831 | ||
description: "A spiritual successor the first." | ||
points: 829 | ||
solves: 126 | ||
author: nobody | ||
date: April 2 2024 | ||
author: Jozef Steinhübl | ||
--- | ||
|
||
yeh' numbers go brrr 2.... it was hard lol | ||
## Introduction | ||
|
||
 | ||
|
||
In this task, we are given a source code of the encryption service and ip with a port to connect to using netcat. | ||
```py | ||
#!/usr/bin/env python3 | ||
from Crypto.Cipher import AES | ||
from Crypto.Util.Padding import pad | ||
from Crypto.Random import random | ||
|
||
seed = random.randint(0, 10 ** 6) | ||
def get_random_number(): | ||
global seed | ||
seed = int(str(seed * seed).zfill(12)[3:9]) | ||
return seed | ||
|
||
def encrypt(message): | ||
key = b'' | ||
for i in range(8): | ||
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big') | ||
cipher = AES.new(key, AES.MODE_ECB) | ||
ciphertext = cipher.encrypt(pad(message, AES.block_size)) | ||
return key.hex(), ciphertext.hex() | ||
|
||
|
||
print("Thanks for using our encryption service! To get the start guessing, type 1. To encrypt a message, type 2.") | ||
print("You will need to guess the key (you get 250 guesses for one key). You will do this 3 times!") | ||
|
||
for i in range(3): | ||
seed = random.randint(0, 10 ** 6) | ||
print("Find the key " + str(i + 1) + " of 3!") | ||
key = encrypt(b"random text to initalize key")[0] | ||
while True: | ||
print("What would you like to do (1 - guess the key, 2 - encrypt a message)?") | ||
user_input = int(input()) | ||
if(user_input == 1): | ||
break | ||
|
||
print("What is your message?") | ||
message = input() | ||
key, ciphertext = encrypt(message.encode()) | ||
print("Here is your encrypted message:", ciphertext) | ||
print("You have 250 guesses to find the key!") | ||
|
||
found = False | ||
for j in range(250): | ||
print("What is your guess (in hex)?") | ||
guess = str(input()).lower() | ||
if guess == key: | ||
print("You found the key!") | ||
found = True | ||
break | ||
else: | ||
print("That is not the key!") | ||
|
||
if not found: | ||
print("You did not find the key!") | ||
exit(0) | ||
|
||
|
||
flag = open('/src/flag.txt', 'r').read(); | ||
print("Here is the flag:", flag) | ||
``` | ||
|
||
This encryption service allows us to guess the key in 250 tries if we type `1` and encrypts a message if we type `2`. Encryption is done same as in the [numbers go brrr](https://gerlachsnezka.github.io/writeups/utctf/2024/cryptography/numbers-go-brrr/) task. | ||
|
||
## Solving | ||
|
||
We can solve this similary to [the previous task](https://gerlachsnezka.github.io/writeups/utctf/2024/cryptography/numbers-go-brrr/) but with a small difference. We'll encrypt our own message and then brute-force the key. This is exactly same approach as in the previous task, but we just need to get own encrypted message first as we don't have encrypted flag. Then we'll just prompt the key and socket will return us the flag. | ||
|
||
```py | ||
import socket | ||
from Crypto.Cipher import AES | ||
from Crypto.Util.Padding import unpad, pad | ||
import binascii | ||
|
||
def get_next_seed(seed): | ||
return int(str(seed * seed).zfill(12)[3:9]) | ||
|
||
def predict_key(seed): | ||
key = b'' | ||
for i in range(8): | ||
key += (seed % (2 ** 16)).to_bytes(2, 'big') | ||
seed = get_next_seed(seed) | ||
return key | ||
|
||
def decrypt(ciphertext, key): | ||
cipher = AES.new(key, AES.MODE_ECB) | ||
try: | ||
decrypted = cipher.decrypt(ciphertext) | ||
return unpad(decrypted, AES.block_size) | ||
except ValueError: | ||
|
||
cipher = AES.new(key, AES.MODE_ECB) | ||
decrypted = cipher.decrypt(ciphertext) | ||
return decrypted | ||
|
||
def hex_to_bytes(hex_str): | ||
return binascii.unhexlify(hex_str) | ||
|
||
HOST = 'betta.utctf.live' | ||
PORT = 2435 | ||
|
||
encrypted_msg_hex = input() # input your encrypted message here | ||
encrypted_msg_bytes = hex_to_bytes(encrypted_msg_hex) | ||
|
||
for seed in range(1000000): | ||
key = predict_key(seed) | ||
decrypted_msg = decrypt(encrypted_msg_bytes, key) | ||
try: | ||
decrypted_msg_text = decrypted_msg.decode('utf-8') | ||
if decrypted_msg_text != "houska": | ||
continue | ||
|
||
print("Decrypted msg:", decrypted_msg_text) | ||
print("Seed:", seed) | ||
print("Key:", key.hex()) | ||
break | ||
except UnicodeDecodeError: | ||
continue | ||
``` | ||
|
||
I used message `houska`, don't ask me why XD | ||
 | ||
|
||
After running the script, we get the key and seed. We can now connect to the server and get the flag by typing `1` and then the key. | ||
``` | ||
utflag{ok_you_are_either_really_lucky_or_you_solved_it_as_intended_yay} | ||
``` |
File renamed without changes
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.