[ASCIS 2021 - PWN] NOTE
Chào cả nhà, sau khi mình không vào được chung khảo nên đâm ra cay cú phải xin bằng được để pwn chung khảo. Sau 1 thời gian loay hoay giải bài note thì mình quyết định viết write up để chứng tỏ trình mình cũng chẳng phải gà :)).
Bài này là 1 bài heap, code dịch ngược rất dài vì menu nó có tới 9 chức năng:
Mình sẽ tập trung vào CreateNote, SaveNote, ListNote, RemoveNote, EncryptNote, DecryptNote.
Đầu tiên là các struct:
Struct thứ 2 quan trọng nhất, tên note dài 0x100, sau đó là length của nội dụng note_content, thằng bit mình chả biết nó để làm gì và chính nó khiến mình đau khổ suy nghĩ, function free là 1 con trỏ tới địa chỉ hàm 0x401380
Và cả 2 struct này đều lưu trên vùng nhớ tạo bởi thư viện libzone.so. Nếu mọi người chạy ./note thì sẽ báo lỗi vì không tìm thấy libzone.so, làm theo 2 câu lệnh sau:
1. CreateNote
Mọi người cứ hiểu code này để tạo note, bao gồm tên note, length, note content, bit = 1, và gán 0x401380 là hàm dọn dẹp note. Ngoài ra không làm gì khác, nhưng tạo note nhưng chưa lưu vào mảng để quản lý, để lưu vào mảng (cái vùng heap 0x400 ấy) thì phải dùng SaveNote
2. SaveNote
Hàm này cho phép mình chọn index của mảng để lưu nhé, nếu index đó có thằng khác rồi thì nó sẽ đẩy mấy thằng kia lên để nó chui vào
3. ListNote
Như cái tên của nó rồi, ai chơi heap nhiều là biết :)). Hàm này cho chọn index rồi in cái note đấy ra thôi, easy.
4. RemoveNote
Ok, note được quản lý bởi zone nên không có vụ double free ở đây nhé
5. EncryptNote (hàm chứa bug)
Hàm này để mã hóa note_content bằng cách xor với key do mình nhập, xong nó chèn chuỗi (Encrypted) trước note name dẫ tới bị overflow nếu độ dài tên ban đầu gần bằng 0x100, thật ra encrypt nhiều lần thì overflow xa hơn nhưng không cần để giải quyết bài này. Điều này sẽ dẫn đến lengh bị thay đổi
Hàm DecryptNote thì mọi người tự suy ra.
Hướng giải
1. Bước 1: Leak libc base
mình sẽ tạo ra 3 chunk, chunk đầu tiên bị thay đổi size, chunk tiếp theo đủ to để khi free nó rơi vào unsorted bin, khiến 8 byte đầu chứa địa chỉ libc, chunk cuối để tránh chunk 2 free bị sát nhập với top chunk.
Ý tưởng cũng đơn giản nên mình không giải thích thêm.
2. Bước 2: Thay đổi __free_hook
Mục tiêu là tạo ra 2 chunk bị free vào cùng bin trong tcache. Ghi đè next pointer để chunk 1 trỏ tới __free_hook khiến lần malloc thứ 2 trả về __free_hook, sau đó đơn giản ghi địa chỉ của hàm system lên __free_hook.
Vậy để ghi đè next pointer thì mình tạo ra 1 chunk ngay trước nó, thay đổi length của nó nhờ bug ở hàm EncryptNote, rồi dùng hàm EditNote để ghi đè. Easy game :)). Không đơn giản thế, logic code của thằng EditNote được thiết kế để tặng độ khó cho game, và nó khiến mính mất buổi chiều.
Trong lúc cuộc sống bế tắc thì mình nhận ra EditNote không phải thằng duy nhất cho mình thay đổi note content, còn 1 hàm nữa là EncryptNote, mình chỉ cần điền lenght key = 8 và chọn key sao cho:
next_pointer ^ key = địa chỉ __free_hook
Ý tưởng thì đơn giản nhưng lúc thực hiện mới thấy nhiều nút thắt của bài toán. Bài pwn này thì cũng chẳng áp dụng gì cao siêu cả, nhưng code dịch ngược hơi phức tạp và dài, đã thế còn strip symbols chứ :)), rõ ràng muốn làm mất thời gian của sinh viên.
Thôi do nó đơn giản nên write up để giải thích code của mình, các bạn hãy tự làm để cảm nhận.
Đây là link: https://github.com/Icefrog2000/CTF-For-Fun/tree/main/hint-4-free
Mong năm sau vào được chung khảo để không còn cay cú nữa









Nhận xét
Đăng nhận xét