It's time to test out Tibel Elf's new encryption method. He says once you encrypt it, you can't unencrypt it. Sureeee... Connect with nc ctf.csd.lol 3551
.
Epochrypt
Category
Points
Author
Cryptography
70
qvipin
Solves (97)
1 | ![]() | 12/06 3:59 pm |
2 | ![]() | 12/06 4:01 pm |
3 | ![]() | 12/06 4:07 pm |
4 | ![]() | 12/06 4:08 pm |
5 | ![]() | 12/06 4:20 pm |
6 | ![]() | 12/06 4:25 pm |
7 | ![]() | 12/06 4:29 pm |
8 | ![]() | 12/06 4:39 pm |
9 | ![]() | 12/06 4:42 pm |
10 | 12/06 5:24 pm | |
11 | 12/06 5:28 pm | |
12 | ![]() | 12/06 5:40 pm |
13 | ![]() | 12/06 6:15 pm |
14 | ![]() | 12/06 8:41 pm |
15 | ![]() | 12/07 1:57 am |
16 | ![]() | 12/07 4:55 am |
17 | ![]() | 12/07 6:16 am |
18 | ![]() | 12/07 7:47 am |
19 | ![]() | 12/07 11:58 am |
20 | ![]() | 12/07 1:34 pm |
21 | ![]() | 12/07 10:45 pm |
22 | ![]() | 12/08 5:55 pm |
23 | ![]() | 12/09 7:46 am |
24 | ![]() | 12/09 9:41 am |
25 | ![]() | 12/10 12:31 am |
26 | ![]() | 12/11 8:12 am |
27 | ![]() | 12/14 2:14 am |
28 | ![]() | 12/14 1:00 pm |
29 | ![]() | 12/15 6:19 am |
30 | ![]() | 12/15 9:09 am |
31 | ![]() | 12/15 1:36 pm |
32 | ![]() | 12/15 6:43 pm |
33 | ![]() | 12/16 8:49 am |
34 | ![]() | 12/16 9:51 am |
35 | ![]() | 12/16 9:51 am |
36 | ![]() | 12/16 4:27 pm |
37 | ![]() | 12/16 6:44 pm |
38 | ![]() | 12/16 9:22 pm |
39 | ![]() | 12/16 9:22 pm |
40 | ![]() | 12/17 3:30 am |
41 | ![]() | 12/17 7:01 am |
42 | ![]() | 12/17 3:28 pm |
43 | ![]() | 12/17 4:12 pm |
44 | ![]() | 12/18 1:58 am |
45 | ![]() | 12/18 3:44 am |
46 | ![]() | 12/18 5:24 am |
47 | ![]() | 12/18 9:30 am |
48 | ![]() | 12/18 10:27 am |
49 | ![]() | 12/18 12:50 pm |
50 | ![]() | 12/18 1:19 pm |
51 | ![]() | 12/18 2:51 pm |
52 | ![]() | 12/18 8:26 pm |
53 | ![]() | 12/18 9:33 pm |
54 | ![]() | 12/19 9:02 am |
55 | ![]() | 12/19 10:21 am |
56 | ![]() | 12/19 11:27 am |
57 | ![]() | 12/19 1:20 pm |
58 | ![]() | 12/20 8:49 pm |
59 | ![]() | 12/21 3:57 am |
60 | ![]() | 12/21 1:49 pm |
61 | ![]() | 12/21 7:06 pm |
62 | ![]() | 12/21 7:25 pm |
63 | ![]() | 12/22 3:59 am |
64 | ![]() | 12/22 10:38 am |
65 | ![]() | 12/22 11:07 am |
66 | ![]() | 12/22 12:31 pm |
67 | ![]() | 12/23 3:31 am |
68 | ![]() | 12/23 8:45 am |
69 | ![]() | 12/23 11:23 am |
70 | ![]() | 12/23 3:39 pm |
71 | ![]() | 12/23 4:39 pm |
72 | ![]() | 12/24 2:29 am |
73 | ![]() | 12/24 1:57 pm |
74 | ![]() | 12/25 12:59 am |
75 | ![]() | 12/25 1:45 am |
76 | ![]() | 12/25 1:59 am |
77 | ![]() | 12/25 7:06 am |
78 | ![]() | 12/25 8:44 am |
79 | ![]() | 12/25 9:38 am |
80 | ![]() | 12/25 10:58 am |
81 | ![]() | 12/25 11:49 am |
82 | ![]() | 12/25 4:48 pm |
83 | ![]() | 12/25 4:48 pm |
84 | ![]() | 12/25 5:34 pm |
85 | ![]() | 12/26 12:16 am |
86 | ![]() | 12/26 12:32 am |
87 | ![]() | 12/26 12:39 am |
88 | ![]() | 12/26 5:38 am |
89 | ![]() | 12/26 6:38 am |
90 | ![]() | 12/26 1:40 pm |
91 | ![]() | 12/27 11:12 pm |
92 | ![]() | 12/28 2:33 am |
93 | ![]() | 12/28 4:12 am |
94 | ![]() | 12/28 12:13 pm |
95 | ![]() | 12/29 6:29 am |
96 | ![]() | 12/29 8:49 am |
97 | ![]() | 12/29 10:26 pm |
Submit flag
Write-up
zarnex's write-up was selected as the best write-up submitted for this challenge.
View this write-up on GitHubLets look at main.py
.
#!/usr/local/bin/python import time import base64 as b64 from pwn import xor def epochrypt(enc): bits = bytes([(b + 3) % 256 for b in enc]) based = b64.b64encode(bits) epc = str(int(time.time())).encode() final = xor(based, epc) print(final.hex()) def menupage(): print("Epochrypt v1.0") print("\"The Dynamic Encryption Method\"") print("------------------------------------") print("1. Encrypt Text") print("2. View Encrypted Flag") print("3. Check Flag") print("4. Exit Program") try: while True: menupage() option = input("Enter option here: ") if option == "1": textToEncrypt = input("Enter String: ") epochrypt(textToEncrypt.encode()) exit(0) if option == "2": with open("/app/flag.txt", "rb") as file: flag = file.read() epochrypt(flag) exit(0) if option == "3": checkFlag = input("Enter flag here to check: ") with open("/app/flag.txt", "rb") as file: flag = file.read() if flag in (checkFlag + "\n").encode(): print("Correct! You got it, now go submit that thang.") exit(0) else: print("*BUZZ* That ain't it bud :(") exit(0) if option == "4": print("bye bye!") exit(0) except KeyboardInterrupt: print("CTRL + C detected, Quitting program...")
Most of this is straight forward with all the features, but the main thing we need to focus on is the epochrypt()
function.
def epochrypt(enc): bits = bytes([(b + 3) % 256 for b in enc]) based = b64.b64encode(bits) epc = str(int(time.time())).encode() final = xor(based, epc) print(final.hex())
This may be a small function but it packs a punch! Lets go over this line by line.
bits = bytes([(b + 3) % 256 for b in enc])
The first line is pretty much adding 3 to every characters ASCII values, kinda treating it like a Caeser Cipher. Using this one liner print(bytes([(b + 3) % 256 for b in b'hello']))
, we see that hello becomes khoor.
based = b64.b64encode(bits)
In this line it takes the items from bits
and Base64 encodes them.
epc = str(int(time.time())).encode() final = xor(based, epc)
Now here comes the interesting part, first it takes the current Unix Epoch time and turns them into a int to strip the decimal at the end, after that it XOR's it by Based
. This is probably where it gets the "The Dynamic Encryption Method" name from because it XOR's it by Epoch time (The amount of time since January 1, 1970) so it will never be the same again.
print(final.hex())
And then finally it outputs the text in Hex! Lets try it out for ourself.
$ nc ctf.csd.lol 3551 Epochrypt v1.0 "The Dynamic Encryption Method" ------------------------------------ 1. Encrypt Text 2. View Encrypted Flag 3. Check Flag 4. Exit Program Enter option here: 1 Enter String: Hello 62055b405201710d6507 $ nc ctf.csd.lol 3551 Epochrypt v1.0 "The Dynamic Encryption Method" ------------------------------------ 1. Encrypt Text 2. View Encrypted Flag 3. Check Flag 4. Exit Program Enter option here: 1 Enter String: Hello 62055b405201710d6406
Here I tried to encrypt Hello twice, notice how it is different. This is because it XOR's with the Epoch time which changes every second. Now we gotta figure out how to reverse the text. Here is what I wrote
from pwn import * from base64 import b64decode from time import sleep, time
I started off by importing pwntools to connect to the server and to items, then imported time to grab the epoch time and use sleep()
target = remote("ctf.csd.lol", 3551) # Connecting to the server sleep(2) # Pausing the program target.sendline("2") # Sending 2 to print out flag epc = str(int(time())) # Grabbing the epoch time exactly when 2 is sent sleep(2) # Pausing for 2 seconds
So I did write comments above on what each line does, but the general idea on what this part of the script does it to grab the epoch when it enters 2 so we have the exact epoch time to XOR with.
One thing I had noticed was that the flag when pressing option 2 always started with 6b5969
so now we can just
response = target.recv(1000).decode() # Receive up to 1000 bytes start_idx = response.find("6b5969") # Find the position of "6b5969" enc_flag = response[start_idx:].split("\n")[0].strip() # Extract flag from marker to end of line
Now we have that extraction, all we need to do now is to write the next part of the script to reverse the encryption.
flag = bytes([(b - 3) % 256 for b in b64decode(xor(bytes.fromhex(enc_flag), epc))]) # Very Concise 1 liner that reverses the epochrypt operations print(f"Flag: {flag.decode()}") # Decodes flag so output wouldn't be b''
So the full solution is...
from pwn import * from base64 import b64decode from time import sleep, time target = remote("ctf.csd.lol", 3551) sleep(2) target.sendline("2") epc = str(int(time())) sleep(2) response = target.recv(1000).decode() start_idx = response.find("6b5969") enc_flag = response[start_idx:].split("\n")[0].strip() flag = bytes([(b - 3) % 256 for b in b64decode(xor(bytes.fromhex(enc_flag), epc))]) print(f"Flag: {flag.decode()}")
Running it...
$ /bin/python3 /home/zarnex/advent_of_ctf/epochrypt/solution.py [+] Opening connection to ctf.csd.lol on port 3551: Done /home/zarnex/advent_of_ctf/epochrypt/solution.py:8: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes target.sendline("2") /home/zarnex/.local/lib/python3.12/site-packages/pwnlib/util/fiddling.py:335: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes strs = [packing.flat(s, word_size = 8, sign = False, endianness = 'little') for s in args] Flag: csd{d3F0_M4d3_8y_4N_3lf}
Yes! But lets double check the flag...
$ nc ctf.csd.lol 3551 Epochrypt v1.0 "The Dynamic Encryption Method" ------------------------------------ 1. Encrypt Text 2. View Encrypted Flag 3. Check Flag 4. Exit Program Enter option here: 3 Enter flag here to check: csd{d3F0_M4d3_8y_4N_3lf} Correct! You got it, now go submit that thang.
Flag: csd{d3F0_M4d3_8y_4N_3lf}