Sandboxie/Sandboxie/core/low/entry_arm.asm

502 lines
14 KiB
NASM

;------------------------------------------------------------------------
; Copyright 2022-2023 David Xanatos, xanasoft.com
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>.
;------------------------------------------------------------------------
AREA |.text|, CODE, READONLY
IMPORT EntrypointC
IMPORT DetourFunc
;EXPORT ServiceDataPtr
EXPORT SystemServiceARM64
EXPORT NtDeviceIoControlFileEC
EXPORT DeviceIoControlSvc
EXPORT EcExitThunkPtr
;EXPORT InjectDataPtr
EXPORT DetourCodeARM64
EXPORT SbieLowData
;----------------------------------------------------------------------------
; break
;----------------------------------------------------------------------------
break PROC
brk #0xF000
ENDP
;----------------------------------------------------------------------------
; Entrypoint at Start
;----------------------------------------------------------------------------
Start PROC
;brk #0xF000
stp x0, x1, [sp, #-0x10]!
stp x2, x3, [sp, #-0x10]!
stp x4, x5, [sp, #-0x10]!
stp x6, x7, [sp, #-0x10]!
stp fp, lr, [sp, #-0x10]!
; EntrypointC()
;ldr x8, =EntrypointC
;ldr x9, =0x180001000 ; Base Address + Segment Offset
;sub x8, x8, x9
;adrp x9, 0
;add x8, x8, x9
;blr x8
bl EntrypointC
mov x8, x0
ldp fp, lr, [sp], #0x10
ldp x6, x7, [sp], #0x10
ldp x4, x5, [sp], #0x10
ldp x2, x3, [sp], #0x10
ldp x0, x1, [sp], #0x10
br x8 ; jump to LdrInitializeThunk trampoline
ENDP
;----------------------------------------------------------------------------
; SystemService
;----------------------------------------------------------------------------
ServiceDataPtr
DCQ 0
SystemServiceARM64 Proc
;brk #0xF000
;
; spill parameters in registers onto the stack
;
stp x6, x7, [sp, #-0x10]!
stp x4, x5, [sp, #-0x10]!
stp x2, x3, [sp, #-0x10]!
stp x0, x1, [sp, #-0x10]!
mov x8, sp ; x8 -> argument stack
ldr x9, ServiceDataPtr ; x9 -> SbieLowData
stp fp, lr, [sp, #-0x10]!
;stp x19, x20, [sp, #-0x10]!
;
; make room for several qwords on the stack:
; ULONG64 arg_9_arg_10_for_NtDeviceIoControlFile[2] (2)
; IO_STATUS_BLOCK IoStatusBlock64; #2 on stack (2)
; ULONG64 IoStatusBlock32; #4 on stack (1)
; ULONG64 parms[API_NUM_ARGS]; #5 on stack (8)
; ULONG64 padding (1)
;
sub sp, sp, (1 + 8 + 1 + 2 + 2) * 8 ; +1 must be 16 aligned !!!
;
; parms[1] = syscall_index
; parms[2] = pointer to system service arguments on stack
; parms[0] = API_INVOKE_SYSCALL (from SbieLowData)
;
add x10, sp, (5*8) ; x10 -> parms
str x17, [x10, (1*8)] ; syscall index
str x8, [x10, (2*8)] ; stack address
ldr w8, [x9, (3*8+4)] ; x8 -> data->api_invoke_syscall
str x8, [x10, (0*8)] ; API_INVOKE_SYSCALL
;
; the 64-bit kernel function for NtDeviceIoControlFile
; expects the 64-bit IoStatusBlock argument to contain a
; 32-bit pointer to a 32-bit IoStatusBlock structure.
; we can allocate the 32-bit structure on the stack
; because the stack is 32-bits in a 32-bit program
;
add x11, sp, (4*8) ; x11 -> IoStatusBlock32
add x12, sp, (2*8) ; x12 -> IoStatusBlock64
str x11, [x12]
;
; invoke SbieLow.NtDeviceIoControlFile(
; data->api_device_handle,
; NULL, NULL, NULL,
; &MyIoStatusBlock,
; API_SBIEDRV_CTLCODE,
; parms,
; API_NUM_ARGS * sizeof(ULONG64),
; NULL, 0);
;
ldr x0, [x9, (2*8)] ; data->api_device_handle
mov x1, #0 ; NULL
mov x2, #0 ; NULL
mov x3, #0 ; NULL
mov x4, x12 ; MyIoStatusBlock64
ldr w5, [x9, (3*8+0)] ; data->api_sbiedrv_ctlcode
mov x6, x10 ; parms
mov x7, (8*8) ; API_NUM_ARGS * sizeof(ULONG64)
mov x8, #0
add x11, sp, 0
str x8, [x11] ; NULL
add x12, sp, 8
str x8, [x12] ; 0
;add x8, x9, #0x80 ; x8 -> SbieLow.NtDeviceIoControlFile_code
add x8, x9, #0xE8 ; x8 -> SbieLow.NtDeviceIoControlFile
ldr x8, [x8]
blr x8
;
; cleanup
;
add sp, sp, (1 + 8 + 1 + 2 + 2) * 8
;ldp x19, x20, [sp], #0x10
ldp fp, lr, [sp], #0x10
add sp, sp, #0x40 ; spilled arguments
ret
ENDP
;----------------------------------------------------------------------------
; MyHandleStubHijack
;----------------------------------------------------------------------------
EcExitThunkPtr
DCQ 0 ; &__os_arm64x_dispatch_call_no_redirect
MyHandleStubHijack PROC
stp x29, x30, [sp, #-0x10]!
mov x29, sp
sub sp, sp, #0x20
mov x8, x0
ldr x16, EcExitThunkPtr
ldr x16, [x16] ; get value of __os_arm64x_dispatch_call_no_redirect
blr x16 ; Call the emulator
b MyHandleStubHijackEnd
DCD 0x00000000
DCD 0x00000000
DCD 0x00000000
DCD 0x05000000
MyHandleStubHijackEnd
nop
mov x0, x8 ; Move return from RAX (x8) to x0
add sp, sp, #0x20
ldp x29, x30, [sp], #0x10
ret
ENDP
;----------------------------------------------------------------------------
; NtDeviceIoControlFileEC
;----------------------------------------------------------------------------
NtDeviceIoControlFileEC PROC
sub sp, sp, #0x10
adrl x16, MyHandleStubHijackEnd ; Put MyHandleStubHijackEnd in x16
str x16, [sp] ; Save address to stack
DeviceIoControlSvc
svc #0x07 ; Issue the sys call
ldr x9, [sp] ; Load address from stack to x9
adrl x16, MyHandleStubHijackEnd ; Again put MyHandleStubHijackEnd in x16
subs x16, x16, x9 ; Compare the addresses
add sp, sp, #0x10
b.ne MyHandleStubHijack ; Jump to MyHandleStubHijack if the address changed
movz x9, #0
ret
ENDP
;----------------------------------------------------------------------------
; detour code loading SbieDll.dll
;----------------------------------------------------------------------------
InjectDataPtr
DCQ 0
DetourCodeARM64 PROC
;brk #0xF000
stp fp, lr, [sp, #-0x10]!
stp x19, x20, [sp, #-0x10]!
sub sp, sp, #0x40
stp x0, x1, [sp, #0x00]
stp x2, x3, [sp, #0x10]
stp x4, x5, [sp, #0x20]
stp x6, x7, [sp, #0x30]
ldr x19, InjectDataPtr ; x19 -> inject data area
;
; call DetourFunc
;
mov x0, x19 ; [x19].InjectData
bl DetourFunc
; cmp x0, #0x00
; bne DetourError
;
; resume execution or original function
;
ldp x0, x1, [sp, #0x00]
ldp x2, x3, [sp, #0x10]
ldp x4, x5, [sp, #0x20]
ldp x6, x7, [sp, #0x30]
ldr x8, [x19, 0x08] ; [x19].InjectData.RtlFindActCtx
add sp, sp, #0x40
ldp x19, x20, [sp], #0x10
ldp fp, lr, [sp], #0x10
br x8
;DetourError
;
; add sp, sp, #0x40
; ldp x19, x20, [sp], #0x10
; ldp fp, lr, [sp], #0x10
;
; ret
ENDP
;;----------------------------------------------------------------------------
;; RtlFindActivationContextSectionString detour code
;;----------------------------------------------------------------------------
;
;
;InjectDataPtr
; DCQ 0
;DetourCodeARM64 PROC
;
; ;brk #0xF000
;
; stp fp, lr, [sp, #-0x10]!
; stp x19, x20, [sp, #-0x10]!
; sub sp, sp, #0x40
;
; stp x0, x1, [sp, #0x00]
; stp x2, x3, [sp, #0x10]
; stp x4, x5, [sp, #0x20]
; stp x6, x7, [sp, #0x30]
;
; ldr x19, InjectDataPtr ; x19 -> inject data area
;
; ;
; ; reatore RtlFindActCtx, copy 16 bytes
; ;
;
; add x8, x19, #0x20 ; [x19].InjectData.RtlFindActCtx
; ldr x9, [x8]
; ldp w10, w11, [x19, #0x2C] ; [x19].InjectData.RtlFindActCtx_Bytes
; stp w10, w11, [x9, #0x00]
; ldp w10, w11, [x19, #0x34] ; [x19].InjectData.RtlFindActCtx_Bytes + 8
; stp w10, w11, [x9, #0x08]
;
; ldr x0, =0xFFFFFFFFFFFFFFFF ; ProcessHandle
; mov x1, x9 ; BaseAddress
; mov x2, #0x10 ; NumberOfBytesToFlush
;
; ;ldr x8, [x19, 0x70] ; [x19].InjectData.NtFlushInstructionCache
; ldr x9, [x19] ; [x19].InjectData.SBIELOW_DATA
; add x8, x9, 0xA0 ; SBIELOW_DATA.NtFlushInstructionCache_code
; blr x8
;
; ;
; ; call LdrLoadDll for kernel32
; ;
;
; mov x20, #0x10 ; retry count
;
;LdrLoadRetry
; mov x0, #0x00 ; PathToFile
; mov x1, #0x00 ; Flags
; add x2, x19, 0x40 ; [x19].InjectData.KernelDll_Unicode
; add x3, x19, 0x60 ; [x19].InjectData.ModuleHandle
;
; ldr x8, [x19, 0x08] ; [x19].InjectData.LdrLoadDll
; blr x8
;
; cmp x0, #0x00
; beq LdrLoadGood
; sub x20, x20, #0x01
; cmp x20, #0x00
; bne LdrLoadRetry
; b RtlFindActivationContextSectionStringError
;
;LdrLoadGood
; ;
; ; call LdrLoadDll for sbiedll
; ;
;
; mov x0, #0x00 ; PathToFile
; mov x1, #0x00 ; Flags
; add x2, x19, 0x50 ; [x19].InjectData.SbieDll_Unicode
; add x3, x19, 0x60 ; [x19].InjectData.ModuleHandle
;
; ldr x8, [x19, 0x08] ; [x19].InjectData.LdrLoadDll
; blr x8
; cmp x0, #0x00
; bne RtlFindActivationContextSectionStringError
;
; ;
; ; call the custom MyGetProcedureAddress implemented in c
; ; which calls LdrGetProcedureAddress for sbiedll ordinal 1,
; ; this forces ntdll to initialize sbiedll and returns the address to call
; ;
; ; in ARM64EC mode it returns the native function address instead of the FFS sequence
; ;
;
; ldr x0, [x19, 0x60] ; [x19].InjectData.ModuleHandle
; mov x1, #0x00 ; FunctionName
; mov x2, #0x01 ; Ordinal
; add x3, x19, 0x68 ; [x19].InjectData.SbieDllOrdinal1
; mov x4, x19 ; [x19].InjectData
;
; ;ldr x8, [x19, 0x10] ; [x19].InjectData.LdrGetProcAddr
; ldr x8, [x19, 0x70] ; [x19].InjectData.MyGetProcAddr
; blr x8
; cmp x0, #0x00
; bne RtlFindActivationContextSectionStringError
;
; ;
; ; pass control to ordinal 1, which will free the inject
; ; data area, and pass control to the original function
; ; RtlFindActivationContextSectionString
; ;
; ; note that we need to pass the address of the inject
; ; data area to ordinal 1, which we do by overwriting the
; ; first argument. the original argument is saved in
; ; the inject data area
; ;
;
; ldr x8, [sp, #0x00]
; str x8, [x19, 0x08] ; [x19].InjectData.LdrLoadDll
; mov x0, x19
; ldr x1, [sp, #0x08]
; ldp x2, x3, [sp, #0x10]
; ldp x4, x5, [sp, #0x20]
; ldp x6, x7, [sp, #0x30]
;
; ldr x8, [x19, 0x68] ; [x19].InjectData.SbieDllOrdinal1
;
; add sp, sp, #0x40
; ldp x19, x20, [sp], #0x10
; ldp fp, lr, [sp], #0x10
;
; br x8
;
;RtlFindActivationContextSectionStringError
;
; str x0, [sp, #0x38] ; save ntstatus
;
; add x8, x19, 0x50 ; [x19].InjectData.SbieDll_Unicode
; str x8, [x19, 0x08] ; [x19].InjectData.LdrLoadDll
;
; add x5, x19, 0x10 ; out_response - [x19].InjectData.LdrGetProcAddr
; mov x4, #0x01 ; response_buttons - ERROR_OK
; mov x3, x8 ; list_of_pointers_to_parameters
; mov x2, #0x01 ; mask_of_strings_in_list
; mov x1, #0x01 ; number_of_parameters_in_list
; ldr x0, =0xD0000142 ; ntstatus_message_code - (STATUS_DLL_INIT_FAILED or FORCE_ERROR_MESSAGE_BOX)
;
; ldr x8, [x19, 0x18] ; [x19].InjectData.LdrGetProcAddr
; blr x8
;
; ldr x0, [sp, #0x38] ; restore ntstatus
;
; add sp, sp, #0x40
; ldp x19, x20, [sp], #0x10
; ldp fp, lr, [sp], #0x10
;
; ret
;
; ENDP
;----------------------------------------------------------------------------
; Parameters stored by SbieSvc
;----------------------------------------------------------------------------
ALIGN 8
SbieLowData
; at least sizeof(SBIELOW_DATA)
DCQ 0,0,0,0,0,0,0,0
DCQ 0,0,0,0,0,0,0,0
DCQ 0,0,0,0,0,0,0,0
DCQ 0,0,0,0,0,0,0,0
DCQ 0,0,0,0,0,0,0,0
DCQ 0,0,0,0,0,0,0,0
DCQ 0,0,0,0,0,0,0,0
DCQ 0,0,0,0,0,0,0,0
;----------------------------------------------------------------------------
; Tail Signature
;----------------------------------------------------------------------------
AREA |zzzzz|, DATA, READONLY
DCQ Start ; entry point for the detour
DCQ SbieLowData ; data location
DCQ DetourCodeARM64 ; detour code location
;----------------------------------------------------------------------------
END