# Crypto slide quest - SquareCTF 2023
---
# Description
> I lost my secret key and the flag while writing this challenge, can you help me out? Ciphertext base64: LEs2fVVxNDMfNHEtcx80cB8nczQfJhVkDHI/Ew==
* [crypto_slide_quest.c](https://)
```
#include "flag.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
_Static_assert(sizeof(key) == 7, "Invalid key size!");
char* output = malloc(sizeof(flag));
strncpy(output, flag, sizeof(flag));
int flag_len = strlen(flag);
int key_len = strlen(key);
for(int i = 0; i < flag_len - key_len + 1; i++) {
for(int j = 0; j < key_len; j++) {
output[i + j] ^= key[j];
}
}
printf("%s", output);
free(output);
return 0;
}
```
# Solution
Đọc code thì ta thấy flag sẽ được mã hóa bằng phép XOR, với mỗi ký tự trong flag, ```key_len``` ký tự tính từ ```i``` sẽ xor lần lượt với key.
Bài này hướng giải của mình là truy tìm key theo format của flag: flag{...}. Với 5 ký tự đầu và 1 ký tự cuối, mình sẽ bruteforce từng ký tự của key trong bảng chữ cái viết hoa, viết thường, và chữ số.
```
#tìm 5 ký tự đầu của key
flag = "flag{"
for index in range(5):
for i in range(len(alphabet)):
XOR = 0
for j in key:
XOR ^= ord(j)
if ciphertext_bytes[index]^ord(alphabet[i])^XOR == ord(flag[index]):
key += alphabet[i]
```
```
#tìm ký tự cuối của key
for i in range(len(alphabet)):
if ciphertext_byte[27]^ord(alphabet[i]) == ord("}"):
key += alphabet[i]
print(key)
```
Xong 2 đoạn trên mình tìm được Key là JmpM4..n. Mình nghĩ key nó không ngắn như vậy nên bắt đầu tìm tiếp chữ cái tiếp theo, cũng bằng bruteforce. Và mình thấy một điều bất ngờ là ký tự tiếp theo và kế cuối của key chỉ có thể là chữ số (vì khi bruteforce, chỉ khi ký tự tiếp theo là chữ số thì ký tự tiếp theo trong flag mới printable)
Trong khi đó, key của mình đang có 6 ký tự, nếu như chỉ có thêm 1 chữ số thì sẽ báo lỗi (đoạn đầu), nên mình dự đoán là 8 ký tự, với 2 ký tự ở giữa đều là chữ số. Nên mình lại tiếp tục bruteforce, sinh ra các key có thể có
```
#sinh key
keys = []
for i in range(ord('0'),ord('9')+1 ):
for j in range( ord('0'),ord('9')+1 ):
tmp= chr(i)+chr(j)
keys.append(tmp)
#bruteforce
for k in keys:
pkey = key + k + 'n'
XOR =0
for i in pkey:
XOR ^= ord(i)
plain = ""
for index in range(5,25):
if chr(ciphertext_byte[index]^XOR).isprintable():
plain += chr(ciphertext_byte[index] ^ XOR)
print(plain, pkey)
```
Kết quả mình thu được là ```plain```là một cụm có nghĩa khi key có 2 chữ số ở giữa giống nhau, nghĩa là key có dạng JmpM4'**'n
Như vậy nên mình bắt đầu đoán key chỉ có 6 ký tự, và không có chữ số: JmpM4n
Và mình tiến hành decode:
```
key = 'JmpM4n'
ciphertext_int = [i for i in ciphertext_byte]
for i in range(flag_len - len(key) + 1 ):
for j in range(len(key)):
ciphertext_int[i + j] ^= ord(key[j])
```
Và flag là: flag{1ts_t1m3_t0_g3t_fUnkee}