diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bed7ec4..31d624df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [1.10.0 / 5.65.0] - 2023-07-?? ### Added +- added box scripting engine to make sandman more flexible - added scriptable troubleshooting wizard [#1875](https://github.com/sandboxie-plus/Sandboxie/issues/1875) - added addon manager which helps to install additional and third-party components, available addons: - [ImDisk Toolkit](https://sourceforge.net/projects/imdisk-toolkit/) - used to create RAM Disks and other virtual drives @@ -23,24 +24,30 @@ This project adheres to [Semantic Versioning](http://semver.org/). - added option to set the update interval to 1, 7, 14 and 30 days - added `What's new in Sandboxie-Plus` dialog in SbieCtrl.exe to praise the new features of the Plus UI - Note: this is shown after the installation of Sandboxie Classic +- added "fixdacls" command to KmdUtil.exe it repairs broken DACL entries on the SbieHome folder to fix issues where SbieDll.dll fails to load ### Changed - setup wizard has now a dedicated update configuration page + - this page will be shown for all users once which do not have updates enabled - split the support page into Sandboxie Support and Sandboxie Updater tabs - when the troubleshooting.7z file is available, the script engine will be used to match compatibility templates - this allows a better granularity in template selection by using the AppCompatibility.js script +- reworked low level code injection mechanism to improve flexibility and debugging + - the main injection detour code is now writen in C instead of Assembler and can proeprly report SbieDll.dll load errors as SBIE2181 - improved session agent startup to be more flexible - improved SBIEMSG help handling ### Fixed - fixed uninstall issue in the Sandboxie Classic installer [d1863ff](https://github.com/sandboxie-plus/Sandboxie/commit/d1863ffadfe105c695de71c9e841c2fd568116fe) - added workaround for Chrome not starting on Windows 11 with KB5027231 [#3040](https://github.com/sandboxie-plus/Sandboxie/issues/3040) +- improved compatybility with procmon/stack traces for debug builds ### Removed - cleaned up duplicate code (thanks lmou523) [#3067](https://github.com/sandboxie-plus/Sandboxie/pull/3067) + ## [1.9.8 / 5.64.8] - 2023-06-21 ### Changed diff --git a/Sandboxie/core/dll/dll.h b/Sandboxie/core/dll/dll.h index d3da84bc..ae815e5e 100644 --- a/Sandboxie/core/dll/dll.h +++ b/Sandboxie/core/dll/dll.h @@ -281,10 +281,10 @@ extern ULONG64 Dll_ProcessFlags; #ifndef _WIN64 extern BOOLEAN Dll_IsWow64; #endif -#ifdef _M_X64 +#ifdef _M_ARM64EC extern BOOLEAN Dll_IsArm64ec; #endif -#ifndef _M_ARM64 +#ifndef _WIN64 extern BOOLEAN Dll_IsXtAjit; #endif extern BOOLEAN Dll_IsSystemSid; diff --git a/Sandboxie/core/dll/dllmain.c b/Sandboxie/core/dll/dllmain.c index e45f018a..b271be24 100644 --- a/Sandboxie/core/dll/dllmain.c +++ b/Sandboxie/core/dll/dllmain.c @@ -90,10 +90,10 @@ ULONG64 Dll_ProcessFlags = 0; #ifndef _WIN64 BOOLEAN Dll_IsWow64 = FALSE; #endif -#ifdef _M_X64 +#ifdef _M_ARM64EC BOOLEAN Dll_IsArm64ec = FALSE; #endif -#ifndef _M_ARM64 +#ifndef _WIN64 BOOLEAN Dll_IsXtAjit = FALSE; #endif BOOLEAN Dll_IsSystemSid = FALSE; @@ -772,46 +772,20 @@ _FX void Dll_SelectImageType(void) //--------------------------------------------------------------------------- -_FX ULONG_PTR Dll_Ordinal1( - ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, - ULONG_PTR arg4, ULONG_PTR arg5) +_FX VOID Dll_Ordinal1(INJECT_DATA * inject) { - typedef ULONG_PTR (*P_RtlFindActivationContextSectionString)( - ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, - ULONG_PTR arg4, ULONG_PTR arg5); - P_RtlFindActivationContextSectionString RtlFindActCtx; - -#if defined(_M_ARM64) || defined(_M_ARM64EC) - // - // on ARM64 we hook LdrLoadDll instead, using the prototype for - // RtlFindActCtx is fine though as arguments 1-8 are passed in registers - // so if we set x4 or not does not matter in the least - // -#endif - - INJECT_DATA *inject; - SBIELOW_DATA *data; - ULONG dummy_prot; + SBIELOW_DATA *data = (SBIELOW_DATA *)inject->sbielow_data; BOOLEAN bHostInject = FALSE; - - extern HANDLE SbieApi_DeviceHandle; - - // - // this code is invoked from our RtlFindActivationContextSectionString - // hook in core/low/entry.asm, with a parameter that points to the - // syscall/inject data area. the first ULONG64 in this data area - // includes a pointer to the SbieLow data area - // - - inject = (struct _INJECT_DATA *)arg1; - - data = (SBIELOW_DATA *)inject->sbielow_data; SbieApi_data = data; #ifdef _M_ARM64EC + // get the pointer to sys_call_list in the SYS_CALL_DATA struct SbieApi_SyscallPtr = (ULONG*)((ULONG64)data->syscall_data + sizeof(ULONG) + sizeof(ULONG) + (NATIVE_FUNCTION_SIZE * NATIVE_FUNCTION_COUNT)); #endif + extern HANDLE SbieApi_DeviceHandle; + SbieApi_DeviceHandle = (HANDLE)data->api_device_handle; + // // the SbieLow data area includes values that are useful to us // so we copy them into dedicated variables if we are going to use them more often @@ -820,38 +794,15 @@ _FX ULONG_PTR Dll_Ordinal1( bHostInject = data->flags.bHostInject == 1; #ifndef _WIN64 - Dll_IsWow64 = data->flags.is_wow64 == 1; + Dll_IsWow64 = data->flags.is_wow64 == 1; // x86 on x64 or arm64 #endif -#ifdef _M_X64 - Dll_IsArm64ec = data->flags.is_arm64ec == 1; +#ifdef _M_ARM64EC + Dll_IsArm64ec = data->flags.is_arm64ec == 1; // x64 on arm64 #endif -#ifndef _M_ARM64 - Dll_IsXtAjit = data->flags.is_xtajit == 1; +#ifndef _WIN64 + Dll_IsXtAjit = data->flags.is_xtajit == 1; // x86 on arm64 #endif - SbieApi_DeviceHandle = (HANDLE)data->api_device_handle; - - // - // our RtlFindActivationContextSectionString hook already restored - // the original bytes, but we should still restore the page protection - // - - VirtualProtect((void *)(ULONG_PTR)inject->RtlFindActCtx, 5, - inject->RtlFindActCtx_Protect, &dummy_prot); - - arg1 = (ULONG_PTR)inject->RtlFindActCtx_SavedArg1; - - RtlFindActCtx = (P_RtlFindActivationContextSectionString) - inject->RtlFindActCtx; - - // - // make sbielow_data read only, as it contsins required - // nt dll function copies it must stay executive - // - - VirtualProtect((void *)data, sizeof(SBIELOW_DATA), - PAGE_EXECUTE_READ, &dummy_prot); - if (!bHostInject) { @@ -928,25 +879,6 @@ _FX ULONG_PTR Dll_Ordinal1( { Ldr_Inject_Init(TRUE); } - - // - // free the syscall/inject data area which is no longer needed - // - -#ifdef _M_ARM64EC - SbieApi_SyscallPtr = NULL; -#endif - VirtualFree(inject, 0, MEM_RELEASE); - - - // - // conclude the detour by passing control back to the original - // RtlFindActivationContextSectionString. the detour code used - // jump rather than call to invoke this function (see entry.asm) - // so RtlFindActivationContextSectionString returns to its caller - // - - return RtlFindActCtx(arg1, arg2, arg3, arg4, arg5); } diff --git a/Sandboxie/core/dll/file_del.c b/Sandboxie/core/dll/file_del.c index f86d0347..6dff6d39 100644 --- a/Sandboxie/core/dll/file_del.c +++ b/Sandboxie/core/dll/file_del.c @@ -412,7 +412,7 @@ _FX VOID File_SavePathTree_internal(LIST* Root, const WCHAR* name) HANDLE hPathsFile; IO_STATUS_BLOCK IoStatusBlock; - if (!NT_SUCCESS(NtCreateFile(&hPathsFile, GENERIC_WRITE | SYNCHRONIZE , &objattrs, &IoStatusBlock, NULL, 0, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, NULL, 0))) + if (!NT_SUCCESS(NtCreateFile(&hPathsFile, GENERIC_WRITE | SYNCHRONIZE, &objattrs, &IoStatusBlock, NULL, 0, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, NULL, 0))) return; WCHAR* Path = (WCHAR *)Dll_Alloc((0x7FFF + 1)*sizeof(WCHAR)); // max nt path diff --git a/Sandboxie/core/dll/file_snapshots.c b/Sandboxie/core/dll/file_snapshots.c index 53ea4e55..3f3a6cef 100644 --- a/Sandboxie/core/dll/file_snapshots.c +++ b/Sandboxie/core/dll/file_snapshots.c @@ -36,7 +36,7 @@ typedef struct _FILE_SNAPSHOT { WCHAR ID[FILE_MAX_SNAPSHOT_ID]; ULONG IDlen; ULONG ScramKey; - //WCHAR Name[34]; + //WCHAR Name[BOXNAME_COUNT]; struct _FILE_SNAPSHOT* Parent; LIST PathRoot; } FILE_SNAPSHOT, *PFILE_SNAPSHOT; @@ -480,8 +480,8 @@ _FX void File_InitSnapshots(void) File_LoadPathTree_internal(&Cur_Snapshot->PathRoot, PathFile); } - //WCHAR SnapshotName[34] = { 0 }; - //GetPrivateProfileStringW(SnapshotId, L"Name", L"", SnapshotName, 34, SnapshotsIni); + //WCHAR SnapshotName[BOXNAME_COUNT] = { 0 }; + //GetPrivateProfileStringW(SnapshotId, L"Name", L"", SnapshotName, BOXNAME_COUNT, SnapshotsIni); //wcscpy(Cur_Snapshot->Name, SnapshotName); GetPrivateProfileStringW(SnapshotId, L"Parent", L"", Snapshot, 16, SnapshotsIni); diff --git a/Sandboxie/core/dll/ldr.c b/Sandboxie/core/dll/ldr.c index a8ca613c..fe15c629 100644 --- a/Sandboxie/core/dll/ldr.c +++ b/Sandboxie/core/dll/ldr.c @@ -282,22 +282,15 @@ void CALLBACK Ldr_LdrDllNotification(ULONG NotificationReason, PLDR_DLL_NOTIFICA { ULONG_PTR LdrCookie = 0; NTSTATUS status = 0; - WCHAR text[4096]; if (NotificationReason == 1) { status = __sys_LdrLockLoaderLock(0, NULL, &LdrCookie); Ldr_MyDllCallbackNew(NotificationData->Loaded.BaseDllName->Buffer, (HMODULE)NotificationData->Loaded.DllBase, TRUE); __sys_LdrUnlockLoaderLock(0, LdrCookie); - - Sbie_snwprintf(text, ARRAYSIZE(text), L"%s (loaded)", NotificationData->Loaded.BaseDllName->Buffer); } else if (NotificationReason == 2) { Ldr_MyDllCallbackNew(NotificationData->Unloaded.BaseDllName->Buffer, (HMODULE)NotificationData->Loaded.DllBase, FALSE); - - Sbie_snwprintf(text, ARRAYSIZE(text), L"%s (unloaded)", NotificationData->Loaded.BaseDllName->Buffer); } - - SbieApi_MonitorPutMsg(MONITOR_IMAGE, text); } //--------------------------------------------------------------------------- @@ -1090,19 +1083,25 @@ _FX void Ldr_MyDllCallbackA(const CHAR *ImageName, HMODULE ImageBase, BOOL LoadS WCHAR ImageNameW[128]; Sbie_snwprintf(ImageNameW, ARRAYSIZE(ImageNameW), L"%S", ImageName); - Ldr_MyDllCallbackW(ImageNameW, ImageBase, LoadState); + Ldr_MyDllCallbackNew(ImageNameW, ImageBase, LoadState); } _FX void Ldr_MyDllCallbackW(const WCHAR *ImageName, HMODULE ImageBase, BOOL LoadState) // Windows XP { - // call new function - Ldr_MyDllCallbackNew(ImageName, ImageBase, LoadState); + Ldr_MyDllCallbackNew(ImageName, ImageBase, LoadState); } _FX void Ldr_MyDllCallbackNew(const WCHAR *ImageName, HMODULE ImageBase, BOOL LoadState) // Windows 8.1 and later { + WCHAR text[4096]; + if(LoadState) + Sbie_snwprintf(text, ARRAYSIZE(text), L"%s (loaded)", ImageName); + else + Sbie_snwprintf(text, ARRAYSIZE(text), L"%s (unloaded)", ImageName); + SbieApi_MonitorPutMsg(MONITOR_IMAGE, text); + // // invoke our sub-modules as necessary // @@ -1187,12 +1186,12 @@ _FX void *Ldr_GetProcAddrOld(const WCHAR *DllName, const WCHAR *ProcNameW) _FX void *Ldr_GetProcAddrNew(const WCHAR *DllName, const WCHAR *ProcNameW, char * ProcNameA) { NTSTATUS status; - void *proc; + void *proc = NULL; // char buffer[768]; // sprintf(buffer,"GetProcAddrNew: DllName = %S, ProcW = %S, ProcA = %s\n",DllName,ProcNameW,ProcNameA); // OutputDebugStringA(buffer); - if (Dll_OsBuild < 9600) { + if (Dll_OsBuild < 9600) { // Windows 8.0 or earlier proc = Ldr_GetProcAddr_2(DllName, ProcNameW); if (!proc) { ULONG_PTR LdrCookie; @@ -1223,7 +1222,7 @@ _FX void *Ldr_GetProcAddrNew(const WCHAR *DllName, const WCHAR *ProcNameW, char } } } - else { + else { // Windows 8.1 and later HMODULE DllBase; DllBase = GetModuleHandle(DllName); if (!DllBase) { diff --git a/Sandboxie/core/dll/ldr_init.c b/Sandboxie/core/dll/ldr_init.c index 292a49c9..39c4612c 100644 --- a/Sandboxie/core/dll/ldr_init.c +++ b/Sandboxie/core/dll/ldr_init.c @@ -22,6 +22,7 @@ #include "dll.h" +#include "core/low/lowdata.h" #include @@ -880,6 +881,22 @@ _FX void* Ldr_Inject_Entry(ULONG_PTR *pPtr) { Ldr_LoadInjectDlls(g_bHostInject); } + + + // + // free the syscall/inject data area which is no longer needed + // + +#ifdef _M_ARM64EC + extern ULONG* SbieApi_SyscallPtr; + SbieApi_SyscallPtr = NULL; +#endif + extern SBIELOW_DATA* SbieApi_data; + VirtualFree((void*)SbieApi_data->syscall_data, 0, MEM_RELEASE); + + // + // return original entry point address to jump to + // return entrypoint; } diff --git a/Sandboxie/core/dll/lowlevel.rc b/Sandboxie/core/dll/lowlevel.rc index e2968b64..347cf8fd 100644 --- a/Sandboxie/core/dll/lowlevel.rc +++ b/Sandboxie/core/dll/lowlevel.rc @@ -1,4 +1,5 @@ // Copyright 2004-2020 Sandboxie Holdings, LLC +// Copyright 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 @@ -54,11 +55,10 @@ #ifdef BUILD_UTILITY_PASS2 #if MY_ARM64_FLAG -LOWLEVEL RCDATA "../low/obj/ARM64/LowLevel.dll" +LOWLEVEL64 RCDATA "../low/obj/ARM64/LowLevel.dll" #elif MY_WIN64_FLAG -LOWLEVEL RCDATA "../low/obj/amd64/LowLevel.dll" -#else -LOWLEVEL RCDATA "../low/obj/i386/LowLevel.dll" +LOWLEVEL64 RCDATA "../low/obj/amd64/LowLevel.dll" #endif // MY_WIN64_FLAG +LOWLEVEL32 RCDATA "../low/obj/i386/LowLevel.dll" #endif // BUILD_UTILITY_PASS2 diff --git a/Sandboxie/core/dll/lowlevel_inject.c b/Sandboxie/core/dll/lowlevel_inject.c index 304b65c3..c5eb2016 100644 --- a/Sandboxie/core/dll/lowlevel_inject.c +++ b/Sandboxie/core/dll/lowlevel_inject.c @@ -1,6 +1,6 @@ /* * Copyright 2004-2020 Sandboxie Holdings, LLC - * Copyright 2020-2022 David Xanatos, xanasoft.com + * Copyright 2020-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 @@ -48,6 +48,7 @@ typedef struct _MY_TARGETS { unsigned long long entry; unsigned long long data; + unsigned long long detour; } MY_TARGETS; #ifdef _M_ARM64 @@ -85,7 +86,7 @@ typedef PVOID (*P_VirtualAlloc2)( SBIEDLL_EXPORT HANDLE SbieDll_InjectLow_SendHandle(HANDLE hProcess); void *SbieDll_InjectLow_CopyCode( - HANDLE hProcess, SIZE_T lowLevel_size, UCHAR *code, ULONG code_len + HANDLE hProcess, SIZE_T total_size, SIZE_T lowLevel_size, const void* lowLevel_ptr #ifdef _M_ARM64 , BOOLEAN use_arm64ec #endif @@ -129,11 +130,16 @@ ULONG Hook_GetSysCallFunc(ULONG* aCode, void** pHandleStubHijack); void *m_sbielow_ptr = NULL; +ULONG m_sbielow_len = 0; //adding two offsets variables to replace the "head" and "tail" dependency ULONG m_sbielow_start_offset = 0; ULONG m_sbielow_data_offset = 0; -ULONG m_sbielow_len = 0; +#ifdef _WIN64 +void *m_sbielow32_ptr = NULL; +ULONG m_sbielow32_len = 0; +ULONG m_sbielow32_detour_offset = 0; +#endif ULONG *m_syscall_data = NULL; @@ -149,19 +155,19 @@ P_VirtualAlloc2 __sys_VirtualAlloc2 = NULL; #endif -#include "core/low/lowlevel_code.c" //--------------------------------------------------------------------------- -// InjectLow_InitHelper +// SbieDll_InjectLow_LoadLow //--------------------------------------------------------------------------- -_FX ULONG SbieDll_InjectLow_InitHelper() +_FX ULONG SbieDll_InjectLow_LoadLow(BOOLEAN arch_64bit, void **sbielow_ptr, ULONG *sbielow_len, ULONG *start_offset, ULONG* data_offset, ULONG* detour_offset) { // // lock the SbieLow resource (embedded within the SbieSvc executable, // see lowlevel.rc) and find the offset to executable code, and length // + IMAGE_DOS_HEADER *dos_hdr = 0; IMAGE_NT_HEADERS *nt_hdrs = 0; IMAGE_SECTION_HEADER *section = 0; @@ -171,8 +177,8 @@ _FX ULONG SbieDll_InjectLow_InitHelper() ULONG errlvl = 0x11; - HRSRC hrsrc = FindResource(Dll_Instance, L"LOWLEVEL", RT_RCDATA); - if (! hrsrc) + HRSRC hrsrc = FindResource(Dll_Instance, arch_64bit ? L"LOWLEVEL64" : L"LOWLEVEL32", RT_RCDATA); + if (! hrsrc) return errlvl; ULONG binsize = SizeofResource(Dll_Instance, hrsrc); @@ -193,44 +199,33 @@ _FX ULONG SbieDll_InjectLow_InitHelper() if (dos_hdr->e_magic == 'MZ' || dos_hdr->e_magic == 'ZM') { nt_hdrs = (IMAGE_NT_HEADERS *)((UCHAR *)dos_hdr + dos_hdr->e_lfanew); - if (nt_hdrs->Signature == IMAGE_NT_SIGNATURE) { // 'PE\0\0' -#ifndef _WIN64 - if (nt_hdrs->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - IMAGE_NT_HEADERS32 *nt_hdrs_32 = (IMAGE_NT_HEADERS32 *)nt_hdrs; - IMAGE_OPTIONAL_HEADER32 *opt_hdr_32 = &nt_hdrs_32->OptionalHeader; - data_dirs = &opt_hdr_32->DataDirectory[0]; - imageBase = opt_hdr_32->ImageBase; - } -#else - if (nt_hdrs->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { - IMAGE_NT_HEADERS64 *nt_hdrs_64 = (IMAGE_NT_HEADERS64 *)nt_hdrs; - IMAGE_OPTIONAL_HEADER64 *opt_hdr_64 = &nt_hdrs_64->OptionalHeader; - data_dirs = &opt_hdr_64->DataDirectory[0]; - imageBase = (ULONG_PTR)opt_hdr_64->ImageBase; - } -#endif - else { - - return errlvl; - } - } - else { - + if (nt_hdrs->Signature != IMAGE_NT_SIGNATURE) // 'PE\0\0' return errlvl; + if (nt_hdrs->OptionalHeader.Magic != (arch_64bit ? IMAGE_NT_OPTIONAL_HDR64_MAGIC : IMAGE_NT_OPTIONAL_HDR32_MAGIC)) + return errlvl; + + if (!arch_64bit) { + IMAGE_NT_HEADERS32 *nt_hdrs_32 = (IMAGE_NT_HEADERS32 *)nt_hdrs; + IMAGE_OPTIONAL_HEADER32 *opt_hdr_32 = &nt_hdrs_32->OptionalHeader; + data_dirs = &opt_hdr_32->DataDirectory[0]; + imageBase = opt_hdr_32->ImageBase; + } + else { + IMAGE_NT_HEADERS64 *nt_hdrs_64 = (IMAGE_NT_HEADERS64 *)nt_hdrs; + IMAGE_OPTIONAL_HEADER64 *opt_hdr_64 = &nt_hdrs_64->OptionalHeader; + data_dirs = &opt_hdr_64->DataDirectory[0]; + imageBase = (ULONG_PTR)opt_hdr_64->ImageBase; } } - ULONG zzzzz; - + ULONG zzzzz = 1; #ifdef _M_ARM64 - zzzzz = 4; -#else - if (imageBase != 0) { - return errlvl; - } - - zzzzz = 1; + if (arch_64bit) + zzzzz = 4; // ARM64 only + else #endif + if (imageBase != 0) // x64 or x86 + return errlvl; section = IMAGE_FIRST_SECTION(nt_hdrs); if (nt_hdrs->FileHeader.NumberOfSections < 2) return errlvl; @@ -241,13 +236,32 @@ _FX ULONG SbieDll_InjectLow_InitHelper() targets = (MY_TARGETS *)& bindata[section[zzzzz].PointerToRawData]; - m_sbielow_start_offset = (ULONG)(targets->entry - imageBase - section[0].VirtualAddress); - m_sbielow_data_offset = (ULONG)(targets->data - imageBase - section[0].VirtualAddress); + if(start_offset) *start_offset = (ULONG)(targets->entry - imageBase - section[0].VirtualAddress); + if(data_offset) *data_offset = (ULONG)(targets->data - imageBase - section[0].VirtualAddress); + if(detour_offset) *detour_offset = (ULONG)(targets->detour - imageBase - section[0].VirtualAddress); - m_sbielow_ptr = bindata + section[0].PointerToRawData; //Old version: head; - m_sbielow_len = section[0].SizeOfRawData; //Old version: (ULONG)(ULONG_PTR)(tail - head); + *sbielow_ptr = bindata + section[0].PointerToRawData; //Old version: head; + *sbielow_len = section[0].SizeOfRawData; //Old version: (ULONG)(ULONG_PTR)(tail - head); - if ((!m_sbielow_start_offset) || (!m_sbielow_data_offset)) + return 0; +} + + +//--------------------------------------------------------------------------- +// InjectLow_InitHelper +//--------------------------------------------------------------------------- + + +_FX ULONG SbieDll_InjectLow_InitHelper() +{ +#ifdef _WIN64 + ULONG errlvl = SbieDll_InjectLow_LoadLow(TRUE, &m_sbielow_ptr, &m_sbielow_len, &m_sbielow_start_offset, &m_sbielow_data_offset, NULL); + if(!errlvl) + errlvl = SbieDll_InjectLow_LoadLow(FALSE, &m_sbielow32_ptr, &m_sbielow32_len, NULL, NULL, &m_sbielow32_detour_offset); +#else + ULONG errlvl = SbieDll_InjectLow_LoadLow(FALSE, &m_sbielow_ptr, &m_sbielow_len, &m_sbielow_start_offset, &m_sbielow_data_offset, NULL); +#endif + if (errlvl) return errlvl; // @@ -403,6 +417,10 @@ _FX ULONG SbieDll_InjectLow_InitSyscalls(BOOLEAN drv_init) // Get the SbieDll Location // + /*if (1) { + GetSystemDirectory(sbie_home, 512); + } + else */ if (drv_init) { status = SbieApi_GetHomePath(NULL, 0, sbie_home, 512); @@ -531,6 +549,15 @@ _FX ULONG SbieDll_InjectLow_InitSyscalls(BOOLEAN drv_init) extra->LdrGetProcAddr_offset = ULONG_DIFF(ptr, extra); ptr += 28 / sizeof(WCHAR); + // + // write an ASCII string for NtProtectVirtualMemory + // + + strcpy((char *)ptr, "NtProtectVirtualMemory"); + + extra->NtProtectVirtualMemory_offset = ULONG_DIFF(ptr, extra); + ptr += 28 / sizeof(WCHAR); + // // write an ASCII string for NtRaiseHardError // @@ -540,6 +567,15 @@ _FX ULONG SbieDll_InjectLow_InitSyscalls(BOOLEAN drv_init) extra->NtRaiseHardError_offset = ULONG_DIFF(ptr, extra); ptr += 20 / sizeof(WCHAR); + // + // write an ASCII string for NtDeviceIoControlFile + // + + strcpy((char *)ptr, "NtDeviceIoControlFile"); + + extra->NtDeviceIoControlFile_offset = ULONG_DIFF(ptr, extra); + ptr += 28 / sizeof(WCHAR); + // // write an ASCII string for RtlFindActivationContextSectionString // @@ -615,15 +651,6 @@ _FX ULONG SbieDll_InjectLow_InitSyscalls(BOOLEAN drv_init) extra->InjectData_offset = ULONG_DIFF(ptr, extra); -#ifdef _WIN64 - - // - // Copy the required non shell code into INJECT_DATA.DetourCode_* - // - - memcpy((UCHAR*)ptr + FIELD_OFFSET(INJECT_DATA, DetourCode_x86), SbieDll_ShellCode_x86, sizeof(SbieDll_ShellCode_x86)); -#endif - // // adjust size of syscall buffer to include path strings // @@ -852,6 +879,7 @@ _FX ULONG SbieDll_InjectLow(HANDLE hProcess, ULONG init_flags, BOOLEAN dup_drv_h #endif lowdata.RealNtDeviceIoControlFile = (ULONG64)GetProcAddress((HMODULE)lowdata.ntdll_base, "NtDeviceIoControlFile"); + lowdata.NativeNtProtectVirtualMemory = (ULONG64)GetProcAddress((HMODULE)lowdata.ntdll_base, "NtProtectVirtualMemory"); lowdata.NativeNtRaiseHardError = (ULONG64)GetProcAddress((HMODULE)lowdata.ntdll_base, "NtRaiseHardError"); // @@ -885,16 +913,76 @@ _FX ULONG SbieDll_InjectLow(HANDLE hProcess, ULONG init_flags, BOOLEAN dup_drv_h #endif lowLevel_size = m_sbielow_len; - void *remote_addr = SbieDll_InjectLow_CopyCode(hProcess, lowLevel_size, lowdata.LdrInitializeThunk_tramp, sizeof(lowdata.LdrInitializeThunk_tramp) + void *remote_addr = SbieDll_InjectLow_CopyCode(hProcess, lowLevel_size, m_sbielow_len, m_sbielow_ptr #ifdef _M_ARM64 , (BOOLEAN)lowdata.flags.is_arm64ec #endif ); + + if (remote_addr) { + + void* pLdrInitializeThunk = (void*)m_LdrInitializeThunk; +#ifdef _M_ARM64 + if (lowdata.flags.is_arm64ec) + pLdrInitializeThunk = (void*)m_LdrInitializeThunkEC; +#endif + + // + // copy code at LdrInitializeThunk from new process + // + + SIZE_T len1 = sizeof(lowdata.LdrInitializeThunk_tramp); + SIZE_T len2 = 0; + /* + sprintf(buffer,"CopyCode: copy ldr size %d\n",code_len); + OutputDebugStringA(buffer); + */ + BOOL vm_ok = ReadProcessMemory( + hProcess, pLdrInitializeThunk, lowdata.LdrInitializeThunk_tramp, + len1, &len2); + + if (!vm_ok || len1 != len2) { + + remote_addr = NULL; + } + } + if (!remote_addr) { errlvl = 0x33; goto finish; } +#ifdef _WIN64 + void *remote_addr32 = NULL; + if (lowdata.flags.is_wow64) { + + // + // when this is a 32 bit process runing under WoW we need to inject also some 32 bit code + // + + remote_addr32 = SbieDll_InjectLow_CopyCode(hProcess, m_sbielow32_len, m_sbielow32_len, m_sbielow32_ptr +#ifdef _M_ARM64 + , FALSE +#endif + ); + + if (remote_addr32) { + + ULONG protect; + BOOL vm_ok = VirtualProtectEx(hProcess, remote_addr32, m_sbielow32_len, + PAGE_EXECUTE_READ, &protect); + if (vm_ok) { + lowdata.ptr_32bit_detour = (ULONG64)((UCHAR*)remote_addr32 + m_sbielow32_detour_offset); + } + } + + if (!lowdata.ptr_32bit_detour) { + errlvl = 0x88; + goto finish; + } + } +#endif + #ifndef _M_ARM64 #ifdef _WIN64 lowdata.flags.long_diff = 1; @@ -1041,8 +1129,8 @@ _FX void* InjectLow_AllocMemory(HANDLE hProcess, SIZE_T size, BOOLEAN executable void *remote_addr = NULL; #ifdef _M_ARM64 - if (use_arm64ec && executable) - { + if (use_arm64ec && executable) { + MEM_EXTENDED_PARAMETER Parameter = { 0 }; Parameter.Type = MemExtendedParameterAttributeFlags; Parameter.ULong64 = MEM_EXTENDED_PARAMETER_EC_CODE; @@ -1051,8 +1139,9 @@ _FX void* InjectLow_AllocMemory(HANDLE hProcess, SIZE_T size, BOOLEAN executable remote_addr = __sys_VirtualAlloc2(hProcess, (void*)base_addr, region_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE, &Parameter, 1); } + + return remote_addr; } - else #endif // @@ -1127,20 +1216,13 @@ _FX HANDLE SbieDll_InjectLow_SendHandle(HANDLE hProcess) //--------------------------------------------------------------------------- -_FX void *SbieDll_InjectLow_CopyCode(HANDLE hProcess, SIZE_T lowLevel_size, UCHAR *code, ULONG code_len +_FX void *SbieDll_InjectLow_CopyCode(HANDLE hProcess, SIZE_T total_size, SIZE_T lowLevel_size, const void* lowLevel_ptr #ifdef _M_ARM64 , BOOLEAN use_arm64ec #endif ) { - void* remote_addr; - void* pLdrInitializeThunk = (void*)m_LdrInitializeThunk; -#ifdef _M_ARM64 - if (use_arm64ec) - pLdrInitializeThunk = (void*)m_LdrInitializeThunkEC; -#endif - - remote_addr = InjectLow_AllocMemory(hProcess, lowLevel_size, TRUE + void* remote_addr = InjectLow_AllocMemory(hProcess, total_size, TRUE #ifdef _M_ARM64 , use_arm64ec #endif @@ -1152,32 +1234,15 @@ _FX void *SbieDll_InjectLow_CopyCode(HANDLE hProcess, SIZE_T lowLevel_size, UCHA // copy SbieLow into the allocated region in the new process // - SIZE_T len1 = m_sbielow_len; + SIZE_T len1 = lowLevel_size; SIZE_T len2 = 0; BOOL vm_ok = WriteProcessMemory( - hProcess, remote_addr, m_sbielow_ptr, + hProcess, remote_addr, lowLevel_ptr, len1, &len2); if (vm_ok && len1 == len2) { - // - // copy code at LdrInitializeThunk from new process - // - - len1 = code_len; - len2 = 0; - /* - sprintf(buffer,"CopyCode: copy ldr size %d\n",code_len); - OutputDebugStringA(buffer); - */ - vm_ok = ReadProcessMemory( - hProcess, pLdrInitializeThunk, code, - len1, &len2); - - if (vm_ok && len1 == len2) { - - return remote_addr; - } + return remote_addr; } } @@ -1356,10 +1421,8 @@ _FX void *SbieDll_InjectLow_CopySyscalls(HANDLE hProcess, BOOLEAN is_wow64 data = m_syscall_data; SIZE_T region_size = *data; - remote_addr = InjectLow_AllocMemory(hProcess, region_size - , is_wow64 // we copy the detour code into this area, hence executable = TRUE + remote_addr = InjectLow_AllocMemory(hProcess, region_size , FALSE #ifdef _M_ARM64 - //|| use_arm64ec , FALSE #endif ); @@ -1406,10 +1469,7 @@ _FX BOOLEAN SbieDll_InjectLow_CopyData( ULONG protect; vm_ok = VirtualProtectEx(hProcess, remote_addr, m_sbielow_len, - // we want to be able to pass data from the low level dll we do this here - // we set PAGE_EXECUTE_READ in SbieDll.dll Dll_Ordinal1 - PAGE_EXECUTE_READWRITE, &protect); - //PAGE_EXECUTE_READ, &protect); + PAGE_EXECUTE_READ, &protect); if (vm_ok) { return TRUE; } diff --git a/Sandboxie/core/dll/sbieapi.c b/Sandboxie/core/dll/sbieapi.c index a68ef9d8..8a1bde29 100644 --- a/Sandboxie/core/dll/sbieapi.c +++ b/Sandboxie/core/dll/sbieapi.c @@ -667,7 +667,7 @@ _FX ULONG64 SbieApi_QueryProcessInfoEx( _FX LONG SbieApi_QueryBoxPath( - const WCHAR *box_name, // WCHAR [34] + const WCHAR *box_name, // WCHAR [BOXNAME_COUNT] WCHAR *out_file_path, WCHAR *out_key_path, WCHAR *out_ipc_path, @@ -828,7 +828,7 @@ _FX LONG SbieApi_QueryPathList( _FX LONG SbieApi_EnumProcessEx( - const WCHAR *box_name, // WCHAR [34] + const WCHAR *box_name, // WCHAR [BOXNAME_COUNT] BOOLEAN all_sessions, ULONG which_session, // -1 for current session ULONG *boxed_pids, // ULONG [512] @@ -1432,7 +1432,7 @@ _FX ULONG SbieApi_QueryConfNumber( _FX LONG SbieApi_EnumBoxes( LONG index, // initialize to -1 - WCHAR *box_name) // WCHAR [34] + WCHAR *box_name) // WCHAR [BOXNAME_COUNT] { return SbieApi_EnumBoxesEx(index, box_name, FALSE); } @@ -1445,7 +1445,7 @@ _FX LONG SbieApi_EnumBoxes( _FX LONG SbieApi_EnumBoxesEx( LONG index, // initialize to -1 - WCHAR *box_name, // WCHAR [34] + WCHAR *box_name, // WCHAR [BOXNAME_COUNT] BOOLEAN return_all_sections) { LONG rc; @@ -1738,7 +1738,7 @@ _FX LONG SbieApi_SessionLeader(HANDLE TokenHandle, HANDLE *ProcessId) _FX LONG SbieApi_IsBoxEnabled( - const WCHAR *box_name) // WCHAR [34] + const WCHAR *box_name) // WCHAR [BOXNAME_COUNT] { NTSTATUS status; __declspec(align(8)) ULONG64 parms[API_NUM_ARGS]; diff --git a/Sandboxie/core/dll/trace.c b/Sandboxie/core/dll/trace.c index 82e67fbb..80aaeb8a 100644 --- a/Sandboxie/core/dll/trace.c +++ b/Sandboxie/core/dll/trace.c @@ -105,10 +105,6 @@ _FX int Trace_Init(void) OutputDebugString(L"SbieDll injected...\n"); - for (int i = 0; i < 16; i++) { - if (SbieApi_data->DebugData[i] != 0) - DbgPrint("DebugData[%d]: %p\n", i, (UINT_PTR)SbieApi_data->DebugData[i]); - } } // diff --git a/Sandboxie/core/drv/syscall.c b/Sandboxie/core/drv/syscall.c index 6fbfdc1b..266a1f32 100644 --- a/Sandboxie/core/drv/syscall.c +++ b/Sandboxie/core/drv/syscall.c @@ -711,7 +711,7 @@ _FX NTSTATUS Syscall_Api_Invoke(PROCESS *proc, ULONG64 *parms) if (pTrapFrame) { ret = pTrapFrame->Rip; UserStack = pTrapFrame->Rsp; - pTrapFrame->Rsp = pTrapFrame->Rbp; //*pRbp; + pTrapFrame->Rsp = pTrapFrame->Rdi; //*pRbp; pTrapFrame->Rip = pTrapFrame->Rbx; //*pRbx; } } diff --git a/Sandboxie/core/drv/syscall_win32.c b/Sandboxie/core/drv/syscall_win32.c index cb411a74..7b05034c 100644 --- a/Sandboxie/core/drv/syscall_win32.c +++ b/Sandboxie/core/drv/syscall_win32.c @@ -554,7 +554,7 @@ _FX NTSTATUS Syscall_Api_Invoke32(PROCESS* proc, ULONG64* parms) if (pTrapFrame) { ret = pTrapFrame->Rip; UserStack = pTrapFrame->Rsp; - pTrapFrame->Rsp = pTrapFrame->Rbp; //*pRbp; + pTrapFrame->Rsp = pTrapFrame->Rdi; //*pRbp; pTrapFrame->Rip = pTrapFrame->Rbx; //*pRbx; } } diff --git a/Sandboxie/core/low/LowLevel.vcxproj b/Sandboxie/core/low/LowLevel.vcxproj index 46516cd7..eae66599 100644 --- a/Sandboxie/core/low/LowLevel.vcxproj +++ b/Sandboxie/core/low/LowLevel.vcxproj @@ -159,11 +159,6 @@ - - true - true - true - diff --git a/Sandboxie/core/low/entry_arm.asm b/Sandboxie/core/low/entry_arm.asm index eca441ac..5f57aa8f 100644 --- a/Sandboxie/core/low/entry_arm.asm +++ b/Sandboxie/core/low/entry_arm.asm @@ -1,5 +1,5 @@ ;------------------------------------------------------------------------ -; Copyright 2022 David Xanatos, xanasoft.com +; 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 @@ -19,6 +19,8 @@ IMPORT EntrypointC + IMPORT DetourFunc + ;EXPORT ServiceDataPtr EXPORT SystemServiceARM64 @@ -251,7 +253,7 @@ DeviceIoControlSvc ;---------------------------------------------------------------------------- -; RtlFindActivationContextSectionString detour code +; detour code loading SbieDll.dll ;---------------------------------------------------------------------------- @@ -272,103 +274,26 @@ DetourCodeARM64 PROC 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 + ; call DetourFunc ; - mov x20, #0x10 ; retry count + mov x0, x19 ; [x19].InjectData + bl DetourFunc -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 +; cmp x0, #0x00 +; bne DetourError ; - ; 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 + ; resume execution or original function ; - 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 x0, x1, [sp, #0x00] ldp x2, x3, [sp, #0x10] ldp x4, x5, [sp, #0x20] ldp x6, x7, [sp, #0x30] - ldr x8, [x19, 0x68] ; [x19].InjectData.SbieDllOrdinal1 + ldr x8, [x19, 0x08] ; [x19].InjectData.RtlFindActCtx add sp, sp, #0x40 ldp x19, x20, [sp], #0x10 @@ -376,34 +301,170 @@ LdrLoadGood 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 +;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 @@ -433,8 +494,9 @@ SbieLowData DCQ Start ; entry point for the detour DCQ SbieLowData ; data location + DCQ DetourCodeARM64 ; detour code location ;---------------------------------------------------------------------------- - END + END \ No newline at end of file diff --git a/Sandboxie/core/low/entry_asm.asm b/Sandboxie/core/low/entry_asm.asm index 355ac98d..d7050c10 100644 --- a/Sandboxie/core/low/entry_asm.asm +++ b/Sandboxie/core/low/entry_asm.asm @@ -1,6 +1,6 @@ ;------------------------------------------------------------------------ ; Copyright 2004-2020 Sandboxie Holdings, LLC -; Copyright 2021-2022 David Xanatos, xanasoft.com +; Copyright 2021-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 @@ -74,16 +74,14 @@ _001: pop rcx ; removed hard coded position dependency ; key symbols are now passed as arguments to EntrypointC ; 64 bit version takes 4 arguments - ; _EntrypointC(SbieLowData,_RtlFindActivationContextSectionString,_SystemService,_RtlFindActivationContextSectionString64) + ; _EntrypointC(SbieLowData,_DetourCode,_SystemService) mov rbx,rcx add rcx, offset SbieLowData - _001 mov rdx,rbx - add rdx, offset _RtlFindActivationContextSectionString64 - _001 + add rdx, offset _DetourCode - _001 mov r8,rbx add r8, offset _SystemService - _001 - ;mov r9,rbx - ;add r9, offset _RtlFindActivationContextSectionString - _001 call EntrypointC @@ -99,21 +97,24 @@ else ; 32-bit EXTERN _EntrypointC@12 : PROC _Start: call $+5 -_001: pop eax - mov edx,eax +_001: pop eax + mov edx,eax ; removed hard coded position dependency ; key symbols are now passed as arguments to EntrypointC ; 32 bit version takes 3 arguments - ;_EntrypointC(SbieLowData,_RtlFindActivationContextSectionString,_SystemService) + ;_EntrypointC(SbieLowData,_DetourCode,_SystemService) + add eax, offset _SystemService - _001 ;old + 96 offset push eax mov eax,edx - add eax, offset _RtlFindActivationContextSectionString - _001; old + 256 offset + add eax, offset _DetourCode - _001; old + 256 offset push eax mov eax, edx add eax, offset SbieLowData - _001 push eax + call _EntrypointC@12 + jmp eax ; jump to LdrInitializeThunk trampoline endif ; 32-bit or 64-bit @@ -126,7 +127,6 @@ endif ; 32-bit or 64-bit _SystemService: -;---------------------------------------------------------------------------- ifdef _WIN64 ; 64-bit myService Proc db 48h, 0B8h ; rax -> SbieLowData @@ -141,17 +141,17 @@ myService Proc ; because of x64 calling convention. ; - push rbp; target rsp + push rdi; target rsp push rbx; target rip mov r11,[rax + 0e0h] ; SbieLow.RealNtDeviceIoControlFile - add r11b,0fh + add r11b,0fh - mov rbx, r11 ; pass new rip in rbx - mov r11, rsp ; restore stack in r11 + mov rbx, r11 ; pass new rip in rbx + mov r11, rsp ; restore stack in r11 add r11, 10h - mov rbp, r11 ; pass stack frame in rbp + mov rdi, r11 ; pass stack frame in rbp API_NUM_ARGS = 8 sub rsp, (API_NUM_ARGS + 1 + 2 + 10) * 8 @@ -225,17 +225,16 @@ myService Proc mov qword ptr [rsp+8*8], rdx mov qword ptr [rsp+9*8], rdx - lea r10, [r10+80h] ; r10 -> SbieLow.NtDeviceIoControlFile + lea r10, [r10+80h] ; r10 -> SbieLow.NtDeviceIoControlFile_code call r10 add rsp, (API_NUM_ARGS + 1 + 2 + 10) * 8 pop rbx - pop rbp + pop rdi ret myService ENDP -;---------------------------------------------------------------------------- else ; 32-bit @@ -297,7 +296,7 @@ else ; 32-bit push 0 push [edx+2*8] ; push SbieLow.api_device_handle - lea eax, [edx+80h] ; eax -> SbieLow.NtDeviceIoControlFile + lea eax, [edx+80h] ; eax -> SbieLow.NtDeviceIoControlFile_code call eax ; @@ -316,160 +315,25 @@ else ; 32-bit neg ecx mov ecx, [esp+ecx] jmp ecx ; return to caller + endif ; 32-bit or 64-bit ;---------------------------------------------------------------------------- -; Inject Data Area for our RtlFindActivationContextSectionString +; detour code ;---------------------------------------------------------------------------- - InjectData struct ; keep in sync with inject.c - dq ? ; 0x00 -LdrLoadDll dq ? ; 0x08 -LdrGetProcAddr dq ? ; 0x10 -NtRaiseHardError dq ? ; 0x18 -RtlFindActCtx dq ? ; 0x20 -RtlFindActCtx_Protect dd ? ; 0x28 -RtlFindActCtx_Bytes db 20 dup (?) ; 0x2C -KernelDll_Unicode dq 2 dup (?) ; 0x40 -SbieDll_Unicode dq 2 dup (?) ; 0x50 -ModuleHandle dq ? ; 0x60 -SbieDllOrdinal1 dq ? ; 0x68 +sbielow_data dq ? ; 0x00 +RtlFindActCtx dq ? ; 0x08 InjectData ends - -;---------------------------------------------------------------------------- -; 32-bit RtlFindActivationContextSectionString detour code -;---------------------------------------------------------------------------- - -_RtlFindActivationContextSectionString: -ifndef _WIN64 ; 32-bit - - mov edx, 0 ; edx -> inject data area - - push esi - mov esi, edx ; esi -> inject data area - - mov eax, dword ptr [esi].InjectData.RtlFindActCtx - mov dl, byte ptr [esi].InjectData.RtlFindActCtx_Bytes - mov byte ptr [eax], dl - mov edx, dword ptr [esi].InjectData.RtlFindActCtx_Bytes+1 - mov dword ptr [eax+1], edx - - ; - ; call LdrLoadDll for kernel32 - ; - mov ecx, 10h ;number of retries -LdrLoadDll_Retry: - push ecx - lea eax, [esi].InjectData.ModuleHandle - push eax - lea eax, [esi].InjectData.KernelDll_Unicode - push eax - push 0 - push 0 - call dword ptr [esi].InjectData.LdrLoadDll - pop ecx - test eax, eax - jz LdrLoadDll_Good - loop LdrLoadDll_Retry - ; retry failed 16 times: raise error - jmp RtlFindActivationContextSectionStringError -LdrLoadDll_Good: - ; - ; call LdrLoadDll for sbiedll - ; - - lea eax, [esi].InjectData.ModuleHandle - push eax - lea eax, [esi].InjectData.SbieDll_Unicode - push eax - push 0 - push 0 - call dword ptr [esi].InjectData.LdrLoadDll - - test eax, eax - jnz RtlFindActivationContextSectionStringError - - ; - ; call LdrGetProcedureAddress for sbiedll ordinal 1, - ; which forces ntdll to initialize sbiedll - ; - - lea eax, [esi].InjectData.SbieDllOrdinal1 - push eax - push 1 - push 0 - push dword ptr [esi].InjectData.ModuleHandle - call dword ptr [esi].InjectData.LdrGetProcAddr - - test eax, eax - jnz 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 - ; - - mov eax, esi - xchg eax, dword ptr [esp+4*2] - mov dword ptr [esi].InjectData.LdrLoadDll, eax - mov eax, esi - pop esi - jmp dword ptr [eax].InjectData.SbieDllOrdinal1 - - ; - ; display error message, invoke NtRaiseHardError( - ; NTSTATUS ntstatus_message_code, - ; ULONG number_of_parameters_in_list, - ; ULONG mask_of_strings_in_list, - ; ULONG_PTR *list_of_pointers_to_parameters, - ; ULONG response_buttons, - ; ULONG *out_response) - ; - -RtlFindActivationContextSectionStringError: - - STATUS_DLL_INIT_FAILED = 0C0000142h - FORCE_ERROR_MESSAGE_BOX = 010000000h - - push eax ; save ntstatus - - lea edx, [esi].InjectData.SbieDll_Unicode - mov dword ptr [esi].InjectData.LdrLoadDll, edx - - lea edx, [esi].InjectData.LdrGetProcAddr - push edx ; out_response - push 1 ; response_buttons - ERROR_OK - lea edx, [esi].InjectData.LdrLoadDll - push edx ; list_of_pointers_to_parameters - push 1 ; mask_of_strings_in_list - push 1 ; number_of_parameters_in_list - push (STATUS_DLL_INIT_FAILED or FORCE_ERROR_MESSAGE_BOX) - call dword ptr [esi].InjectData.NtRaiseHardError - - pop eax ; pop error ntstatus to return - pop esi - ret 14h ; return to caller with error - -endif ; 32-bit or 64-bit - - -;---------------------------------------------------------------------------- -; 64-bit RtlFindActivationContextSectionString detour code -;---------------------------------------------------------------------------- - - ifdef _WIN64 ; 64-bit -dq 0h ;inject data area address - _RtlFindActivationContextSectionString64: + +EXTERN DetourFunc : PROC + + dq 0h ;inject data area address +_DetourCode: mov rax, qword ptr [$-8] ; rax -> inject data area push rsi ; save rsi, and align stack @@ -482,134 +346,367 @@ dq 0h ;inject data area address mov rsi, rax ; rsi -> inject data area - mov rax, qword ptr [rsi].InjectData.RtlFindActCtx - - ;replace 12bytes - mov rdx, qword ptr [rsi].InjectData.RtlFindActCtx_Bytes - mov qword ptr [rax], rdx - mov edx, dword ptr [rsi].InjectData.RtlFindActCtx_Bytes + 8 - mov dword ptr [rax+8], edx - ; - ; call LdrLoadDll for kernel32 - ; - ;; retry loop - mov qword ptr [rsi].InjectData.RtlFindActCtx_Bytes, rbx - mov rbx, 010h - -LdrLoadRetry: - xor rcx, rcx - xor rdx, rdx - lea r8, [rsi].InjectData.KernelDll_Unicode - lea r9, [rsi].InjectData.ModuleHandle - ;cmp rbx,1 - ;jnz LdrTestLoop - call qword ptr [rsi].InjectData.LdrLoadDll - test eax, eax - jz LdrLoadGood -;LdrTestLoop: - dec rbx - test rbx, rbx - jnz LdrLoadRetry ;loop LdrLoadRetry - jmp RtlFindActivationContextSectionStringError -LdrLoadGood: - mov rbx, qword ptr [rsi].InjectData.RtlFindActCtx_Bytes - - ; - ; call LdrLoadDll for sbiedll + ; call DetourFunc ; - xor rcx, rcx - xor rdx, rdx - lea r8, [rsi].InjectData.SbieDll_Unicode - lea r9, [rsi].InjectData.ModuleHandle - call qword ptr [rsi].InjectData.LdrLoadDll - - test eax, eax - jnz RtlFindActivationContextSectionStringError - - ; - ; call LdrGetProcedureAddress for sbiedll ordinal 1, - ; which forces ntdll to initialize sbiedll - ; - - mov rcx, qword ptr [rsi].InjectData.ModuleHandle + mov rcx, rsi xor rdx, rdx xor r8, r8 - inc r8 - lea r9, [rsi].InjectData.SbieDllOrdinal1 - call qword ptr [rsi].InjectData.LdrGetProcAddr + xor r9, r9 + call DetourFunc - test eax, eax - jnz RtlFindActivationContextSectionStringError +; test eax, eax +; jnz DetourError ; - ; 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 + ; resume execution or original function ; - mov rax, qword ptr [rsp+4*8] - mov qword ptr [rsi].InjectData.LdrLoadDll, rax - mov rcx, rsi + mov rcx, qword ptr [rsp+4*8] mov rdx, qword ptr [rsp+5*8] mov r8, qword ptr [rsp+6*8] mov r9, qword ptr [rsp+7*8] add rsp, 8*8 + mov rax, qword ptr [rsi].InjectData.RtlFindActCtx pop rsi - jmp qword ptr [rcx].InjectData.SbieDllOrdinal1 + jmp rax + +;DetourError: +; +; add rsp, 8*8 +; pop rsi +; ret ; return to caller with error + +else ; 32-bit + +EXTERN _DetourFunc@4 : PROC + +_DetourCode: + + mov edx, 0 ; edx -> inject data area + + push esi + mov esi, edx ; esi -> inject data area ; - ; display error message, invoke NtRaiseHardError( - ; NTSTATUS ntstatus_message_code, - ; ULONG number_of_parameters_in_list, - ; ULONG mask_of_strings_in_list, - ; ULONG_PTR *list_of_pointers_to_parameters, - ; ULONG response_buttons, - ; ULONG *out_response) + ; call DetourFunc + ; + + push esi + call _DetourFunc@4 + +; test eax, eax +; jnz DetourError + + ; + ; resume execution or original function ; -RtlFindActivationContextSectionStringError: - - STATUS_DLL_INIT_FAILED = 0C0000142h - FORCE_ERROR_MESSAGE_BOX = 010000000h - - mov qword ptr [rsp+7*8], rax ; save ntstatus - - mov ecx, \ ; ntstatus_message_code - (STATUS_DLL_INIT_FAILED or FORCE_ERROR_MESSAGE_BOX) + mov eax, dword ptr [esi].InjectData.RtlFindActCtx + pop esi + jmp eax - xor rdx, rdx ; number_of_parameters_in_list - inc rdx +;DetourError: +; +; pop esi +; ret 14h ; return to caller with error - mov r8, rdx ; mask_of_strings_in_list +endif ; 32-bit or 64-bit - lea r9, \ ; list_of_pointers_to_parameters - [esi].InjectData.LdrLoadDll - lea rax, [rsi].InjectData.SbieDll_Unicode - mov qword ptr [r9], rax - - mov \ ; response_buttons - ERROR_OK - qword ptr [rsp+4*8], rdx - - lea rax, [rsi].InjectData.LdrGetProcAddr - mov \ ; out_response - qword ptr [rsp+5*8], rax - - call qword ptr [rsi].InjectData.NtRaiseHardError - - mov rax, qword ptr [rsp+7*8] ; restore ntstatus - add rsp, 8*8 - pop rsi - ret ; return to caller with error - -endif ; 64-bit + +;;---------------------------------------------------------------------------- +;; Inject Data Area for our RtlFindActivationContextSectionString +;;---------------------------------------------------------------------------- +; +; +;InjectData struct ; keep in sync with inject.c +; dq ? ; 0x00 +;LdrLoadDll dq ? ; 0x08 +;LdrGetProcAddr dq ? ; 0x10 +;NtRaiseHardError dq ? ; 0x18 +;RtlFindActCtx dq ? ; 0x20 +;RtlFindActCtx_Protect dd ? ; 0x28 +;RtlFindActCtx_Bytes db 20 dup (?) ; 0x2C +;KernelDll_Unicode dq 2 dup (?) ; 0x40 +;SbieDll_Unicode dq 2 dup (?) ; 0x50 +;ModuleHandle dq ? ; 0x60 +;SbieDllOrdinal1 dq ? ; 0x68 +;InjectData ends +; +; +;;---------------------------------------------------------------------------- +;; 32-bit RtlFindActivationContextSectionString detour code +;;---------------------------------------------------------------------------- +; +;_RtlFindActivationContextSectionString: +;ifndef _WIN64 ; 32-bit +; +; mov edx, 0 ; edx -> inject data area +; +; push esi +; mov esi, edx ; esi -> inject data area +; +; mov eax, dword ptr [esi].InjectData.RtlFindActCtx +; mov dl, byte ptr [esi].InjectData.RtlFindActCtx_Bytes +; mov byte ptr [eax], dl +; mov edx, dword ptr [esi].InjectData.RtlFindActCtx_Bytes+1 +; mov dword ptr [eax+1], edx +; +; ; +; ; call LdrLoadDll for kernel32 +; ; +; mov ecx, 10h ;number of retries +;LdrLoadDll_Retry: +; push ecx +; lea eax, [esi].InjectData.ModuleHandle +; push eax +; lea eax, [esi].InjectData.KernelDll_Unicode +; push eax +; push 0 +; push 0 +; call dword ptr [esi].InjectData.LdrLoadDll +; pop ecx +; test eax, eax +; jz LdrLoadDll_Good +; loop LdrLoadDll_Retry +; ; retry failed 16 times: raise error +; jmp RtlFindActivationContextSectionStringError +;LdrLoadDll_Good: +; ; +; ; call LdrLoadDll for sbiedll +; ; +; +; lea eax, [esi].InjectData.ModuleHandle +; push eax +; lea eax, [esi].InjectData.SbieDll_Unicode +; push eax +; push 0 +; push 0 +; call dword ptr [esi].InjectData.LdrLoadDll +; +; test eax, eax +; jnz RtlFindActivationContextSectionStringError +; +; ; +; ; call LdrGetProcedureAddress for sbiedll ordinal 1, +; ; which forces ntdll to initialize sbiedll +; ; +; +; lea eax, [esi].InjectData.SbieDllOrdinal1 +; push eax +; push 1 +; push 0 +; push dword ptr [esi].InjectData.ModuleHandle +; call dword ptr [esi].InjectData.LdrGetProcAddr +; +; test eax, eax +; jnz 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 +; ; +; +; mov eax, esi +; xchg eax, dword ptr [esp+4*2] +; mov dword ptr [esi].InjectData.LdrLoadDll, eax +; mov eax, esi +; pop esi +; jmp dword ptr [eax].InjectData.SbieDllOrdinal1 +; +; ; +; ; display error message, invoke NtRaiseHardError( +; ; NTSTATUS ntstatus_message_code, +; ; ULONG number_of_parameters_in_list, +; ; ULONG mask_of_strings_in_list, +; ; ULONG_PTR *list_of_pointers_to_parameters, +; ; ULONG response_buttons, +; ; ULONG *out_response) +; ; +; +;RtlFindActivationContextSectionStringError: +; +; STATUS_DLL_INIT_FAILED = 0C0000142h +; FORCE_ERROR_MESSAGE_BOX = 010000000h +; +; push eax ; save ntstatus +; +; lea edx, [esi].InjectData.SbieDll_Unicode +; mov dword ptr [esi].InjectData.LdrLoadDll, edx +; +; lea edx, [esi].InjectData.LdrGetProcAddr +; push edx ; out_response +; push 1 ; response_buttons - ERROR_OK +; lea edx, [esi].InjectData.LdrLoadDll +; push edx ; list_of_pointers_to_parameters +; push 1 ; mask_of_strings_in_list +; push 1 ; number_of_parameters_in_list +; push (STATUS_DLL_INIT_FAILED or FORCE_ERROR_MESSAGE_BOX) +; call dword ptr [esi].InjectData.NtRaiseHardError +; +; pop eax ; pop error ntstatus to return +; pop esi +; ret 14h ; return to caller with error +; +;endif ; 32-bit or 64-bit +; +; +;;---------------------------------------------------------------------------- +;; 64-bit RtlFindActivationContextSectionString detour code +;;---------------------------------------------------------------------------- +; +; +;ifdef _WIN64 ; 64-bit +;dq 0h ;inject data area address +; _RtlFindActivationContextSectionString64: +; mov rax, qword ptr [$-8] ; rax -> inject data area +; +; push rsi ; save rsi, and align stack +; sub rsp, 8*8 ; set up local stack +; +; mov qword ptr [rsp+4*8], rcx +; mov qword ptr [rsp+5*8], rdx +; mov qword ptr [rsp+6*8], r8 +; mov qword ptr [rsp+7*8], r9 +; +; mov rsi, rax ; rsi -> inject data area +; +; mov rax, qword ptr [rsi].InjectData.RtlFindActCtx +; +; ;replace 12bytes +; mov rdx, qword ptr [rsi].InjectData.RtlFindActCtx_Bytes +; mov qword ptr [rax], rdx +; mov edx, dword ptr [rsi].InjectData.RtlFindActCtx_Bytes + 8 +; mov dword ptr [rax+8], edx +; +; ; +; ; call LdrLoadDll for kernel32 +; ; +; ;; retry loop +; mov qword ptr [rsi].InjectData.RtlFindActCtx_Bytes, rbx +; mov rbx, 010h +; +;LdrLoadRetry: +; xor rcx, rcx +; xor rdx, rdx +; lea r8, [rsi].InjectData.KernelDll_Unicode +; lea r9, [rsi].InjectData.ModuleHandle +; ;cmp rbx,1 +; ;jnz LdrTestLoop +; call qword ptr [rsi].InjectData.LdrLoadDll +; test eax, eax +; jz LdrLoadGood +;;LdrTestLoop: +; dec rbx +; test rbx, rbx +; jnz LdrLoadRetry ;loop LdrLoadRetry +; jmp RtlFindActivationContextSectionStringError +;LdrLoadGood: +; mov rbx, qword ptr [rsi].InjectData.RtlFindActCtx_Bytes +; +; ; +; ; call LdrLoadDll for sbiedll +; ; +; +; xor rcx, rcx +; xor rdx, rdx +; lea r8, [rsi].InjectData.SbieDll_Unicode +; lea r9, [rsi].InjectData.ModuleHandle +; call qword ptr [rsi].InjectData.LdrLoadDll +; +; test eax, eax +; jnz RtlFindActivationContextSectionStringError +; +; ; +; ; call LdrGetProcedureAddress for sbiedll ordinal 1, +; ; which forces ntdll to initialize sbiedll +; ; +; +; mov rcx, qword ptr [rsi].InjectData.ModuleHandle +; xor rdx, rdx +; xor r8, r8 +; inc r8 +; lea r9, [rsi].InjectData.SbieDllOrdinal1 +; call qword ptr [rsi].InjectData.LdrGetProcAddr +; +; test eax, eax +; jnz 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 +; ; +; +; mov rax, qword ptr [rsp+4*8] +; mov qword ptr [rsi].InjectData.LdrLoadDll, rax +; mov rcx, rsi +; mov rdx, qword ptr [rsp+5*8] +; mov r8, qword ptr [rsp+6*8] +; mov r9, qword ptr [rsp+7*8] +; +; add rsp, 8*8 +; pop rsi +; jmp qword ptr [rcx].InjectData.SbieDllOrdinal1 +; +; ; +; ; display error message, invoke NtRaiseHardError( +; ; NTSTATUS ntstatus_message_code, +; ; ULONG number_of_parameters_in_list, +; ; ULONG mask_of_strings_in_list, +; ; ULONG_PTR *list_of_pointers_to_parameters, +; ; ULONG response_buttons, +; ; ULONG *out_response) +; ; +; +;RtlFindActivationContextSectionStringError: +; +; STATUS_DLL_INIT_FAILED = 0C0000142h +; FORCE_ERROR_MESSAGE_BOX = 010000000h +; +; mov qword ptr [rsp+7*8], rax ; save ntstatus +; +; mov ecx, \ ; ntstatus_message_code +; (STATUS_DLL_INIT_FAILED or FORCE_ERROR_MESSAGE_BOX) +; +; xor rdx, rdx ; number_of_parameters_in_list +; inc rdx +; +; mov r8, rdx ; mask_of_strings_in_list +; +; lea r9, \ ; list_of_pointers_to_parameters +; [esi].InjectData.LdrLoadDll +; lea rax, [rsi].InjectData.SbieDll_Unicode +; mov qword ptr [r9], rax +; +; mov \ ; response_buttons - ERROR_OK +; qword ptr [rsp+4*8], rdx +; +; lea rax, [rsi].InjectData.LdrGetProcAddr +; mov \ ; out_response +; qword ptr [rsp+5*8], rax +; +; call qword ptr [rsi].InjectData.NtRaiseHardError +; +; mov rax, qword ptr [rsp+7*8] ; restore ntstatus +; add rsp, 8*8 +; pop rsi +; ret ; return to caller with error +; +;endif ; 64-bit ;---------------------------------------------------------------------------- @@ -631,6 +728,7 @@ SbieLowData LABEL QWORD dq _Start dq SbieLowData + dq _DetourCode ;---------------------------------------------------------------------------- end diff --git a/Sandboxie/core/low/init.c b/Sandboxie/core/low/init.c index f4e58391..196e8775 100644 --- a/Sandboxie/core/low/init.c +++ b/Sandboxie/core/low/init.c @@ -148,11 +148,11 @@ _FX NTSTATUS SbieApi_Ioctl(SBIELOW_DATA *data, void *parms) //--------------------------------------------------------------------------- -// SbieApi_DebugPrint +// SbieApi_LogMsg //--------------------------------------------------------------------------- -_FX NTSTATUS SbieApi_DebugPrint(SBIELOW_DATA *data, const WCHAR *text) +_FX NTSTATUS SbieApi_LogMsg(ULONG64 pNtDeviceIoControlFile, ULONG64 api_device_handle, ULONG code, const WCHAR *text) { NTSTATUS status = 0; __declspec(align(8)) UNICODE_STRING64 msgtext; @@ -170,9 +170,18 @@ _FX NTSTATUS SbieApi_DebugPrint(SBIELOW_DATA *data, const WCHAR *text) memzero(parms, sizeof(parms)); args->func_code = API_LOG_MESSAGE; args->session_id.val = -1; - args->msgid.val = 1122; + args->msgid.val = code; args->msgtext.val = &msgtext; - status = SbieApi_Ioctl(data, parms); + //status = SbieApi_Ioctl(data, parms); + + IO_STATUS_BLOCK MyIoStatusBlock; +#ifdef _WIN64 + ULONG MyIoStatusBlock32[2]; + *(ULONG_PTR *)&MyIoStatusBlock = (ULONG_PTR)MyIoStatusBlock32; +#endif _WIN64 + return ((P_NtDeviceIoControlFile)pNtDeviceIoControlFile)( + (HANDLE)api_device_handle, NULL, NULL, NULL, &MyIoStatusBlock, + API_SBIEDRV_CTLCODE, parms, sizeof(ULONG64) * 8, NULL, 0); return status; } @@ -196,7 +205,7 @@ _FX NTSTATUS SbieApi_DebugError(SBIELOW_DATA* data, ULONG error) for(int i=28; i >= 0; i-=4) *ptr++ = table[(error >> i) & 0xF]; - return SbieApi_DebugPrint(data, text); + return SbieApi_LogMsg(data->NtDeviceIoControlFile, data->api_device_handle, 2180, text); } @@ -223,9 +232,42 @@ _FX void WaitForDebugger(SBIELOW_DATA *data) __debugbreak(); } + #endif +//--------------------------------------------------------------------------- +// WriteMemorySafe +//--------------------------------------------------------------------------- + + +_FX void WriteMemorySafe(SBIELOW_DATA* data, void *Address, SIZE_T Size, void *Data) +{ + void *RegionBase = Address; + SIZE_T RegionSize = Size; + ULONG OldProtect; + + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &OldProtect); + + // memcopy is not available, lets do our own + switch (Size) { + case 1: *(UCHAR*)Address = *(UCHAR*)Data; break; + case 2: *(USHORT*)Address = *(USHORT*)Data; break; + case 4: *(ULONG*)Address = *(ULONG*)Data; break; + case 8: *(ULONG64*)Address = *(ULONG64*)Data; break; + default: + for (SIZE_T i = 0; i < Size; i++) + ((UCHAR*)Address)[i] = ((UCHAR*)Data)[i]; + } + + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + OldProtect, &OldProtect); +} + + //--------------------------------------------------------------------------- // PrepSyscalls //--------------------------------------------------------------------------- @@ -233,11 +275,6 @@ _FX void WaitForDebugger(SBIELOW_DATA *data) _FX void PrepSyscalls(SBIELOW_DATA *data, void * SystemService) { - UCHAR *SystemServiceAsm; - void *RegionBase; - SIZE_T RegionSize; - ULONG OldProtect; - #ifdef _M_ARM64 if (data->flags.is_arm64ec) { @@ -248,7 +285,8 @@ _FX void PrepSyscalls(SBIELOW_DATA *data, void * SystemService) // a replica of the #NtDeviceIoControlFile EC variant // - data->NtDeviceIoControlFile = (ULONG64)&NtDeviceIoControlFileEC; + ULONG64 pNtDeviceIoControlFileEC = (ULONG64)&NtDeviceIoControlFileEC; + WriteMemorySafe(data, &data->NtDeviceIoControlFile, sizeof(ULONG64), &pNtDeviceIoControlFileEC); // @@ -260,9 +298,9 @@ _FX void PrepSyscalls(SBIELOW_DATA *data, void * SystemService) // we can just copy the ULONG strait out of the native function // - DeviceIoControlSvc = *(ULONG*)&data->NtDeviceIoControlFile_code[0]; + WriteMemorySafe(data, &DeviceIoControlSvc, sizeof(ULONG), &data->NtDeviceIoControlFile_code[0]); + - // // get the EcExitThunkPtr which points to // __os_arm64x_dispatch_call_no_redirect @@ -275,11 +313,15 @@ _FX void PrepSyscalls(SBIELOW_DATA *data, void * SystemService) ULONG* syscall_ec_data = (ULONG*)data->syscall_data; - EcExitThunkPtr = *(ULONG64*)((UINT_PTR)syscall_ec_data + syscall_ec_data[1] - 8); + UINT_PTR pEcExitThunkPtr = *(UINT_PTR*)((UINT_PTR)syscall_ec_data + syscall_ec_data[1] - 8); + WriteMemorySafe(data, &EcExitThunkPtr, sizeof(UINT_PTR), &pEcExitThunkPtr); } else #endif - data->NtDeviceIoControlFile = (ULONG64)&data->NtDeviceIoControlFile_code[0]; + { + ULONG64 pNtDeviceIoControlFile = (ULONG64)&data->NtDeviceIoControlFile_code[0]; + WriteMemorySafe(data, &data->NtDeviceIoControlFile, sizeof(ULONG64), &pNtDeviceIoControlFile); + } const LONG OFFSET_ULONG_PTR = #ifdef _M_ARM64 @@ -295,21 +337,14 @@ _FX void PrepSyscalls(SBIELOW_DATA *data, void * SystemService) // to include the data area pointer // - SystemServiceAsm = (UCHAR *)SystemService; - RegionBase = (void *)(SystemServiceAsm + OFFSET_ULONG_PTR); - RegionSize = sizeof(ULONG_PTR); + WriteMemorySafe(data, ((UCHAR *)SystemService) + OFFSET_ULONG_PTR, sizeof(ULONG_PTR), &data); - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &OldProtect); + // + // store the SystemService address in pSystemService + // - *(ULONG_PTR *)(SystemServiceAsm + OFFSET_ULONG_PTR) = (ULONG_PTR)data; - - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - OldProtect, &OldProtect); - - data->pSystemService = (ULONG64)SystemServiceAsm; + ULONG64 SystemServicePtr = (ULONG64)SystemService; + WriteMemorySafe(data, &data->pSystemService, sizeof(ULONG64), &SystemServicePtr); } @@ -597,33 +632,29 @@ _FX void DisableCHPE(SBIELOW_DATA* data) if (!RtlImageOptionsEx) return; - // - // backup bytes for trampoline - // - - ULONG DetourSize = 28; - memcpy(data->RtlImageOptionsEx_tramp, RtlImageOptionsEx, DetourSize); - - // - // make target writable & create detour - // - void *RegionBase; SIZE_T RegionSize; ULONG OldProtect; + ULONG* aCode; - RegionBase = (void*)RtlImageOptionsEx; - RegionSize = DetourSize; // 16; + // + // backup target & create simple trampoline + // + + RegionBase = (void*)data->RtlImageOptionsEx_tramp; + RegionSize = sizeof(data->RtlImageOptionsEx_tramp); SBIELOW_CALL(NtProtectVirtualMemory)( NtCurrentProcess(), &RegionBase, &RegionSize, PAGE_EXECUTE_READWRITE, &OldProtect); - ULONG* aCode = (ULONG*)RtlImageOptionsEx; - aCode[0] = 0x580000a7; // ldr x7, 20 - data - aCode[1] = 0x58000048; // ldr x8, 8 - MyImageOptionsEx - aCode[2] = 0xD61F0100; // br x8 - *(DWORD64*)&aCode[3] = (DWORD64)MyImageOptionsEx; - *(DWORD64*)&aCode[5] = (DWORD64)data; + ULONG DetourSize = 28; + memcpy(data->RtlImageOptionsEx_tramp, RtlImageOptionsEx, DetourSize); + + aCode = (ULONG*)(data->RtlImageOptionsEx_tramp + DetourSize); // 28 + aCode[0] = 0x58000048; // ldr x8, 8 - Rest of RtlImageOptionsEx + aCode[1] = 0xD61F0100; // br x8 + *(DWORD64*)&aCode[2] = (DWORD64)RtlImageOptionsEx + DetourSize; + // 44 SBIELOW_CALL(NtProtectVirtualMemory)( NtCurrentProcess(), &RegionBase, &RegionSize, @@ -633,13 +664,29 @@ _FX void DisableCHPE(SBIELOW_DATA* data) NtCurrentProcess(), RegionBase, (ULONG)RegionSize); // - // create simple trampoline + // make target writable & create detour // - aCode = (ULONG*)(data->RtlImageOptionsEx_tramp + DetourSize); - aCode[0] = 0x58000048; // ldr x8, 8 - Rest of RtlImageOptionsEx - aCode[1] = 0xD61F0100; // br x8 - *(DWORD64*)&aCode[2] = (DWORD64)RtlImageOptionsEx + DetourSize; + RegionBase = (void*)RtlImageOptionsEx; + RegionSize = DetourSize; + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &OldProtect); + + aCode = (ULONG*)RtlImageOptionsEx; + aCode[0] = 0x580000a7; // ldr x7, 20 - data + aCode[1] = 0x58000048; // ldr x8, 8 - MyImageOptionsEx + aCode[2] = 0xD61F0100; // br x8 + *(DWORD64*)&aCode[3] = (DWORD64)MyImageOptionsEx; + *(DWORD64*)&aCode[5] = (DWORD64)data; + //28 + + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + OldProtect, &OldProtect); + + SBIELOW_CALL(NtFlushInstructionCache)( + NtCurrentProcess(), RegionBase, (ULONG)RegionSize); } #endif @@ -745,7 +792,7 @@ ULONG_PTR EntrypointC(SBIELOW_DATA *data, void *DetourCode, void *SystemService) // WaitForDebugger(data); //wchar_t text[] = { 't','e','s','t',0 }; - //SbieApi_DebugPrint(data, text); + //SbieApi_LogMsg(data->NtDeviceIoControlFile, data->api_device_handle, 1122, text); PrepSyscalls(data, SystemService); if (!data->flags.bHostInject && !data->flags.bNoSysHooks) diff --git a/Sandboxie/core/low/inject.c b/Sandboxie/core/low/inject.c index d5d1bb93..ec7468b6 100644 --- a/Sandboxie/core/low/inject.c +++ b/Sandboxie/core/low/inject.c @@ -1,6 +1,6 @@ /* * Copyright 2004-2020 Sandboxie Holdings, LLC - * Copyright 2020-2022 David Xanatos, xanasoft.com + * Copyright 2020-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 @@ -17,7 +17,7 @@ */ //--------------------------------------------------------------------------- -// Functions +// inject //--------------------------------------------------------------------------- #include @@ -28,12 +28,13 @@ typedef long NTSTATUS; #include "common/win32_ntddk.h" #include "common/defines.h" #include "lowdata.h" - +#include "core/drv/api_defs.h" //--------------------------------------------------------------------------- // Functions //--------------------------------------------------------------------------- +_FX NTSTATUS SbieApi_LogMsg(ULONG64 pNtDeviceIoControlFile, ULONG64 api_device_handle, ULONG code, const WCHAR* text); _FX NTSTATUS SbieApi_DebugError(SBIELOW_DATA* data, ULONG error); UCHAR *FindDllExport(void *DllBase, const UCHAR *ProcName, ULONG *pErr); @@ -45,10 +46,27 @@ static UCHAR *FindDllExport2( void* Hook_GetFFSTarget(UCHAR* SourceFunc); #endif -static void InitInjectWow64(SBIELOW_DATA *data); +//static void InitInjectWow64(SBIELOW_DATA *data); //--------------------------------------------------------------------------- +typedef NTSTATUS(*P_LdrLoadDll)( + WCHAR *PathString, ULONG *DllFlags, + UNICODE_STRING *ModuleName, HANDLE *ModuleHandle); + +typedef NTSTATUS (*P_LdrGetProcedureAddress)( + HANDLE ModuleHandle, ANSI_STRING *ProcName, ULONG ProcNum, + ULONG_PTR *Address); + +typedef NTSTATUS (*P_NtProtectVirtualMemory)( + HANDLE ProcessHandle, PVOID *BaseAddress, + PSIZE_T RegionSize, ULONG NewProtect, PULONG OldProtect); + +typedef NTSTATUS (*P_NtRaiseHardError)( + NTSTATUS ErrorStatus, ULONG NumberOfParameters, ULONG UnicodeBitMask, + ULONG_PTR *Parameters, ULONG ErrorOption, ULONG *ErrorReturn); + +//--------------------------------------------------------------------------- #define SBIELOW_CALL(x) ((P_##x)&data->x##_code) @@ -176,34 +194,135 @@ _FX UCHAR *FindDllExport2( return proc; } -#ifdef _M_ARM64 //--------------------------------------------------------------------------- -// MyGetProcedureAddress +// DetourFunc //--------------------------------------------------------------------------- -_FX NTSTATUS MyGetProcedureAddress(HMODULE ModuleHandle, PANSI_STRING FunctionName, WORD Ordinal, PVOID*FunctionAddress, INJECT_DATA *inject) +ULONG_PTR DetourFunc(INJECT_DATA *inject) { - SBIELOW_DATA* data = (SBIELOW_DATA*)*(ULONG64*)inject; - - typedef (*P_LdrGetProcedureAddress)(HMODULE, PANSI_STRING, WORD, PVOID*); - NTSTATUS status = ((P_LdrGetProcedureAddress)inject->LdrGetProcAddr)(ModuleHandle, FunctionName, Ordinal, FunctionAddress); - // - // in ARM64EC mode unwrap the FFS and return the native function + // Note: this function is invoked from the detour code hence when running in WoW64 + // the used instance of this function will be from the 32 bit version + // in which case we are unable to use SBIELOW_CALL and need to have a + // pointer to the apropriate 32 bit function + // + // Further more on ARM64 the SBIELOW_DATA will be allocated past the 4 GB boundry + // hence in 32 bit mode we can not access it, only INJECT_DATA is available // - if (data->flags.is_arm64ec && status >= 0) { - *FunctionAddress = Hook_GetFFSTarget(*FunctionAddress); - if (!*FunctionAddress) - return STATUS_ENTRYPOINT_NOT_FOUND; + NTSTATUS status; + UNICODE_STRING* pDllPath; + HANDLE ModuleHandle; + typedef VOID(*P_Dll_Ordinal1)(INJECT_DATA* inject); + P_Dll_Ordinal1 SbieDllOrdinal1; + void *RegionBase; + SIZE_T RegionSize; + ULONG OldProtect; + +#ifdef _WIN64 + SBIELOW_DATA* data = (SBIELOW_DATA*)inject->sbielow_data; +#endif + + // + // restore original function + // + + RegionBase = (void*)inject->RtlFindActCtx; +#ifdef _WIN64 +#ifdef _M_ARM64 + RegionSize = 16; + memcpy((void*)inject->RtlFindActCtx, inject->RtlFindActCtx_Bytes, 16); + + SBIELOW_CALL(NtFlushInstructionCache)( + NtCurrentProcess(), (void*)inject->RtlFindActCtx, 16); +#else + RegionSize = 12; + memcpy((void*)inject->RtlFindActCtx, inject->RtlFindActCtx_Bytes, 12); +#endif + + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + inject->RtlFindActCtx_Protect, &OldProtect); +#else + RegionSize = 5; + memcpy((void*)inject->RtlFindActCtx, inject->RtlFindActCtx_Bytes, 5); + + ((P_NtProtectVirtualMemory)inject->NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + inject->RtlFindActCtx_Protect, &OldProtect); +#endif + + // + // load kernel32.dll + // + + pDllPath = (UNICODE_STRING*)&inject->KernelDll; + + status = ((P_LdrLoadDll)inject->LdrLoadDll)(NULL, 0, pDllPath, &ModuleHandle); + + // + // load sbiedll.dll + // + + if (status == 0) { + + pDllPath = (UNICODE_STRING*)&inject->SbieDll; + + status = ((P_LdrLoadDll)inject->LdrLoadDll)(NULL, 0, pDllPath, &ModuleHandle); + } + + // + // get ordinal 1 from sbiedll + // + + if (status == 0) { + + status = ((P_LdrGetProcedureAddress)inject->LdrGetProcAddr)(ModuleHandle, NULL, 1, (ULONG_PTR*)&SbieDllOrdinal1); +#ifdef _M_ARM64 + // + // on ARM64EC we hook the native code hence we need to obtain the address of the native erdinal 1 from our SbieDll.dll + // instead of the FFS sequence as given by NtGetProcedureAddress when in ARM64EC mode + // + + if (data->flags.is_arm64ec && status >= 0) { + SbieDllOrdinal1 = (P_Dll_Ordinal1)Hook_GetFFSTarget((UCHAR*)SbieDllOrdinal1); + //if (!SbieDllOrdinal1) + // status = STATUS_ENTRYPOINT_NOT_FOUND; + } +#endif + } + + // + // call ordinal 1 of sbiedll.dll + // + + if (status == 0) { + + SbieDllOrdinal1(inject); + } + + // + // or report error if one occured instead + // + + else { + + wchar_t text[] = { 0 }; + SbieApi_LogMsg(inject->NtDeviceIoControlFile, inject->api_device_handle, 2181, text); + + status = 0xC0000142; // = STATUS_DLL_INIT_FAILED + ULONG_PTR Parameters[1] = { (ULONG_PTR)pDllPath }; + ULONG ErrorReturn; + ((P_NtRaiseHardError)inject->NtRaiseHardError)( + status | 0x10000000, // | FORCE_ERROR_MESSAGE_BOX + 1, 1, Parameters, 1, &ErrorReturn); } return status; } -#endif //--------------------------------------------------------------------------- // InitInject @@ -216,7 +335,7 @@ _FX void InitInject(SBIELOW_DATA *data, void *DetourCode) SYSCALL_DATA* syscall_data; INJECT_DATA *inject; SBIELOW_EXTRA_DATA *extra; - UCHAR *LdrCode, *MyHookCode; + UCHAR *HookTarget, *HookCode; void *RegionBase; SIZE_T RegionSize; ULONG OldProtect; @@ -284,67 +403,65 @@ _FX void InitInject(SBIELOW_DATA *data, void *DetourCode) // and RtlFindActivationContextSectionString // - LdrCode = FindDllExport(ntdll_base, - (UCHAR *)extra + extra->LdrLoadDll_offset, &uError); - if (!LdrCode) { + inject->LdrLoadDll = (ULONG_PTR)FindDllExport(ntdll_base, + (UCHAR *)extra + extra->LdrLoadDll_offset, &uError); +#ifdef _M_ARM64 + if (inject->LdrLoadDll && data->flags.is_arm64ec) + inject->LdrLoadDll = (ULONG_PTR)Hook_GetFFSTarget((UCHAR*)inject->LdrLoadDll); +#endif + if (!inject->LdrLoadDll) { SbieApi_DebugError(data, (0x01 << 4) | uError); return; } -#ifdef _M_ARM64 - if (data->flags.is_arm64ec) - LdrCode = Hook_GetFFSTarget(LdrCode); -#endif - if (!LdrCode) { - SbieApi_DebugError(data, 0x01d); - return; - } - inject->LdrLoadDll = (ULONG_PTR)LdrCode; - LdrCode = FindDllExport(ntdll_base, - (UCHAR *)extra + extra->LdrGetProcAddr_offset, &uError); - if (!LdrCode) { + inject->LdrGetProcAddr = (ULONG_PTR)FindDllExport(ntdll_base, + (UCHAR *)extra + extra->LdrGetProcAddr_offset, &uError); +#ifdef _M_ARM64 + if (inject->LdrGetProcAddr && data->flags.is_arm64ec) + inject->LdrGetProcAddr = (ULONG_PTR)Hook_GetFFSTarget((UCHAR*)inject->LdrGetProcAddr); +#endif + if (!inject->LdrGetProcAddr) { SbieApi_DebugError(data, (0x02 << 4) | uError); return; } -#ifdef _M_ARM64 - if (data->flags.is_arm64ec) - LdrCode = Hook_GetFFSTarget(LdrCode); -#endif - if (!LdrCode) { - SbieApi_DebugError(data, 0x02d); - return; - } - inject->LdrGetProcAddr = (ULONG_PTR)LdrCode; - -#ifdef _M_ARM64 - - // - // on ARM64EC we hook the native code hence we need the custom MyGetProcedureAddress - // to obtain the address of the native original 1 from our SbieDll.dll - // instead of the FFS sequence as given by NtGetProcedureAddress - // - - inject->MyGetProcAddr = (ULONG_PTR)MyGetProcedureAddress; -#endif #ifdef _WIN64 if (data->flags.is_wow64) { - LdrCode = FindDllExport(ntdll_base, - (UCHAR*)extra + extra->NtRaiseHardError_offset, &uError); - if (!LdrCode) { + + inject->NtProtectVirtualMemory = (ULONG_PTR)FindDllExport(ntdll_base, + (UCHAR*)extra + extra->NtProtectVirtualMemory_offset, &uError); + if (!inject->NtProtectVirtualMemory) { SbieApi_DebugError(data, (0x03 << 4) | uError); return; } - inject->NtRaiseHardError = (ULONG_PTR)LdrCode; + + inject->NtRaiseHardError = (ULONG_PTR)FindDllExport(ntdll_base, + (UCHAR*)extra + extra->NtRaiseHardError_offset, &uError); + if (!inject->NtRaiseHardError) { + SbieApi_DebugError(data, (0x04 << 4) | uError); + return; + } + + inject->NtDeviceIoControlFile = (ULONG_PTR)FindDllExport(ntdll_base, + (UCHAR*)extra + extra->NtDeviceIoControlFile_offset, &uError); + if (!inject->NtDeviceIoControlFile) { + SbieApi_DebugError(data, (0x05 << 4) | uError); + return; + } } else #endif + { + // + // for ARM64EC we need native functions, FindDllExport can manage FFS's + // however this does not work for syscalls, hence we use the native function directly + // - // - // for ARM64EC we need native functions, FindDllExport can manage FFS's - // however this does not work for syscalls, hence we use the native function directly - // + inject->NtProtectVirtualMemory = data->NativeNtProtectVirtualMemory; inject->NtRaiseHardError = data->NativeNtRaiseHardError; + inject->NtDeviceIoControlFile = data->NtDeviceIoControlFile; + } + inject->api_device_handle = data->api_device_handle; #ifdef _M_ARM64 @@ -355,226 +472,168 @@ _FX void InitInject(SBIELOW_DATA *data, void *DetourCode) // if (!data->flags.is_wow64) - LdrCode = (UCHAR*)inject->LdrLoadDll; + HookTarget = (UCHAR*)inject->LdrLoadDll; else #endif { - LdrCode = FindDllExport(ntdll_base, + HookTarget = FindDllExport(ntdll_base, (UCHAR *)extra + extra->RtlFindActCtx_offset, &uError); - if (!LdrCode) { - SbieApi_DebugError(data, (0x04 << 4) | uError); + if (!HookTarget) { + SbieApi_DebugError(data, (0x05 << 4) | uError); return; } } - inject->RtlFindActCtx = (ULONG_PTR)LdrCode; + inject->RtlFindActCtx = (ULONG_PTR)HookTarget; // // prepare unicode strings // - inject->KernelDll_Length = (USHORT)extra->KernelDll_length; - inject->KernelDll_MaxLen = inject->KernelDll_Length + sizeof(WCHAR); - inject->KerneDll_Buf32 = + inject->KernelDll.Length = (USHORT)extra->KernelDll_length; + inject->KernelDll.MaxLen = inject->KernelDll.Length + sizeof(WCHAR); + inject->KernelDll.Buf32 = (ULONG)((ULONG_PTR)extra + extra->KernelDll_offset); - inject->KerneDll_Buf64 = - (ULONG64)((ULONG_PTR)extra + extra->KernelDll_offset); - - #ifdef _WIN64 - if (data->flags.is_wow64) { + inject->KernelDll.Buf64 = + (ULONG64)((ULONG_PTR)extra + extra->KernelDll_offset); +#endif - InitInjectWow64(data); - return; - } -#endif _WIN64 + // + // sellect the right version of SbieDll.dll + // #ifdef _M_ARM64 if (data->flags.is_arm64ec) { - inject->SbieDll_Length = (SHORT)extra->Arm64ecSbieDll_length; - inject->SbieDll_MaxLen = inject->SbieDll_Length + sizeof(WCHAR); - inject->SbieDll_Buf64 = + inject->SbieDll.Length = (SHORT)extra->Arm64ecSbieDll_length; + inject->SbieDll.MaxLen = inject->SbieDll.Length + sizeof(WCHAR); + inject->SbieDll.Buf64 = (ULONG64)((ULONG_PTR)extra + extra->Arm64ecSbieDll_offset); } else #endif +#ifdef _WIN64 + if (data->flags.is_wow64) { - inject->SbieDll_Length = (SHORT)extra->NativeSbieDll_length; - inject->SbieDll_MaxLen = inject->SbieDll_Length + sizeof(WCHAR); - inject->SbieDll_Buf32 = - (ULONG)((ULONG_PTR)extra + extra->NativeSbieDll_offset); - inject->SbieDll_Buf64 = + inject->SbieDll.Length = (SHORT)extra->Wow64SbieDll_length; + inject->SbieDll.MaxLen = inject->SbieDll.Length + sizeof(WCHAR); + inject->SbieDll.Buf32 = + (ULONG)((ULONG_PTR)extra + extra->Wow64SbieDll_offset); + } + else +#endif + { + inject->SbieDll.Length = (SHORT)extra->NativeSbieDll_length; + inject->SbieDll.MaxLen = inject->SbieDll.Length + sizeof(WCHAR); +#ifdef _WIN64 + inject->SbieDll.Buf64 = (ULONG64)((ULONG_PTR)extra + extra->NativeSbieDll_offset); +#else + inject->SbieDll.Buf32 = + (ULONG)((ULONG_PTR)extra + extra->NativeSbieDll_offset); +#endif } // - // select version of RtlFindActivationContextSectionString detour code: - // because both the 32-bit and 64-bit versions of this SbieLow code must - // handle 32-bit programs, both versions include the 32-bit detour code. - // (see entry.asm) + // modify our detour code in entry.asm to include a hard coded pointer to the inject data area. // - - - // - // modify our RtlFindActivationContextSectionString detour code in - // entry.asm to include a hard coded pointer to the inject data area. +#ifdef _WIN64 + if (!data->flags.is_wow64) { + #ifdef _M_ARM64 - MyHookCode = (UCHAR *) DetourCode; - RegionBase = (void *)(MyHookCode - 8); - RegionSize = sizeof(ULONG_PTR); - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &OldProtect); + HookCode = (UCHAR*)DetourCode; + RegionBase = (void*)(HookCode - 8); + RegionSize = sizeof(ULONG_PTR); + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &OldProtect); - *(ULONG_PTR *)(MyHookCode - 8) = (ULONG_PTR)inject; + *(ULONG_PTR*)(HookCode - 8) = (ULONG_PTR)inject; - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - OldProtect, &OldProtect); + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + OldProtect, &OldProtect); - RegionBase = (void *)&LdrCode[0]; // RtlFindActCtx - RegionSize = 16; - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &inject->RtlFindActCtx_Protect); - memcpy(&inject->RtlFindActCtx_Bytes, LdrCode, 16); + RegionBase = (void*)&HookTarget[0]; // RtlFindActCtx + RegionSize = 16; + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &inject->RtlFindActCtx_Protect); + memcpy(inject->RtlFindActCtx_Bytes, HookTarget, 16); - ULONG* aCode = (ULONG*)LdrCode; - *aCode++ = 0x58000048; // ldr x8, 8 - *aCode++ = 0xD61F0100; // br x8 - *(DWORD64*)aCode = (DWORD64)MyHookCode; + ULONG* aCode = (ULONG*)HookTarget; + *aCode++ = 0x58000048; // ldr x8, 8 + *aCode++ = 0xD61F0100; // br x8 + *(DWORD64*)aCode = (DWORD64)HookCode; - SBIELOW_CALL(NtFlushInstructionCache)( - NtCurrentProcess(), RegionBase, (ULONG)RegionSize); - -#elif _WIN64 - - MyHookCode = (UCHAR *) DetourCode; - RegionBase = (void *)(MyHookCode - 8); - RegionSize = sizeof(ULONG_PTR); - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &OldProtect); - - *(ULONG_PTR *)(MyHookCode - 8) = (ULONG_PTR)inject; - - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - OldProtect, &OldProtect); - - RegionBase = (void *)&LdrCode[0]; // RtlFindActCtx - RegionSize = 12; - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &inject->RtlFindActCtx_Protect); - memcpy(&inject->RtlFindActCtx_Bytes, LdrCode, 12); - - LdrCode[0] = 0x48; - LdrCode[1] = 0xb8; - *(ULONG_PTR *)&LdrCode[2] = (ULONG_PTR)MyHookCode; - LdrCode[10] = 0xff; - LdrCode[11] = 0xe0; + SBIELOW_CALL(NtFlushInstructionCache)( + NtCurrentProcess(), RegionBase, (ULONG)RegionSize); #else - MyHookCode = (UCHAR *)DetourCode; - RegionBase = (void *)(MyHookCode + 1); - RegionSize = sizeof(ULONG_PTR); + HookCode = (UCHAR*)DetourCode; + RegionBase = (void*)(HookCode - 8); + RegionSize = sizeof(ULONG_PTR); + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &OldProtect); - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &OldProtect); + *(ULONG_PTR*)(HookCode - 8) = (ULONG_PTR)inject; - *(ULONG *)(MyHookCode + 1) = (ULONG)(ULONG_PTR)inject; + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + OldProtect, &OldProtect); - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - OldProtect, &OldProtect); + RegionBase = (void*)&HookTarget[0]; // RtlFindActCtx + RegionSize = 12; + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &inject->RtlFindActCtx_Protect); + memcpy(inject->RtlFindActCtx_Bytes, HookTarget, 12); - RegionBase = (void *)LdrCode; // RtlFindActCtx - RegionSize = 5; - - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &inject->RtlFindActCtx_Protect); - - memcpy(&inject->RtlFindActCtx_Bytes, LdrCode, 5); - - LdrCode[0] = 0xE9; - *(ULONG *)&LdrCode[1] = (ULONG)(MyHookCode - (LdrCode + 5)); + HookTarget[0] = 0x48; + HookTarget[1] = 0xb8; + *(ULONG_PTR*)&HookTarget[2] = (ULONG_PTR)HookCode; + HookTarget[10] = 0xff; + HookTarget[11] = 0xe0; #endif + + } + else + { + HookCode = (UCHAR*)data->ptr_32bit_detour; +#else + { + HookCode = (UCHAR*)DetourCode; +#endif + RegionBase = (void*)(HookCode + 1); + RegionSize = sizeof(ULONG_PTR); + + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &OldProtect); + + *(ULONG*)(HookCode + 1) = (ULONG)(ULONG_PTR)inject; + + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + OldProtect, &OldProtect); + + RegionBase = (void*)HookTarget; // RtlFindActCtx + RegionSize = 5; + + SBIELOW_CALL(NtProtectVirtualMemory)( + NtCurrentProcess(), &RegionBase, &RegionSize, + PAGE_EXECUTE_READWRITE, &inject->RtlFindActCtx_Protect); + + memcpy(inject->RtlFindActCtx_Bytes, HookTarget, 5); + + HookTarget[0] = 0xE9; + *(ULONG*)&HookTarget[1] = (ULONG)(HookCode - (HookTarget + 5)); + } } - - -//--------------------------------------------------------------------------- -// InitInjectWow64 -//--------------------------------------------------------------------------- - - -#ifdef _WIN64 -_FX void InitInjectWow64(SBIELOW_DATA *data) -{ - SYSCALL_DATA* syscall_data; - INJECT_DATA *inject; - SBIELOW_EXTRA_DATA *extra; - UCHAR *LdrCode, *MyCode; - void *RegionBase; - SIZE_T RegionSize; - - // - // find inject and extra data areas, same as in InitInject() - // - - syscall_data = (SYSCALL_DATA *)data->syscall_data; - - extra = (SBIELOW_EXTRA_DATA *) (data->syscall_data + syscall_data->extra_data_offset); - - inject = (INJECT_DATA *) ((UCHAR *)extra + extra->InjectData_offset); - - // - // prepare unicode strings - // - - inject->SbieDll_Length = (SHORT)extra->Wow64SbieDll_length; - inject->SbieDll_MaxLen = inject->SbieDll_Length + sizeof(WCHAR); - inject->SbieDll_Buf32 = - (ULONG)((ULONG_PTR)extra + extra->Wow64SbieDll_offset); - - // - // the service fills INJECT_DATA.DetourCode_x86 with the right non native code - // - - MyCode = inject->DetourCode_x86; - - // - // modify our copied detour code to include a hard coded pointer to - // the inject data area (which is the syscall data area) - // - - *(ULONG *)(MyCode + 1) = (ULONG)(ULONG_PTR)inject; - - // - // hook the top of RtlFindActivationContextSectionString - // to jump to our copied detour - // - - LdrCode = (UCHAR *)inject->RtlFindActCtx; - - RegionBase = (void *)LdrCode; - RegionSize = 5; - - SBIELOW_CALL(NtProtectVirtualMemory)( - NtCurrentProcess(), &RegionBase, &RegionSize, - PAGE_EXECUTE_READWRITE, &inject->RtlFindActCtx_Protect); - - memcpy(&inject->RtlFindActCtx_Bytes, LdrCode, 5); - - LdrCode[0] = 0xE9; - *(ULONG *)&LdrCode[1] = (ULONG)(MyCode - (LdrCode + 5)); -} -#endif _WIN64 diff --git a/Sandboxie/core/low/lowdata.h b/Sandboxie/core/low/lowdata.h index e830aed7..05b2ab1a 100644 --- a/Sandboxie/core/low/lowdata.h +++ b/Sandboxie/core/low/lowdata.h @@ -1,6 +1,6 @@ /* * Copyright 2004-2020 Sandboxie Holdings, LLC - * Copyright 2020-2022 David Xanatos, xanasoft.com + * Copyright 2020-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 @@ -103,16 +103,16 @@ typedef struct _SBIELOW_DATA { ULONG64 RealNtDeviceIoControlFile; // offset 224 ULONG64 NtDeviceIoControlFile; // for ARM64 // offset 232 - ULONG64 NativeNtRaiseHardError; // offset 240 + ULONG64 NativeNtProtectVirtualMemory; // offset 240 + ULONG64 NativeNtRaiseHardError; // offset 248 ULONG64 pSystemService; - ULONG64 DebugData[16]; - #ifdef _WIN64 SBIELOW_J_TABLE * Sbie64bitJumpTable; ULONG64 ntdll_wow64_base; + ULONG64 ptr_32bit_detour; #endif #ifdef _M_ARM64 @@ -142,7 +142,9 @@ typedef struct _SBIELOW_EXTRA_DATA { ULONG LdrLoadDll_offset; ULONG LdrGetProcAddr_offset; + ULONG NtProtectVirtualMemory_offset; ULONG NtRaiseHardError_offset; + ULONG NtDeviceIoControlFile_offset; ULONG RtlFindActCtx_offset; #ifdef _M_ARM64 ULONG RtlImageOptionsEx_offset; @@ -206,51 +208,45 @@ typedef struct _SYSCALL_DATA32 { // win32u.dll } SYSCALL_DATA32; +// +// UNICIDE_STRING compatible with 32 and 64 bit API +// + +typedef struct _UNIVERSAL_STRING { + USHORT Length; + USHORT MaxLen; + ULONG Buf32; + ULONG64 Buf64; +} UNIVERSAL_STRING; + // // temporary data used by the Detour Code any changed to // this structure must be synchronized with all 3 versions of the -// Detour Code as well as with the binary copies of the x86 and x64 code -// -// entry_asm.asm, entry_arm.asm and lowlevel_code.c +// in entry_asm.asm and entry_arm.asm // typedef struct _INJECT_DATA { ULONG64 sbielow_data; // 0 - union { - ULONG64 LdrLoadDll; // 8 - ULONG64 RtlFindActCtx_SavedArg1; // todo: split this - }; - ULONG64 LdrGetProcAddr; // 16 - ULONG64 NtRaiseHardError; // 24 - ULONG64 RtlFindActCtx; // 32 + ULONG64 RtlFindActCtx; // 8 + ULONG RtlFindActCtx_Protect; + UCHAR RtlFindActCtx_Bytes[20]; - ULONG RtlFindActCtx_Protect; // 40 - UCHAR RtlFindActCtx_Bytes[20]; // 44 + ULONG64 LdrLoadDll; + ULONG64 LdrGetProcAddr; + ULONG64 NtProtectVirtualMemory; + ULONG64 NtRaiseHardError; + ULONG64 NtDeviceIoControlFile; + ULONG64 api_device_handle; - USHORT KernelDll_Length; // 64 - USHORT KernelDll_MaxLen; - ULONG KerneDll_Buf32; - ULONG64 KerneDll_Buf64; - - USHORT SbieDll_Length; // 80 - USHORT SbieDll_MaxLen; - ULONG SbieDll_Buf32; - ULONG64 SbieDll_Buf64; - - ULONG64 ModuleHandle; // 96 - ULONG64 SbieDllOrdinal1; // 104 - - ULONG64 MyGetProcAddr; // 112 - -#ifdef _WIN64 - UCHAR DetourCode_x86[128]; // 120 -#endif _WIN64 + UNIVERSAL_STRING KernelDll; + UNIVERSAL_STRING SbieDll; } INJECT_DATA; + //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/low/lowlevel_code.c b/Sandboxie/core/low/lowlevel_code.c deleted file mode 100644 index 4fc63b01..00000000 --- a/Sandboxie/core/low/lowlevel_code.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2004-2020 Sandboxie Holdings, LLC - * Copyright 2020-2022 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 . - */ - -#ifdef _WIN64 - -// -// we need the 32-bit version of RtlFindActivationContextSectionString -// on both 32-bit and 64-bit versions of SbieLow, because of wow64 -// -// it will not compile correctly as assembly on 64-bit, so we simply -// dump the machine code bytes here -// - -UCHAR SbieDll_ShellCode_x86[] = -{ - 0xBA, 0, 0, 0, 0, // mov edx, 0 ; edx -> inject data area - - //0xCC, // int3 - - 0x56, // push esi - 0x8B, 0xF2, // mov esi, edx ; esi -> inject data area - - // - // restore bytes - // - - 0x8B, 0x46, 0x20, // mov eax,dword ptr [esi+20h] ; ... [esi].InjectData.RtlFindActCtx - 0x8A, 0x56, 0x2C, // mov dl,byte ptr [esi+2Ch] ; ... [esi].InjectData.RtlFindActCtx_Bytes - 0x88, 0x10, // mov byte ptr [eax],dl - 0x8B, 0x56, 0x2D, // mov edx,dword ptr [esi+2Dh] ; ... [esi].InjectData.RtlFindActCtx_Bytes+1 - 0x89, 0x50, 0x01, // mov dword ptr [eax+1],edx - - // - // call LdrLoadDll for kernel32 - // - - 0xb9, 0x10, 0, 0, 0, // mov ecx, 10h - // LdrLoadDll_Retry: - //for(i = 0; i < 0x10; i++) { - 0x51, // push ecx - 0x8D, 0x46, 0x60, // lea eax,[esi+60h] ; ... [esi].InjectData.ModuleHandle - 0x50, // push eax - 0x8D, 0x46, 0x40, // lea eax,[esi+40h] ; ... [esi].InjectData.KernelDll_Unicode - 0x50, // push eax - 0x6A, 0x00, // push 0 - 0x6A, 0x00, // push 0 - 0xFF, 0x56, 0x08, // call dword ptr [esi+8] ; ... [esi].InjectData.LdrLoadDll - 0x59, // pop ecx - 0x85, 0xC0, // test eax,eax - 0x74, 0x04, // jz LdrLoadDll_Good - //} - 0xE2, 0xE9, // loop LdrLoadDll_Retry - 0xEB, 0x34, // jmp error - // LdrLoadDll_Good: - - // - // call LdrLoadDll for sbiedll - // - - 0x8D, 0x46, 0x60, // lea eax,[esi+60h] ; ... [esi].InjectData.ModuleHandle - 0x50, // push eax - 0x8D, 0x46, 0x50, // lea eax,[esi+50h] ; ... [esi].InjectData.SbieDll_Unicode - 0x50, // push eax - 0x6A, 0x00, // push 0 - 0x6A, 0x00, // push 0 - 0xFF, 0x56, 0x08, // call dword ptr [esi+8] ; ... [esi].InjectData.LdrLoadDll - - 0x85, 0xC0, // test eax,eax - 0x75, 0x21, // jnz RtlFindActivationContextSectionStringError - - // - // call LdrGetProcedureAddress for sbiedll ordinal 1, - // which forces ntdll to initialize sbiedll - // - - 0x8D, 0x46, 0x68, // lea eax,[esi+68h] ; ... [esi].InjectData.SbieDllOrdinal1 - 0x50, // push eax - 0x6A, 0x01, // push 1 - 0x6A, 0x00, // push 0 - 0xFF, 0x76, 0x60, // push dword ptr [esi+60h] ; ... [esi].InjectData.ModuleHandle - 0xFF, 0x56, 0x10, // call dword ptr [esi+10h] ; ... [esi].InjectData.LdrGetProcAddr - - 0x85, 0xC0, // test eax,eax - 0x75, 0x0F, // jnz RtlFindActivationContextSectionStringError - - // - // pass control to ordinal 1 ... - // - - 0x8B, 0xC6, // mov eax, esi - 0x87, 0x44, 0x24, 0x08, // xchg eax, dword ptr [esp+8] - 0x89, 0x46, 0x08, // mov dword ptr [esi+8],eax ; ... [esi].InjectData.LdrLoadDll ... - 0x8B, 0xC6, // mov eax, esi - 0x5E, // pop esi - 0xFF, 0x60, 0x68, // jmp dword ptr [eax+68h] ; ... [eax].InjectData.SbieDllOrdinal1 - - // - // display error message ... - // - - // RtlFindActivationContextSectionStringError: - 0x50, // push eax - - 0x8D, 0x56, 0x50, // lea edx,[esi+50h] ; ... [esi].InjectData.SbieDll_Unicode - 0x89, 0x56, 0x08, // mov dword ptr [esi+8],edx ; ... [esi].InjectData.LdrLoadDll ... - - 0x8d, 0x56, 0x10, // lea edx,[esi+10h] ; ... [esi].InjectData.LdrGetProcAddr - 0x52, // push edx - 0x6A, 0x01, // push 1 - 0x8D, 0x56, 0x08, // lea edx,[esi+8] ; ... [esi].InjectData.LdrLoadDll - 0x52, // push edx - 0x6A, 0x01, // push 1 - 0x6A, 0x01, // push 1 - 0x68, 0x42, 0x01, 0x00, 0xD0, // push 0D0000142h - 0xFF, 0x56, 0x18, // call dword ptr [esi+18h] ; ... [esi].InjectData.NtRaiseHardError - - 0x58, // pop eax - 0x5E, // pop esi - 0xC2, 0x14, 0 // ret 14h -}; - -#endif - -#ifdef _M_ARM64 - -// -// we need the x64 version of RtlFindActivationContextSectionString -// -// it will not compile correctly as assembly on arm64, so we simply -// dump the machine code bytes here -// - -//UCHAR SbieDll_ShellCode_x64[] = -//{ -// -// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // inject data area address -// -// 0x48, 0x8B, 0x05, 0xF1, 0xFF, 0xFF, 0xFF, // mov rax, qword ptr [rip - 0xf] ; rax -> inject data area -// -// // 0xCC, // int3 -// -// 0x56, // push rsi ; save rsi, and align stack -// 0x48, 0x83, 0xEC, 0x40, // sub rsp, 0x40 ; set up local stack -// -// 0x48, 0x89, 0x4C, 0x24, 0x20, // mov qword ptr [rsp + 0x20], rcx -// 0x48, 0x89, 0x54, 0x24, 0x28, // mov qword ptr [rsp + 0x28], rdx -// 0x4C, 0x89, 0x44, 0x24, 0x30, // mov qword ptr [rsp + 0x30], r8 -// 0x4C, 0x89, 0x4C, 0x24, 0x38, // mov qword ptr [rsp + 0x38], r9 -// -// 0x48, 0x8B, 0xF0, // mov rsi, rax ; rsi -> inject data area -// -// 0x48, 0x8B, 0x46, 0x20, // mov rax, qword ptr [rsi + 0x20] ; ... [rsi].InjectData.RtlFindActCtx -// -// // replace 12bytes -// 0x48, 0x8B, 0x56, 0x2C, // mov rdx, qword ptr [rsi + 0x2c] ; ... [rsi].InjectData.RtlFindActCtx_Bytes -// 0x48, 0x89, 0x10, // mov qword ptr [rax], rdx -// 0x8B, 0x56, 0x34, // mov edx, dword ptr [rsi + 0x34] ; ... [rsi].InjectData.RtlFindActCtx_Bytes + 8 -// 0x89, 0x50, 0x08, // mov dword ptr [rax + 8], edx -// -// // -// // call LdrLoadDll for kernel32 -// // -// //// retry loop -// 0x48, 0x89, 0x5E, 0x2C, // mov qword ptr [rsi + 0x2c], rbx ; ... [rsi].InjectData.RtlFindActCtx_Bytes ... -// 0x48, 0xC7, 0xC3, 0x10, 0x00, 0x00, 0x00, // mov rbx, 0x10 -// -// // LdrLoadRetry: -// 0x48, 0x33, 0xC9, // xor rcx, rcx -// 0x48, 0x33, 0xD2, // xor rdx, rdx -// 0x4C, 0x8D, 0x46, 0x40, // lea r8, [rsi + 0x40] ; ... [rsi].InjectData.KernelDll_Unicode -// 0x4C, 0x8D, 0x4E, 0x60, // lea r9, [rsi + 0x60] ; ... [rsi].InjectData.ModuleHandle -// //cmp rbx,1 -// //jnz LdrTestLoop -// 0xFF, 0x56, 0x08, // call qword ptr [rsi + 8] ; ... [rsi].InjectData.LdrLoadDll -// 0x85, 0xC0, // test eax, eax -// 0x74, 0x0A, // je 0x5e ; LdrLoadGood -// ////LdrTestLoop: -// 0x48, 0xFF, 0xCB, // dec rbx -// 0x48, 0x85, 0xDB, // test rbx, rbx -// 0x75, 0xE3, // jne 0x3f ; ;loop LdrLoadRetry -// 0xEB, 0x54, // jmp 0xb2 ; RtlFindActivationContextSectionStringError -// -// // -// // call LdrLoadDll for sbiedll -// // -// // LdrLoadGood: -// 0x48, 0x8B, 0x5E, 0x2C, // mov rbx, qword ptr [rsi + 0x2c] ; ... [rsi].InjectData.RtlFindActCtx_Bytes -// 0x48, 0x33, 0xC9, // xor rcx, rcx -// 0x48, 0x33, 0xD2, // xor rdx, rdx -// 0x4C, 0x8D, 0x46, 0x50, // lea r8, [rsi + 0x50] ; ... [rsi].InjectData.SbieDll_Unicode -// 0x4C, 0x8D, 0x4E, 0x60, // lea r9, [rsi + 0x60] ; ... [rsi].InjectData.ModuleHandle -// 0xFF, 0x56, 0x08, // call qword ptr [rsi + 8] ; ... [rsi].InjectData.LdrLoadDll -// -// 0x85, 0xC0, // test eax, eax -// 0x75, 0x3B, // jne 0xb2 ; RtlFindActivationContextSectionStringError -// -// // -// // call LdrGetProcedureAddress for sbiedll ordinal 1, -// // which forces ntdll to initialize sbiedll -// // -// -// 0x48, 0x8B, 0x4E, 0x60, // mov rcx, qword ptr [rsi + 0x60] ; ... [rsi].InjectData.ModuleHandle -// 0x48, 0x33, 0xD2, // xor rdx, rdx -// 0x4D, 0x33, 0xC0, // xor r8, r8 -// 0x49, 0xFF, 0xC0, // inc r8 -// 0x4C, 0x8D, 0x4E, 0x68, // lea r9, [rsi + 0x68] ; ... [rsi].InjectData.SbieDllOrdinal1 -// 0xFF, 0x56, 0x10, // call qword ptr [rsi + 0x10] ; ... [rsi].InjectData.LdrGetProcAddr -// -// 0x85, 0xC0, // test eax, eax -// 0x75, 0x23, // jne 0xb2 ; 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 -// // -// -// 0x48, 0x8B, 0x44, 0x24, 0x20, // mov rax, qword ptr [rsp + 0x20] -// 0x48, 0x89, 0x46, 0x08, // mov qword ptr [rsi + 8], rax ; ... [rsi].InjectData.LdrLoadDll ... -// 0x48, 0x8B, 0xCE, // mov rcx, rsi -// 0x48, 0x8B, 0x54, 0x24, 0x28, // mov rdx, qword ptr [rsp + 0x28] -// 0x4C, 0x8B, 0x44, 0x24, 0x30, // mov r8, qword ptr [rsp + 0x30] -// 0x4C, 0x8B, 0x4C, 0x24, 0x38, // mov r9, qword ptr [rsp + 0x38] -// -// 0x48, 0x83, 0xC4, 0x40, // add rsp, 0x40 -// 0x5E, // pop rsi -// 0xFF, 0x61, 0x68, // jmp qword ptr [rcx + 0x68] ; [rcx].InjectData.SbieDllOrdinal1 -// -// // -// // display error message, invoke NtRaiseHardError( -// // NTSTATUS ntstatus_message_code, -// // ULONG number_of_parameters_in_list, -// // ULONG mask_of_strings_in_list, -// // ULONG_PTR *list_of_pointers_to_parameters, -// // ULONG response_buttons, -// // ULONG *out_response) -// // -// -// //RtlFindActivationContextSectionStringError: -// -// 0x48, 0x89, 0x44, 0x24, 0x38, // mov qword ptr [rsp + 0x38], rax ; save ntstatus -// 0xB9, 0x42, 0x01, 0x00, 0xD0, // mov ecx, 0xd0000142 ; ntstatus_message_code -// 0x48, 0x33, 0xD2, // xor rdx, rdx ; number_of_parameters_in_list -// 0x48, 0xFF, 0xC2, // inc rdx -// 0x4C, 0x8B, 0xC2, // mov r8, rdx ; mask_of_strings_in_list -// 0x67, 0x4C, 0x8D, 0x4E, 0x08, // lea r9, [esi + 8] ; ... [esi].InjectData.LdrLoadDll ; list_of_pointers_to_parameters -// 0x48, 0x8D, 0x46, 0x50, // lea rax, [rsi + 0x50] ; ... [rsi].InjectData.SbieDll_Unicode -// 0x49, 0x89, 0x01, // mov qword ptr [r9], rax -// 0x48, 0x89, 0x54, 0x24, 0x20, // mov qword ptr [rsp + 0x20], rdx ; response_buttons - ERROR_OK -// 0x48, 0x8D, 0x46, 0x10, // lea rax, [rsi + 0x10] ; ... [rsi].InjectData.LdrGetProcAddr -// 0x48, 0x89, 0x44, 0x24, 0x28, // mov qword ptr [rsp + 0x28], rax ; out_response -// 0xFF, 0x56, 0x18, // call qword ptr [rsi + 0x18] ; ... [rsi].InjectData.NtRaiseHardError -// 0x48, 0x8B, 0x4C, 0x24, 0x38, // mov rcx, qword ptr [rsp + 0x38] ; restore ntstatus -// 0x48, 0x83, 0xC4, 0x40, // add rsp, 0x40 -// 0x5E, // pop rsi -// 0xC3 // ret ; return to caller with error -//}; - -#endif \ No newline at end of file diff --git a/Sandboxie/install/kmdutil/fixdacls.cpp b/Sandboxie/install/kmdutil/fixdacls.cpp new file mode 100644 index 00000000..31ac3789 --- /dev/null +++ b/Sandboxie/install/kmdutil/fixdacls.cpp @@ -0,0 +1,215 @@ +/* +* Copyright 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 . +*/ + +#include "stdafx.h" + +#include +#include +#include +#include +#include "common/defines.h" +#include "common/my_version.h" +#include "core/dll/sbieapi.h" +#include +#include + +extern "C" void Display_Error(PWSTR SubFuncName, DWORD LastError); + +struct SDaclEntry +{ + SDaclEntry() : pSid(NULL), AllowMask(0),DenyMask(0) {} + BYTE bSid[68]; + PSID pSid; + ACCESS_MASK AllowMask; + ACCESS_MASK DenyMask; +}; + +std::map ListFolderDACLs(const wchar_t* folderPath) +{ + std::map map; + + PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; + DWORD result = GetNamedSecurityInfoW(folderPath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSecurityDescriptor); + if (result != ERROR_SUCCESS) { + Display_Error(L"GetNamedSecurityInfoW", result); + return map; + } + + BOOL ok; + PACL pDacl = NULL; + BOOL bDaclPresent = FALSE; + BOOL bDaclDefaulted = FALSE; + ok = GetSecurityDescriptorDacl(pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted); + if (!ok) { + Display_Error(L"GetSecurityDescriptorDacl", 0); + return map; + } + if (!bDaclPresent) + return map; // empty not an error + + for (DWORD i = 0; i < pDacl->AceCount; ++i) { + + PACE_HEADER pAceHeader = NULL; + if (!GetAce(pDacl, i, (LPVOID*)&pAceHeader)) { + //Display_Error(L"GetAce", 0); + continue; + } + + PSID pSid = NULL; + ACCESS_MASK AllowMask = 0; + ACCESS_MASK DenyMask = 0; + switch (pAceHeader->AceType) { + case ACCESS_ALLOWED_ACE_TYPE: { + PACCESS_ALLOWED_ACE pAce = (PACCESS_ALLOWED_ACE)pAceHeader; + pSid = (PSID)&pAce->SidStart; + AllowMask = pAce->Mask; + break; + } + case ACCESS_DENIED_ACE_TYPE: { + PACCESS_DENIED_ACE pAce = (PACCESS_DENIED_ACE)pAceHeader; + pSid = (PSID)&pAce->SidStart; + DenyMask = pAce->Mask; + break; + } + } + + if (pSid) { + LPWSTR pSidString = NULL; + if (ConvertSidToStringSidW(pSid, &pSidString)) { + SDaclEntry& entry = map[pSidString]; + if (!entry.pSid) { + CopySid(sizeof(entry.bSid), entry.bSid, pSid); + entry.pSid = entry.bSid; + } + entry.AllowMask |= AllowMask; + entry.DenyMask |= DenyMask; + LocalFree(pSidString); + } + } + } + + LocalFree(pSecurityDescriptor); + + return map; +} + +BOOL UpdateFolderDACLs(const wchar_t* folderPath, EXPLICIT_ACCESS *ea) +{ + PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; + DWORD result = GetNamedSecurityInfoW(folderPath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSecurityDescriptor); + if (result != ERROR_SUCCESS) { + Display_Error(L"GetNamedSecurityInfoW", result); + return FALSE; + } + + BOOL ok; + PACL pDacl = NULL; + BOOL bDaclPresent = FALSE; + BOOL bDaclDefaulted = FALSE; + ok = GetSecurityDescriptorDacl(pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted); + if (!ok) { + Display_Error(L"GetSecurityDescriptorDacl", 0); + return FALSE; + } + if (!bDaclPresent) { + Display_Error(L"GetSecurityDescriptorDacl", ERROR_INVALID_ACCESS); + return FALSE; + } + + result = SetEntriesInAclW(1, ea, pDacl, &pDacl); + if (result != ERROR_SUCCESS) + Display_Error(L"SetEntriesInAclW", result); + else { + result = SetNamedSecurityInfoW((LPWSTR)folderPath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL); + if (result != ERROR_SUCCESS) + Display_Error(L"SetNamedSecurityInfoW", result); + } + + LocalFree(pSecurityDescriptor); + return result == ERROR_SUCCESS; +} + +//--------------------------------------------------------------------------- +// Kmd_FixDacls +//--------------------------------------------------------------------------- + +extern "C" BOOL Kmd_FixDacls() +{ + WCHAR HomePath[MAX_PATH]; + SbieApi_GetHomePath(NULL, 0, HomePath, MAX_PATH); + if (!*HomePath) // sbie not installed or not running + return FALSE; + + // + // remove problematic permissions created when the + // win 11 shell extension was registered + // for a folder not being under program files + // + + std::map map = ListFolderDACLs(HomePath); + + for (auto I = map.begin(); I != map.end(); ++I) { + + if (I->first.length() > 44 && ( + (I->first.substr(0, 13) == L"S-1-15-3-1024") + || (I->first.substr(0, 8) == L"S-1-15-2") )) { + + EXPLICIT_ACCESS ea_clear = + { + GENERIC_ALL, + REVOKE_ACCESS, + SUB_CONTAINERS_AND_OBJECTS_INHERIT, + { + NULL, + NO_MULTIPLE_TRUSTEE, + TRUSTEE_IS_SID, + TRUSTEE_IS_GROUP, + reinterpret_cast(I->second.pSid) + } + }; + + UpdateFolderDACLs(HomePath, &ea_clear); + } + } + + // + // add read access for ALL_APP_PACKAGES + // + + PSID pSid = NULL; // ALL_APP_PACKAGES + ConvertStringSidToSidW(L"S-1-15-2-1", &pSid); + + EXPLICIT_ACCESS ea_set = + { + GENERIC_READ | GENERIC_EXECUTE, + SET_ACCESS, + SUB_CONTAINERS_AND_OBJECTS_INHERIT, + { + NULL, + NO_MULTIPLE_TRUSTEE, + TRUSTEE_IS_SID, + TRUSTEE_IS_GROUP, + reinterpret_cast(pSid) + } + }; + + UpdateFolderDACLs(HomePath, &ea_set); + + LocalFree(pSid); + + return TRUE; +} diff --git a/Sandboxie/install/kmdutil/kmdutil.c b/Sandboxie/install/kmdutil/kmdutil.c index 55fd16cf..27321882 100644 --- a/Sandboxie/install/kmdutil/kmdutil.c +++ b/Sandboxie/install/kmdutil/kmdutil.c @@ -30,6 +30,8 @@ extern void Kmd_ScanDll(BOOLEAN silent); +extern BOOL Kmd_FixDacls(); + //--------------------------------------------------------------------------- // Defines @@ -43,7 +45,8 @@ typedef enum _COMMAND { CMD_STOP, CMD_SCANDLL, CMD_SCANDLL_SILENT, - CMD_MESSAGE + CMD_MESSAGE, + CMD_FIXDACLS } COMMAND; typedef enum _OPTIONS { @@ -224,6 +227,10 @@ BOOL Parse_Command_Line( *Command = CMD_MESSAGE; num_args_needed = 2; + } else if (_wcsicmp(args[1], L"fixdacls") == 0) { + *Command = CMD_FIXDACLS; + num_args_needed = 0; + } else { *Command = CMD_ERROR; MessageBox(NULL, L"Invalid command", L"KmdUtil", @@ -761,6 +768,16 @@ int __stdcall WinMain( &Options)) return EXIT_FAILURE; + if (Command == CMD_MESSAGE) { + ok = Kmd_Show_Message(Driver_Name, Driver_Path); + goto finish; + } + + if (Command == CMD_FIXDACLS) { + ok = Kmd_FixDacls(); + goto finish; + } + ScMgr = OpenSCManager( NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CREATE_SERVICE); @@ -803,9 +820,7 @@ int __stdcall WinMain( if (Command == CMD_STOP) ok = Kmd_Stop_Service(Driver_Name); - if (Command == CMD_MESSAGE) - ok = Kmd_Show_Message(Driver_Name, Driver_Path); - +finish: if (! ok) return EXIT_FAILURE; diff --git a/Sandboxie/install/kmdutil/kmdutil.vcxproj b/Sandboxie/install/kmdutil/kmdutil.vcxproj index e9259160..f73f4948 100644 --- a/Sandboxie/install/kmdutil/kmdutil.vcxproj +++ b/Sandboxie/install/kmdutil/kmdutil.vcxproj @@ -183,6 +183,20 @@ + + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + Sync + Sync + Sync + Sync + Sync + Sync + diff --git a/Sandboxie/msgs/Sbie-English-1033.txt b/Sandboxie/msgs/Sbie-English-1033.txt index 1bde3442..8913a22d 100644 --- a/Sandboxie/msgs/Sbie-English-1033.txt +++ b/Sandboxie/msgs/Sbie-English-1033.txt @@ -386,6 +386,14 @@ SBIE2114 File is too large to copy into sandbox, denying access - %2 SBIE2115 File is too large to copy into sandbox, opening in read only - %2 . +2180;pop;inf;01 +SBIE2180 LowLevel.dll error %2 +. + +2181;pop;inf;01 +SBIE2181 LowLevel.dll detour failed to load SbieDll.dll into target process. +. + # %2 = Mozilla Firefox 2191;pop;inf;01 SBIE2191 %2 should not be updated while running under Sandboxie.