Module: Msf::Payload::Windows::Exitfunk

Included in:
BindNamedPipe, BindTcp, ReverseHttp, ReverseNamedPipe, ReverseTcp
Defined in:
lib/msf/core/payload/windows/exitfunk.rb

Overview

Implements arbitrary exit routines for Windows ARCH_X86 payloads

Instance Method Summary collapse

Instance Method Details

#asm_exitfunk(opts = {}) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/msf/core/payload/windows/exitfunk.rb', line 13

def asm_exitfunk(opts={})

  asm = "exitfunk:\n"

  case opts[:exitfunk]

  when 'seh'
    asm << %Q^
      mov ebx, 0x#{Msf::Payload::Windows.exit_types['seh'].to_s(16)}
      push.i8 0              ; push the exit function parameter
      push ebx               ; push the hash of the exit function
      call ebp               ; SetUnhandledExceptionFilter(0)
      push.i8 0
      ret                    ; Return to NULL (crash)
    ^

  # On Windows Vista, Server 2008, and newer, it is not possible to call ExitThread
  # on WoW64 processes, instead we need to call RtlExitUserThread. This stub will
  # automatically generate the right code depending on the selected exit method.

  when 'thread'
    asm << %Q^
      mov ebx, 0x#{Msf::Payload::Windows.exit_types['thread'].to_s(16)}
      push #{Rex::Text.block_api_hash("kernel32.dll", "GetVersion")}        ; hash( "kernel32.dll", "GetVersion" )
      call ebp               ; GetVersion(); (AL will = major version and AH will = minor version)
      cmp al, 6              ; If we are not running on Windows Vista, 2008 or 7
      jl exitfunk_goodbye    ; Then just call the exit function...
      cmp bl, 0xE0           ; If we are trying a call to kernel32.dll!ExitThread on Windows Vista, 2008 or 7...
      jne exitfunk_goodbye   ;
      mov ebx, #{Rex::Text.block_api_hash("ntdll.dll", "RtlExitUserThread")}     ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
    exitfunk_goodbye:        ; We now perform the actual call to the exit function
      push.i8 0              ; push the exit function parameter
      push ebx               ; push the hash of the exit function
      call ebp               ; call ExitThread(0) || RtlExitUserThread(0)
    ^

  when 'process', nil
    asm << %Q^
      mov ebx, 0x#{Msf::Payload::Windows.exit_types['process'].to_s(16)}
      push.i8 0              ; push the exit function parameter
      push ebx               ; push the hash of the exit function
      call ebp               ; ExitProcess(0)
    ^

  when 'sleep'
    asm << %Q^
      mov ebx, #{Rex::Text.block_api_hash('kernel32.dll', 'Sleep')}
      push 300000            ; 300 seconds
      push ebx               ; push the hash of the function
      call ebp               ; Sleep(300000)
      jmp exitfunk           ; repeat
    ^
  else
    # Do nothing and continue after the end of the shellcode
  end

  asm
end