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

[View source] [View on GitHub]

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