Đăng trong Pwnable.tw

[Pwnable.tw] – hacknote

Challenge

1

file

1.png

checksec

1.png

run binary

1.png1.png


IDA

main()

1.png

AddNote()

1.png

print_note()

1

DeleteNote()

1.png

PrintNote()

1.png

Struct NOTE

1


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:

1.png

Ta thấy trên heap lúc này có 4 chunk tương ứng với 2 note:

  1. 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).
  2. chunk 1: notes_list[0].content: 0x804b010: nội dung notes_list[0]: ‘AAAA’
  3. chunk 2: notes_list[1]: 0x804b028: tương tự chunk 0.
  4. chunk 3: notes_list[1].content: 0x804b038: nội dung notes_list[1]: ‘BBBB’
  5. 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

1.png

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

1.png

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

1.png1.png

1.png

Bình luận về bài viết này