[Writeup] PascalCTF 2025
Đang giữa tuần, và cũng rất nhiều bài kiểm tra giữa kỳ. Mình thấy hơi xì-chét nên lên check CTFTime thì thấy giải này. Giải này chơi cá nhân và chủ yếu là dành cho Newbie nên mình gần như clear đề (Còn mỗi câu Crypto cuối chưa làm kịp @@). Writeup này cũng như là để ghi nhớ giải CTF đầu tiên mà bản thân gần như clear trong năm.
Mình sẽ chỉ giải một vài bài thuộc chuyên môn của mình (PWN, Web, RE - nhưng Web dễ quá nên mình lười viết hehehe) với giải thích đơn giản.
PWN
Những bài PWN đều khá dễ không có source code nên mình sẽ dùng IDA để phân tích.
Morris Worm
Analysis
Checksec
1 | ┌──(kali㉿ANONYMOUS)-[/mnt/d/Security/ctf-storage/2025/pascalctf/Morris Worm] |
Source code
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
Dựa vào những gì lấy được từ checksec và logic của đoạn code thì bài này là một bài BOF ở hàm fgets(s, 1337, stdin);
=> Ghi đè giá trị của biến v5
thành 1337 => Get flag
Exploit
1 | from pwn import * |
E.L.I.A
Analysis
Checksec
1 | ┌──(kali㉿ANONYMOUS)-[/mnt/d/Security/ctf-storage/2025/pascalctf/E.L.I.A] |
Source code
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
Bài này là một bài Format String ở đoạn code printf(format);
Mình dùng đoạn code bên dưới để lấy flag
1 | from pwn import * |
Ở offset thứ 8 là của flag
1 | import struct |
Unpwnable shop
Analysis
Checksec
1 | ┌──(kali㉿ANONYMOUS)-[/mnt/d/Security/ctf-storage/2025/pascalctf/Unpwnable shop] |
Source code
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
1 | __int64 printMenu() |
1 | __int64 win() |
Trong bài này, mình thấy có hàm win
không được gọi, cũng như PIE tắt => ret2win để gọi hàm win và lấy flag
Canary Found từ checksec là lỗi của thằng checksec nha quý zị :> Lâu lâu nó ngu vậy á, nên bài này không có canary.
Dựa vào logic của code thì mình nhận thấy fgets(v13, 81LL, stdin);
cho nhập vào biến v13
tận 81 ký tự (Nhiều hơn khai báo 5 ký tự). Tuy nhiên với mỗi 5 byte này thì không thể ghi đè địa chỉ trả về được => Thay vào đó mình sẽ tận dụng lỗi BOF để ghi đè giá trị của biến v14
nằm liền kề. => Tiếp theo là nhập 69 để chương trình đi vào phần nhập lần 2 của biến v13
(Lúc này do v14 đã bị ghi đè nên attacker có thể kiểm soát được số lượng ký tự nhập vào v13
) -> BOF lần 2
Lúc này đã có đủ số byte thừa ra cần thiết để thực hiện kỹ thuật ret2win nên mình sẽ viết payload luôn.
Exploit
1 | from pwn import * |
Reverse Engineer
X-Ray
Analysis
- Source code
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
- Data
1 | .rodata:0000000000002010 key db '*7^tVr4FZ#7S4RFNd2',0 |
Bài này đơn giản là chương trình sẽ lấy chuỗi người dùng nhập vào đem xor với key rồi so sánh với enc => Xor ngược lại để lấy được flag
Exploit
1 | key = "*7^tVr4FZ#7S4RFNd2" |
1 | ┌──(kali㉿ANONYMOUS)-[/mnt/d/Security/ctf-storage/2025/pascalctf/RE/x-ray] |
Switcharoo
Analysis
- Source code
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
Logic bài này đơn giản là chúng ta sẽ nối lại các ký tự theo thứ tự từ 0 -> 31 để lấy được flag hoàn chỉnh
Flag: pascalCTF{pa0Lo_c4nT_D0_r3V_l0L}
KONtAct MI
Bài này mình thấy khá khó hiểu với cách ra đề của tác giả. Không biết là cố tình để nó dễ hay là vô tình làm nó hong khó :>
Analysis
Bài này được cấp source code đầy đủ + file binary
- main.c
1 | /** |
- util.c
1 |
|
- util.h
1 |
|
Mình xem nhanh qua code thì hiểu được là chương trình sẽ cho mình chơi một trò chơi điều khiển di chuyển một đối tượng với các thao tác: up, down, right, left, A và B.
Sau đó, khi chọn contact_support
thì sẽ gửi request lên server https://kontactmi.challs.pascalctf.it/adminSupport với danh sách các nút bấm mà người chơi đã nhấn.
Mình tò mò nên vào url đấy xem thử thì khi GET nó trả về một chuỗi như là danh sách các nút bấm. (Chuỗi này cũng xuất hiện trong code)
Mình thử POST chuỗi này lên luôn thì … Bùm, nhận được flag luôn :>