Skip to content

Some useful commands and template when doing kernel pwn challenges

Notifications You must be signed in to change notification settings

yifengchen-cc/Kernel-PWN-Cheat-Sheet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 

Repository files navigation

Kernel PWN Cheat Sheet

Some useful commands when doing kernel pwn challenges

Pack/Unpack rootfs

#pack
$ mkdir output
$ cd output
$ file rootfs.cpio 
rootfs.cpio: gzip compressed data, last modified: Tue Nov 12 01:43:34 2019, from Unix
/output$ cp ../rootfs.cpio rootfs.cpio.gz
/output$ gunzip rootfs.cpio.gz
/output$ cpio -idmv < rootfs.cpio
#unpack
/output$ find . | cpio -o --format=newc | gzip -c  > ../rootfs.cpio

Extract vmlinux from bzImage:

$ /usr/src/linux-headers-4.4.0-31/scripts/extract-vmlinux bzImage >> vmlinux

Check whether the environment KPTI is turned on:

If there is -cpu kvm64,+smep in the qemu startup script, it means that KPTI is enabled in the environment.

Or enter the following command after opening the challenge environment(root privilege required):

/ # dmesg | grep 'page table'
[    0.712632] Kernel/User page tables isolation: enabled
/ # cat /proc/cpuinfo | grep pti
fpu_exception	: yes
flags		: ... pti smep smap

gdb debug template (KASLR should be closed) :

gdb \
	-ex 'set arch i386:x86-64' \
    -ex 'target remote localhost:1234'\
	-ex 'file vmlinux' \
    -ex 'add-symbol-file output/module.ko 0xffffffffc0002000'\ 
    #use 'cat /proc/modules | grep module' to find base address of target module.

Find the size of a structure in the kernel (source code needed):

$sudo apt install dwarves
$pahole -C packet_sock ./linux-5.6/vmlinux
die__process_function: tag not supported (INVALID)!
struct packet_sock {
	struct sock                sk;                   /*     0   752 */
	/* --- cacheline 11 boundary (704 bytes) was 48 bytes ago --- */
	struct packet_fanout *     fanout;               /*   752     8 */
	union tpacket_stats_u      stats;                /*   760    12 */

	/* XXX 4 bytes hole, try to pack */

	/* --- cacheline 12 boundary (768 bytes) was 8 bytes ago --- */
	struct packet_ring_buffer  rx_ring;              /*   776   192 */
	/* --- cacheline 15 boundary (960 bytes) was 8 bytes ago --- */
	struct packet_ring_buffer  tx_ring;              /*   968   192 */
	/* --- cacheline 18 boundary (1152 bytes) was 8 bytes ago --- */
	int                        copy_thresh;          /*  1160     4 */
	spinlock_t                 bind_lock;            /*  1164     4 */
	struct mutex               pg_vec_lock;          /*  1168    32 */
	unsigned int               running;              /*  1200     4 */
	unsigned int               auxdata:1;            /*  1204:31  4 */
	unsigned int               origdev:1;            /*  1204:30  4 */
	unsigned int               has_vnet_hdr:1;       /*  1204:29  4 */
	unsigned int               tp_loss:1;            /*  1204:28  4 */
	unsigned int               tp_tx_has_off:1;      /*  1204:27  4 */

	/* XXX 27 bits hole, try to pack */

	int                        pressure;             /*  1208     4 */
	int                        ifindex;              /*  1212     4 */
	/* --- cacheline 19 boundary (1216 bytes) --- */
	__be16                     num;                  /*  1216     2 */

	/* XXX 6 bytes hole, try to pack */

	struct packet_rollover *   rollover;             /*  1224     8 */
	struct packet_mclist *     mclist;               /*  1232     8 */
	atomic_t                   mapped;               /*  1240     4 */
	enum tpacket_versions      tp_version;           /*  1244     4 */
	unsigned int               tp_hdrlen;            /*  1248     4 */
	unsigned int               tp_reserve;           /*  1252     4 */
	unsigned int               tp_tstamp;            /*  1256     4 */

	/* XXX 4 bytes hole, try to pack */

	struct completion          skb_completion;       /*  1264    32 */
	/* --- cacheline 20 boundary (1280 bytes) was 16 bytes ago --- */
	struct net_device *        cached_dev;           /*  1296     8 */
	int                        (*xmit)(struct sk_buff *); /*  1304     8 */

	/* XXX 32 bytes hole, try to pack */

	/* --- cacheline 21 boundary (1344 bytes) --- */
	struct packet_type         prot_hook;            /*  1344    64 */
	/* --- cacheline 22 boundary (1408 bytes) --- */
	atomic_t                   tp_drops;             /*  1408     4 */

	/* size: 1472, cachelines: 23, members: 29 */
	/* sum members: 1366, holes: 4, sum holes: 46 */
	/* bit holes: 1, sum bit holes: 27 bits */
	/* padding: 60 */
};

Find the address of a kernel function:

# cat /proc/kallsyms | grep "commit_creds"
# cat /proc/kallsyms | grep "prepare_kernel_cred"

Use ropper to get some useful gadgets:

$ ropper --file ./vmlinux --all --nocolor >> gadget

The exp file is too large after glibc static compilation:

We can use the musl library to compile, apt-get can be installed directly under ubuntu, or refer to Official Website to compile and install:

$ sudo apt-get install musl
$ sudo apt-get install musl-tools

Let's compare the file size after static compilation with gcc and musl-gcc:

$ musl-gcc exp2.c -o exp2 --static
$ ls -al | grep exp2
-rwxr-xr-x  1 ivan ivan  50800 Jan 13 03:44 exp2
$ gcc exp2.c -o exp2 --static
$ ls -al | grep exp2
-rwxr-xr-x  1 ivan ivan 859080 Jan 13 18:16 exp2

Remote interactive python script template:

#!/usr/bin/env python2
from __future__ import print_function
from pwn import *
import sys
#context.proxy = (socks.SOCKS5,'test',9381)

def main():
    host = sys.argv[1]
    port = int(sys.argv[2])
    conn = remote(host, port)
    PROMPT = b"/ $ "
    result = conn.recvuntil(PROMPT)
    print("Received before the first prompt:", result, file=sys.stderr)
    xblob = ""
    with open("./poc.bz2", "r") as f:
      xblob = f.read()
    for line in xblob.encode('base64').split('\n'):
      conn.sendline("echo \"%s\" >> /tmp/x.bz2.64" % line)
      conn.recvuntil(PROMPT)
    print("Exploit blob %d bytes" % len(xblob.encode('base64')), file=sys.stderr)
    conn.sendline("base64 -d /tmp/x.bz2.64 > /tmp/x.bz2")
    conn.recvuntil(PROMPT)
    conn.sendline("bunzip2 /tmp/x.bz2")
    conn.recvuntil(PROMPT)
    conn.sendline("chmod 777 /tmp/x")
    conn.recvuntil(PROMPT)
    conn.sendline("ls -l /tmp")
    result = conn.recvuntil(PROMPT)
    print("ls -l /tmp:",result,file=sys.stderr)
    conn.sendline("/tmp/x")
    result = conn.recvuntil(b"/ # ")
    print("Catting flag..",file=sys.stderr)
    conn.sendline("cat /root/flag")
    result = conn.recvuntil(b"}")
    print("flag:",result)
    sys.exit(0)

if __name__ == '__main__':
    main()

About

Some useful commands and template when doing kernel pwn challenges

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published