Challenge

file

checksec

run binary


IDA
main()

AddNote()

print_note()

DeleteNote()

PrintNote()

Struct NOTE

Analysis
Chương trình có 3 chức năng tương ứng với 3 hàm:
- AddNote(): thêm 1 note vào notes_list[].
- PrintNote(): in nội dung của note.
- DeleteNote(): xóa 1 note khỏi notes_list[].
Phân tích code ta có nhận xét:
- Mỗi note là một struct gồm 2 entry:
- NOTE.pprint: con trỏ trỏ tới hàm print_note(), có chức năng in nội dung trong NOTE.content.
- NOTE.content: chứa nội dung của note.
- Mỗi khi 1 note mới được tạo sẽ có 2 câu lệnh malloc() được gọi:
- notes_list[i] = malloc(8)
- notes_list[i].content = malloc(size)
- Mỗi khi xóa 1 note, có 2 câu lệnh free() được gọi:
- free(notes_list[i].content)
- free(notes_list[i])
Giờ giả sử tôi tạo 2 note mới kích thước là 16 bytes, nội dung là ‘AAAA’ và ‘BBBB’. Cấu trúc heap lúc này như sau:

Ta thấy trên heap lúc này có 4 chunk tương ứng với 2 note:
- chunk 0: notes_list[0]: 0x804b000: 8 byte đầu là header, 4 byte tiếp theo 0x0804862b là địa chỉ của hàm print_note(), 4 byte tiếp theo là địa chỉ của chunk 1 chứa notes_list[0].content. (Lưu ý: địa chỉ của chunk không tính phần header).
- chunk 1: notes_list[0].content: 0x804b010: nội dung notes_list[0]: ‘AAAA’
- chunk 2: notes_list[1]: 0x804b028: tương tự chunk 0.
- chunk 3: notes_list[1].content: 0x804b038: nội dung notes_list[1]: ‘BBBB’
- top_chunk: 0x804b050
Giờ ta hãy xóa note ‘AAAA’, sau đó xóa note ‘BBBB’. 4 chunk trên sẽ được đẩy vào fastbins

Giờ nếu ta tạo note mới kích thước 8 bytes nội dung ‘CCCC’, vì cấu trúc của fastbins là FILO, nên hệ thống sẽ lấy chunk tại 0x804b028 để lưu notes_list[2] và 0x804b000 để lưu notes_list[2].content

Như vậy, lúc này nếu xét notes_list[0] thì notes_list[0].pprint bị ghi đè thành ‘CCCC’. Nếu ta cho PrintNote(0) thì chương trình sẽ coi ‘CCCC’ là hàm print_note() và gọi lên.
Vậy ta có thể thay ‘CCCC’ thành địa chỉ hàm system để get shell. Chú ý là hàm print_note() được truyền tham số là địa chỉ của note đó, nên ta sẽ dùng payload p32(system_address) + p32(‘;sh;’) để truyền tham số ‘;sh;’ cho hàm system().
Nhưng trước hết, ta cần leak địa chỉ của libc. Ở đoạn add note 2, ta sẽ add 1 note kích thước 8 bytes nội dung là: (print_note address) + (puts_address). Khi gọi PrintNote(0) thì chương trình sẽ in địa chỉ hàm puts cho ta và ta đã leak được libc.
Exploit


