From f2314e284735a451f6d52915280ecfd7fa3ecb8d Mon Sep 17 00:00:00 2001 From: DavidXanatos Date: Tue, 3 Nov 2020 17:41:33 +0100 Subject: [PATCH] --- CHANGELOG.md | 18 +- Sandboxie/Sandbox.sln | 22 +- Sandboxie/SboxHostDll/SboxHostDll.vcxproj | 3 - Sandboxie/apps/ldr/SbieLdr.vcxproj | 152 +++ Sandboxie/apps/ldr/global.h | 22 + Sandboxie/apps/ldr/main.c | 35 + Sandboxie/apps/ldr/resource1.rc | 55 + Sandboxie/common/my_version.h | 6 +- Sandboxie/core/dll/SboxDll.vcxproj | 17 + Sandboxie/core/dll/SboxDll.vcxproj.filters | 268 +++++ Sandboxie/core/dll/dllhook.c | 23 + Sandboxie/core/dll/hook.h | 143 +++ Sandboxie/core/{drv => dll}/hook_inst.c | 14 +- Sandboxie/core/{drv => dll}/hook_tramp.c | 31 +- Sandboxie/core/{svc => dll}/lowlevel.rc | 0 Sandboxie/core/dll/lowlevel_inject.c | 1136 ++++++++++++++++++++ Sandboxie/core/dll/sbieapi.c | 4 +- Sandboxie/core/dll/sbiedll.h | 4 + Sandboxie/core/drv/SboxDrv.vcxproj | 40 +- Sandboxie/core/drv/api.c | 2 +- Sandboxie/core/drv/api_defs.h | 2 +- Sandboxie/core/drv/driver.c | 34 +- Sandboxie/core/drv/hook.c | 4 + Sandboxie/core/drv/hook.h | 111 +- Sandboxie/core/low/inject.c | 20 +- Sandboxie/core/low/lowdata.h | 1 + Sandboxie/core/svc/DriverAssist.h | 36 +- Sandboxie/core/svc/DriverAssistInject.cpp | 964 +---------------- Sandboxie/core/svc/DriverAssistStart.cpp | 2 +- Sandboxie/core/svc/SboxSvc.vcxproj | 1 - SandboxiePlus/QSbieAPI/SbieAPI.cpp | 2 +- SandboxiePlus/SandMan/SandMan.h | 2 +- 32 files changed, 2023 insertions(+), 1151 deletions(-) create mode 100644 Sandboxie/apps/ldr/SbieLdr.vcxproj create mode 100644 Sandboxie/apps/ldr/global.h create mode 100644 Sandboxie/apps/ldr/main.c create mode 100644 Sandboxie/apps/ldr/resource1.rc create mode 100644 Sandboxie/core/dll/SboxDll.vcxproj.filters create mode 100644 Sandboxie/core/dll/hook.h rename Sandboxie/core/{drv => dll}/hook_inst.c (95%) rename Sandboxie/core/{drv => dll}/hook_tramp.c (95%) rename Sandboxie/core/{svc => dll}/lowlevel.rc (100%) create mode 100644 Sandboxie/core/dll/lowlevel_inject.c diff --git a/CHANGELOG.md b/CHANGELOG.md index ea1f692759..44fb68272c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,26 @@ This project adheres to [Semantic Versioning](http://semver.org/). -## [0.4.3 / 5.43.7] - 2020-11-03 +## [0.4.4 / 5.44.0] - 2020-11-03 ### Added -- added disable forced programs menu command to he sandman ui +- added SbieLdr (experimental) ### Changed +- moved code injection mechanism from SbieSvc to SbieDll +- moved function hooking mechanism from SbieDrv to SbieDll +- introduced a new driverless method to resolve wow64 ntdll base address + +### Fixed + +### removed +- removed support for windows vista x64 + + +## [0.4.3 / 5.43.7] - 2020-11-03 + +### Added +- added disable forced programs menu command to he sandman ui ### Fixed - fixed file rename bug introduced with an earlier driver verifier fix diff --git a/Sandboxie/Sandbox.sln b/Sandboxie/Sandbox.sln index 8e5914e961..fa2b7581d2 100644 --- a/Sandboxie/Sandbox.sln +++ b/Sandboxie/Sandbox.sln @@ -73,7 +73,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SbieControl", "apps\control {8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4} = {8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4} {41453A79-CA9B-ABCA-981C-5242AFC72DDF} = {41453A79-CA9B-ABCA-981C-5242AFC72DDF} {2D3DBCAE-883E-54A6-F8F6-11228D989033} = {2D3DBCAE-883E-54A6-F8F6-11228D989033} - {08A656D9-CDD0-4C9F-AB3F-D98F8E5B6EC6} = {08A656D9-CDD0-4C9F-AB3F-D98F8E5B6EC6} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kmdutil", "install\kmdutil\KmdUtil.vcxproj", "{0BF4988E-2325-4426-8CDC-BD221E4FB68C}" @@ -86,8 +85,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SbieIni", "apps\ini\SbieIni {8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4} = {8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SandboxieInstall", "install\release\SandboxieInstall.vcxproj", "{08A656D9-CDD0-4C9F-AB3F-D98F8E5B6EC6}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Parse", "msgs\Parse.vcxproj", "{7BA01954-12F1-4CEE-BA97-FAD3250D9776}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SboxHostDll", "SboxHostDll\SboxHostDll.vcxproj", "{3A42A9F3-E0C7-4633-9570-381802D6647D}" @@ -106,6 +103,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{E9D1318A-F EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "apps", "apps", "{0301861F-98D8-4767-BA7D-E146DE2E0C92}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SbieLdr", "apps\ldr\SbieLdr.vcxproj", "{352AA425-D224-4F23-AF1D-D54AFADDDB22}" + ProjectSection(ProjectDependencies) = postProject + {8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4} = {8E0EAA5B-6F5B-E0E2-338A-453EF2B548E4} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution SbieDebug|Win32 = SbieDebug|Win32 @@ -234,11 +236,6 @@ Global {B8D7002B-0468-44E7-93A7-94327A5D7C7A}.SbieRelease|Win32.Build.0 = SbieRelease|Win32 {B8D7002B-0468-44E7-93A7-94327A5D7C7A}.SbieRelease|x64.ActiveCfg = SbieRelease|x64 {B8D7002B-0468-44E7-93A7-94327A5D7C7A}.SbieRelease|x64.Build.0 = SbieRelease|x64 - {08A656D9-CDD0-4C9F-AB3F-D98F8E5B6EC6}.SbieDebug|Win32.ActiveCfg = SbieRelease|Win32 - {08A656D9-CDD0-4C9F-AB3F-D98F8E5B6EC6}.SbieDebug|Win32.Build.0 = SbieRelease|Win32 - {08A656D9-CDD0-4C9F-AB3F-D98F8E5B6EC6}.SbieDebug|x64.ActiveCfg = SbieRelease|Win32 - {08A656D9-CDD0-4C9F-AB3F-D98F8E5B6EC6}.SbieRelease|Win32.ActiveCfg = SbieRelease|Win32 - {08A656D9-CDD0-4C9F-AB3F-D98F8E5B6EC6}.SbieRelease|x64.ActiveCfg = SbieRelease|Win32 {7BA01954-12F1-4CEE-BA97-FAD3250D9776}.SbieDebug|Win32.ActiveCfg = SbieRelease|Win32 {7BA01954-12F1-4CEE-BA97-FAD3250D9776}.SbieDebug|Win32.Build.0 = SbieRelease|Win32 {7BA01954-12F1-4CEE-BA97-FAD3250D9776}.SbieDebug|x64.ActiveCfg = SbieRelease|Win32 @@ -254,6 +251,14 @@ Global {3A42A9F3-E0C7-4633-9570-381802D6647D}.SbieRelease|Win32.Build.0 = SbieRelease|Win32 {3A42A9F3-E0C7-4633-9570-381802D6647D}.SbieRelease|x64.ActiveCfg = SbieRelease|x64 {3A42A9F3-E0C7-4633-9570-381802D6647D}.SbieRelease|x64.Build.0 = SbieRelease|x64 + {352AA425-D224-4F23-AF1D-D54AFADDDB22}.SbieDebug|Win32.ActiveCfg = SbieDebug|Win32 + {352AA425-D224-4F23-AF1D-D54AFADDDB22}.SbieDebug|Win32.Build.0 = SbieDebug|Win32 + {352AA425-D224-4F23-AF1D-D54AFADDDB22}.SbieDebug|x64.ActiveCfg = SbieDebug|x64 + {352AA425-D224-4F23-AF1D-D54AFADDDB22}.SbieDebug|x64.Build.0 = SbieDebug|x64 + {352AA425-D224-4F23-AF1D-D54AFADDDB22}.SbieRelease|Win32.ActiveCfg = SbieRelease|Win32 + {352AA425-D224-4F23-AF1D-D54AFADDDB22}.SbieRelease|Win32.Build.0 = SbieRelease|Win32 + {352AA425-D224-4F23-AF1D-D54AFADDDB22}.SbieRelease|x64.ActiveCfg = SbieRelease|x64 + {352AA425-D224-4F23-AF1D-D54AFADDDB22}.SbieRelease|x64.Build.0 = SbieRelease|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -273,6 +278,7 @@ Global {0BF4988E-2325-4426-8CDC-BD221E4FB68C} = {0301861F-98D8-4767-BA7D-E146DE2E0C92} {B8D7002B-0468-44E7-93A7-94327A5D7C7A} = {0301861F-98D8-4767-BA7D-E146DE2E0C92} {3A42A9F3-E0C7-4633-9570-381802D6647D} = {E9D1318A-FAF0-4EF8-8561-FCB03862AC99} + {352AA425-D224-4F23-AF1D-D54AFADDDB22} = {0301861F-98D8-4767-BA7D-E146DE2E0C92} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8CC68B2E-A32E-409D-8D3F-F68AF524E29C} diff --git a/Sandboxie/SboxHostDll/SboxHostDll.vcxproj b/Sandboxie/SboxHostDll/SboxHostDll.vcxproj index 3b1611664c..fba6a4f4be 100644 --- a/Sandboxie/SboxHostDll/SboxHostDll.vcxproj +++ b/Sandboxie/SboxHostDll/SboxHostDll.vcxproj @@ -130,9 +130,6 @@ msvcprt.lib;%(IgnoreSpecificDefaultLibraries) - - - diff --git a/Sandboxie/apps/ldr/SbieLdr.vcxproj b/Sandboxie/apps/ldr/SbieLdr.vcxproj new file mode 100644 index 0000000000..19038ec92c --- /dev/null +++ b/Sandboxie/apps/ldr/SbieLdr.vcxproj @@ -0,0 +1,152 @@ + + + + + SbieDebug + Win32 + + + SbieDebug + x64 + + + SbieRelease + Win32 + + + SbieRelease + x64 + + + + + + + + + + + + + {352AA425-D224-4F23-AF1D-D54AFADDDB22} + Win32Proj + SbieLdr + 8.1 + + + + Application + true + Unicode + v140 + + + Application + true + Unicode + v140 + + + Application + false + true + Unicode + v140 + + + Application + false + true + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + SbieLdr + + + SbieLdr + + + SbieLdr + + + SbieLdr + + + + + + Disabled + + + + Console + SbieDll.lib;%(AdditionalDependencies) + + + + + + + + Disabled + + + + Console + SbieDll.lib;%(AdditionalDependencies) + + + + + + + + + + + + + Console + SbieDll.lib;%(AdditionalDependencies) + + + + + + + + + + + + + Console + SbieDll.lib;%(AdditionalDependencies) + + + + + + + \ No newline at end of file diff --git a/Sandboxie/apps/ldr/global.h b/Sandboxie/apps/ldr/global.h new file mode 100644 index 0000000000..8b9286d22d --- /dev/null +++ b/Sandboxie/apps/ldr/global.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, David Xanatos + * + * 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 +#include +#include "core/dll/sbiedll.h" + + diff --git a/Sandboxie/apps/ldr/main.c b/Sandboxie/apps/ldr/main.c new file mode 100644 index 0000000000..24ee533a75 --- /dev/null +++ b/Sandboxie/apps/ldr/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020, David Xanatos + * + * 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 "global.h" +#include "common/my_version.h" +#include "msgs/msgs.h" + +int __cdecl wmain(int argc, char **argv) +{ + int errlvl = SbieDll_InjectLow_InitHelper(); + + if (errlvl) { + //LogEvent(MSG_9234, 0x9241, errlvl); + return errlvl; + } + + SbieDll_InjectLow_InitSyscalls(FALSE); + + return 0; +} diff --git a/Sandboxie/apps/ldr/resource1.rc b/Sandboxie/apps/ldr/resource1.rc new file mode 100644 index 0000000000..e646b7b1eb --- /dev/null +++ b/Sandboxie/apps/ldr/resource1.rc @@ -0,0 +1,55 @@ +//--------------------------------------------------------------------------- +// SbieLdr scripting utility +//--------------------------------------------------------------------------- + + +#include +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#include "common/my_version.h" + + +//--------------------------------------------------------------------------- +// Version +//--------------------------------------------------------------------------- + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION MY_VERSION_BINARY + PRODUCTVERSION MY_VERSION_BINARY + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", MY_COMPANY_NAME_STRING "\0" + VALUE "FileDescription", MY_PRODUCT_NAME_STRING " configuration file utility\0" + VALUE "FileVersion", MY_VERSION_STRING "\0" + OPTIONAL_VALUE("InternalName", "SbieLdr\0") + VALUE "LegalCopyright", MY_COPYRIGHT_STRING "\0" + VALUE "LegalTrademarks", "\0" + OPTIONAL_VALUE("OriginalFilename", "SbieLdr.exe\0") + VALUE "PrivateBuild", "\0" + VALUE "ProductName", MY_PRODUCT_NAME_STRING "\0" + VALUE "ProductVersion", MY_VERSION_STRING "\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + diff --git a/Sandboxie/common/my_version.h b/Sandboxie/common/my_version.h index 54ab1f9985..757f6f9476 100644 --- a/Sandboxie/common/my_version.h +++ b/Sandboxie/common/my_version.h @@ -20,9 +20,9 @@ #ifndef _MY_VERSION_H #define _MY_VERSION_H -#define MY_VERSION_BINARY 5,43,7 -#define MY_VERSION_STRING "5.43.7" -#define MY_VERSION_COMPAT "5.43.5" +#define MY_VERSION_BINARY 5,44,0 +#define MY_VERSION_STRING "5.44.0" +#define MY_VERSION_COMPAT "5.44.0" // this reffers to the driver ABI compatybility // These #defines are used by either Resource Compiler, or by NSIC installer #define SBIE_INSTALLER_PATH "..\\Bin\\" diff --git a/Sandboxie/core/dll/SboxDll.vcxproj b/Sandboxie/core/dll/SboxDll.vcxproj index 789d7a6124..7d1ecf256a 100644 --- a/Sandboxie/core/dll/SboxDll.vcxproj +++ b/Sandboxie/core/dll/SboxDll.vcxproj @@ -104,6 +104,9 @@ false false + + BUILD_UTILITY_PASS2;%(PreprocessorDefinitions) + @@ -120,6 +123,9 @@ false false + + BUILD_UTILITY_PASS2;MY_WIN64_FLAG;%(PreprocessorDefinitions) + @@ -137,6 +143,9 @@ false false + + BUILD_UTILITY_PASS2;%(PreprocessorDefinitions) + @@ -152,6 +161,9 @@ false false + + BUILD_UTILITY_PASS2;MY_WIN64_FLAG;%(PreprocessorDefinitions) + @@ -227,6 +239,8 @@ + + @@ -258,6 +272,7 @@ true true + @@ -336,6 +351,7 @@ + @@ -346,6 +362,7 @@ + diff --git a/Sandboxie/core/dll/SboxDll.vcxproj.filters b/Sandboxie/core/dll/SboxDll.vcxproj.filters new file mode 100644 index 0000000000..2a42416f25 --- /dev/null +++ b/Sandboxie/core/dll/SboxDll.vcxproj.filters @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + scm + + + scm + + + scm + + + scm + + + scm + + + scm + + + hook + + + hook + + + hook + + + hook + + + hook + + + file + + + file + + + file + + + file + + + file + + + file + + + gui + + + gui + + + gui + + + gui + + + gui + + + gui + + + gui + + + gui + + + gui + + + gui + + + gui + + + gui + + + common + + + common + + + gui + + + + pst + + + pst + + + pst + + + + api + + + key + + + key + + + key + + + hook + + + ipc + + + ipc + + + com + + + com + + + api + + + hook + + + + + + + + hook + + + gui + + + gui + + + common + + + gui + + + gui + + + pst + + + pst + + + pst + + + api + + + api + + + com + + + + + + + + + hook + + + + + + + api + + + api + + + + + {6da9a76f-4d0f-47ee-b825-7c1e546a0d71} + + + {5f7e4efc-f1a0-402a-bdc9-b2b89d6b7dd2} + + + {881ad2c8-b8c4-4ca8-aecd-5c4796ad46b5} + + + {8ee84c6a-ed91-4765-b5c9-d8d65a4d605a} + + + {aebace4d-7063-460f-a875-1dacf59a4ed6} + + + {5d69d34a-4b02-40d2-a27e-ae16165b5933} + + + {d6a7a70a-5bfe-4598-b4e6-516442cd97e1} + + + {66c7aa3a-4c74-4ccc-8d57-ddb65c59cd58} + + + {fde0ce5f-2daf-4dfc-9512-731510cffabf} + + + {1903d308-e235-4da0-a117-0dfaa6eb24eb} + + + + + pst + + + \ No newline at end of file diff --git a/Sandboxie/core/dll/dllhook.c b/Sandboxie/core/dll/dllhook.c index cffb0c07d1..aa8e02b3f3 100644 --- a/Sandboxie/core/dll/dllhook.c +++ b/Sandboxie/core/dll/dllhook.c @@ -22,6 +22,7 @@ #define NOGDI #include "dll.h" +#include "hook.h" #include "common/pool.h" #include "common/pattern.h" @@ -68,6 +69,28 @@ extern CRITICAL_SECTION VT_CriticalSection; #endif _WIN64 extern ULONG Dll_Windows; +//--------------------------------------------------------------------------- +// SbieApi_HookTramp +//--------------------------------------------------------------------------- + + +_FX LONG SbieApi_HookTramp(void *Source, void *Trampoline) +{ + NTSTATUS status; +#ifdef _WIN64 + BOOLEAN is64 = TRUE; +#else + BOOLEAN is64 = FALSE; +#endif _WIN64 + + if (Hook_BuildTramp(Source, Trampoline, is64, TRUE)) + status = STATUS_SUCCESS; + else + status = STATUS_UNSUCCESSFUL; + + return status; +} + //--------------------------------------------------------------------------- // SbieDll_Hook diff --git a/Sandboxie/core/dll/hook.h b/Sandboxie/core/dll/hook.h new file mode 100644 index 0000000000..a6625b34af --- /dev/null +++ b/Sandboxie/core/dll/hook.h @@ -0,0 +1,143 @@ +/* + * Copyright 2004-2020 Sandboxie Holdings, LLC + * + * 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 . + */ + +//--------------------------------------------------------------------------- +// Hook Management +//--------------------------------------------------------------------------- + + +#ifndef _MY_HOOK_H +#define _MY_HOOK_H + + +//--------------------------------------------------------------------------- +// Structures and Types +//--------------------------------------------------------------------------- + + +#ifdef HOOK_WITH_PRIVATE_PARTS + + +enum HOOK_KIND { + + INST_UNKNOWN = 0, + INST_MOVE, + INST_CTLXFER, // jmp/jcc/call with 32-bit disp + INST_CTLXFER_REG, // jmp/call reg or [reg] + INST_CALL_MEM, // call [mem] + INST_JUMP_MEM, // jmp [mem] + INST_SYSCALL, + INST_RET +}; + + +typedef struct _HOOK_INST { + + ULONG len; + UCHAR kind; + UCHAR op1, op2; + ULONG64 parm; + LONG *rel32; // --> 32-bit relocation for control-xfer + UCHAR *modrm; + ULONG flags; + +} HOOK_INST; + + +#endif // HOOK_WITH_PRIVATE_PARTS + + +//--------------------------------------------------------------------------- +// HOOK_TRAMP +//--------------------------------------------------------------------------- + + +#pragma pack(push) +#pragma pack(1) + +typedef struct _HOOK_TRAMP { + + ULONG eyecatcher; // (0,4) signature + + ULONG size; // (4,4) tramp size (multiple of 16) + + void *target; // (8,4/8) branch target in source + + __declspec(align(16)) + UCHAR code[64]; // (16) source code + extra jmp + + ULONG count; // original length of relocated code + +} HOOK_TRAMP; + +#pragma pack(pop) + + +#define HOOK_TRAMP_CODE_TO_TRAMP_HEAD(x) \ + (HOOK_TRAMP *)((ULONG_PTR)x - FIELD_OFFSET(HOOK_TRAMP, code)) + + +//--------------------------------------------------------------------------- +// Functions +//--------------------------------------------------------------------------- + +// Hook_BuildTramp constructs a detour trampoline that will jump to +// SourceFunc + n, where n is the length, in bytes, of the first few +// instructions at SourceFunc that would be damaged by placing a jump +// instruction at the top of SourceFunc. The jump instruction is assumed +// to be 5 bytes long in 32-bit mode and 12 bytes long in 64-bit mode. +// The damaged instructions are copied to the detour trampoline. +// Returns the address to the start of the code in the detour trampoline. +// The function being redirected to, through the overwriting jump +// instruction, should jump to the returned value, to invoke the +// original code. The trampoline is built on the address specified +// in Trampoline. Kernel-mode code should pass a NULL address to +// use a system space trampoline. + +void *Hook_BuildTramp( + void *SourceFunc, void *Trampoline, BOOLEAN is64, BOOLEAN probe); + + +// Hook_BuildJump1 will write a 'jmp DestFunc' instruction at +// the address specified by WritableAddr. In case WritableAddr was +// generated using MmGetSystemAddressForMdlSafe, then ExecutableAddr +// specifies the corresponding "real" address which will be used to +// generate a 32-bit jump offset. (Note that 64-bit code does not +// use jump offsets and disregards ExecutableAddr.) + +void Hook_BuildJump( + void *WritableAddr, void *ExecutableAddr, void *JumpTarget); + + +#ifdef HOOK_WITH_PRIVATE_PARTS + + +// Analyze a single instruction at the specified address + +BOOLEAN Hook_Analyze( + void *address, + BOOLEAN probe_address, + BOOLEAN is64, + HOOK_INST *inst); + +#endif // HOOK_WITH_PRIVATE_PARTS + + +//--------------------------------------------------------------------------- + + +#endif // _MY_HOOK_H diff --git a/Sandboxie/core/drv/hook_inst.c b/Sandboxie/core/dll/hook_inst.c similarity index 95% rename from Sandboxie/core/drv/hook_inst.c rename to Sandboxie/core/dll/hook_inst.c index b294906a58..d2e0eb0a0b 100644 --- a/Sandboxie/core/drv/hook_inst.c +++ b/Sandboxie/core/dll/hook_inst.c @@ -20,8 +20,16 @@ //--------------------------------------------------------------------------- +#ifdef KERNEL_MODE +#define Sbie_swprintf swprintf +#else +#include "dll.h" +#include "msgs/msgs.h" +#define MSG_HOOK_ANALYZE MSG_1151 +#define Log_Msg1 SbieApi_Log #define HOOK_WITH_PRIVATE_PARTS #include "hook.h" +#endif //--------------------------------------------------------------------------- @@ -130,8 +138,10 @@ ALIGNED BOOLEAN Hook_Analyze( __try { +#ifdef KERNEL_MODE if (probe_address) ProbeForRead(address, 16, sizeof(UCHAR)); +#endif /*if (1) { UCHAR *z = (UCHAR *)address; @@ -147,7 +157,7 @@ ALIGNED BOOLEAN Hook_Analyze( addr = Hook_Analyze_Inst(addr, inst); if (! addr) { addr = address; - swprintf(text, L"%08p: %02X,%02X,%02X,%02X," + Sbie_swprintf(text, L"%08p: %02X,%02X,%02X,%02X," L"%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X", addr, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11]); @@ -158,7 +168,7 @@ ALIGNED BOOLEAN Hook_Analyze( } __except (EXCEPTION_EXECUTE_HANDLER) { addr = NULL; - swprintf(text, L"(fault at %p)", address); + Sbie_swprintf(text, L"(fault at %p)", address); Log_Msg1(MSG_HOOK_ANALYZE, text); } diff --git a/Sandboxie/core/drv/hook_tramp.c b/Sandboxie/core/dll/hook_tramp.c similarity index 95% rename from Sandboxie/core/drv/hook_tramp.c rename to Sandboxie/core/dll/hook_tramp.c index ac9813e62e..c6a2405c22 100644 --- a/Sandboxie/core/drv/hook_tramp.c +++ b/Sandboxie/core/dll/hook_tramp.c @@ -20,9 +20,14 @@ //--------------------------------------------------------------------------- + +#ifdef KERNEL_MODE + +#else +#include "dll.h" #define HOOK_WITH_PRIVATE_PARTS #include "hook.h" -#include "util.h" +#endif //--------------------------------------------------------------------------- // Structures and Types @@ -42,9 +47,6 @@ typedef struct _HOOK_TRAMP_PAGE { // Functions //--------------------------------------------------------------------------- - -static void *Hook_Tramp_Get(ULONG TrampSize); - static BOOLEAN Hook_Tramp_CountBytes( void *SysProc, ULONG *ByteCount, BOOLEAN is64, BOOLEAN probe); @@ -66,7 +68,7 @@ static BOOLEAN Hook_Tramp_Pages_Initialized = FALSE; // Hook_Tramp_Get //--------------------------------------------------------------------------- - +#ifdef KERNEL_MODE _FX void *Hook_Tramp_Get(ULONG TrampSize) { NTSTATUS status; @@ -172,7 +174,7 @@ _FX void *Hook_Tramp_Get(ULONG TrampSize) return tramp; } - +#endif //--------------------------------------------------------------------------- // Hook_Tramp_CountBytes @@ -452,13 +454,14 @@ _FX void *Hook_BuildTramp( return NULL; } - if (Trampoline) +#ifdef KERNEL_MODE + if (!Trampoline) + tramp = (HOOK_TRAMP *)Hook_Tramp_Get(sizeof(HOOK_TRAMP)); + else +#endif tramp = (HOOK_TRAMP *)Trampoline; - else { - tramp = (HOOK_TRAMP *)Hook_Tramp_Get(sizeof(HOOK_TRAMP)); - if (! tramp) - return NULL; - } + if (! tramp) + return NULL; if (SourceFunc) { if (! Hook_Tramp_Copy(tramp, SourceFunc, ByteCount, is64, probe)) @@ -479,6 +482,7 @@ _FX void Hook_BuildJump( { UCHAR *SourceAddr = (UCHAR *)WritableAddr; +#ifdef KERNEL_MODE // // ideally, WritableAddr points at a writable page received through // MmGetSystemAddressForMdlSafe for the page at ExecutableAddr. @@ -487,6 +491,7 @@ _FX void Hook_BuildJump( // DisableWriteProtect(); +#endif // // if we detect JMP DWORD/QWORD PTR [+00], then replace the jump target @@ -545,5 +550,7 @@ _FX void Hook_BuildJump( } +#ifdef KERNEL_MODE EnableWriteProtect(); +#endif } diff --git a/Sandboxie/core/svc/lowlevel.rc b/Sandboxie/core/dll/lowlevel.rc similarity index 100% rename from Sandboxie/core/svc/lowlevel.rc rename to Sandboxie/core/dll/lowlevel.rc diff --git a/Sandboxie/core/dll/lowlevel_inject.c b/Sandboxie/core/dll/lowlevel_inject.c new file mode 100644 index 0000000000..ba54121d92 --- /dev/null +++ b/Sandboxie/core/dll/lowlevel_inject.c @@ -0,0 +1,1136 @@ +/* + * Copyright 2004-2020 Sandboxie Holdings, LLC + * + * 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 . + */ + + //--------------------------------------------------------------------------- + // Sandboxie Low Level code injection mechanism moved here from SbieSvc + //--------------------------------------------------------------------------- + +#include "dll.h" + +#include +#include + +#include "common/my_version.h" +#include "core/low/lowdata.h" +#include "common/win32_ntddk.h" +#include "core/drv/api_defs.h" + + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Structures and Types +//--------------------------------------------------------------------------- + + +typedef struct _MY_TARGETS { + unsigned long long entry; + unsigned long long data; +} MY_TARGETS; + + +//--------------------------------------------------------------------------- +// Functions +//--------------------------------------------------------------------------- + +SBIEDLL_EXPORT HANDLE SbieDll_InjectLow_SendHandle(HANDLE hProcess); + +SBIEDLL_EXPORT void *SbieDll_InjectLow_CopyCode( + HANDLE hProcess, BOOLEAN iswow64, UCHAR *code, ULONG code_len); +SBIEDLL_EXPORT BOOLEAN SbieDll_InjectLow_BuildTramp( + BOOLEAN long_diff, UCHAR *code, ULONG_PTR addr); +SBIEDLL_EXPORT void *SbieDll_InjectLow_CopySyscalls(HANDLE hProcess); +SBIEDLL_EXPORT BOOLEAN SbieDll_InjectLow_CopyData( + HANDLE hProcess, void *remote_addr, void *local_data); +#ifdef _WIN64 +SBIEDLL_EXPORT BOOLEAN SbieDll_Has32BitJumpHorizon(void * target, void * detour); +SBIEDLL_EXPORT void * SbieDll_InjectLow_getPage(HANDLE hProcess, void *remote_addr); +#endif +SBIEDLL_EXPORT BOOLEAN SbieDll_InjectLow_WriteJump( + HANDLE hProcess, void *remote_addr, BOOLEAN long_diff, void *localdata); + +//--------------------------------------------------------------------------- +// Variables +//--------------------------------------------------------------------------- + + +void *m_sbielow_ptr = NULL; +//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; + +ULONG *m_syscall_data = NULL; + +ULONG_PTR m_LdrInitializeThunk = 0; + + +//--------------------------------------------------------------------------- +// InjectLow_InitHelper +//--------------------------------------------------------------------------- + + +_FX ULONG SbieDll_InjectLow_InitHelper() +{ + // + // 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; + IMAGE_DATA_DIRECTORY *data_dirs = 0; + ULONG_PTR imageBase = 0; + MY_TARGETS *targets = 0; + + ULONG errlvl = 0x11; + + HRSRC hrsrc = FindResource(Dll_Instance, L"LOWLEVEL", RT_RCDATA); + if (! hrsrc) + return errlvl; + + ULONG binsize = SizeofResource(Dll_Instance, hrsrc); + if (! binsize) + return errlvl; + + HGLOBAL hglob = LoadResource(Dll_Instance, hrsrc); + if (! hglob) + return errlvl; + + UCHAR *bindata = (UCHAR *)LockResource(hglob); + if (! bindata) + return errlvl; + + errlvl = 0x22; + dos_hdr = (IMAGE_DOS_HEADER *)bindata; + + 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 { + + return errlvl; + } + } + + if (imageBase) { + return errlvl; + } + + section = IMAGE_FIRST_SECTION(nt_hdrs); + if (nt_hdrs->FileHeader.NumberOfSections < 2) return errlvl; + if (strncmp((char *)section[0].Name, SBIELOW_INJECTION_SECTION, strlen(SBIELOW_INJECTION_SECTION)) || + strncmp((char *)section[1].Name, SBIELOW_SYMBOL_SECTION, strlen(SBIELOW_SYMBOL_SECTION))) { + return errlvl; + } + + + targets = (MY_TARGETS *)& bindata[section[1].PointerToRawData]; + m_sbielow_start_offset = (ULONG)targets->entry - section[0].VirtualAddress; + m_sbielow_data_offset = (ULONG)targets->data - 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); + + if ((!m_sbielow_start_offset) || (!m_sbielow_data_offset)) + return errlvl; + + // + // record information about ntdll and the virtual memory system + // + + errlvl = 0x33; + + m_LdrInitializeThunk = (ULONG_PTR) GetProcAddress(Dll_Ntdll, "LdrInitializeThunk"); + + if (! m_LdrInitializeThunk) + return errlvl; + +#ifdef _WIN64 + if (Dll_Windows >= 10) { + unsigned char * code; + code = (unsigned char *)m_LdrInitializeThunk; + if (*(ULONG *)&code[0] == 0x24048b48 && code[0xa] == 0x48) { + m_LdrInitializeThunk += 0xa; + } + } +#endif + + return 0; +} + + +//--------------------------------------------------------------------------- +// InjectLow_InitSyscalls +//--------------------------------------------------------------------------- + + +_FX ULONG SbieDll_InjectLow_InitSyscalls(BOOLEAN drv_init) +{ + const WCHAR *_SbieDll = L"\\" SBIEDLL L".dll"; + WCHAR sbie_home[512]; + ULONG status; + ULONG len; + SBIELOW_EXTRA_DATA *extra; + WCHAR *ptr; + ULONG *syscall_data; + + // + // Get the SbieDll Location + // + + if (drv_init) + { + status = SbieApi_GetHomePath(NULL, 0, sbie_home, 512); + if (status != 0) + return status; + } + else + { + GetModuleFileName(Dll_Instance, sbie_home, 512); + ptr = wcsrchr(sbie_home, L'\\'); + if (ptr) + *ptr = L'\0'; + } + +#define ULONG_DIFF(b,a) ((ULONG)((ULONG_PTR)(b) - (ULONG_PTR)(a))) + + // + // get the list of syscall from the driver + // + + if (!m_syscall_data) { + syscall_data = (ULONG *)HeapAlloc(GetProcessHeap(), 0, 8192); + if (!syscall_data) + return STATUS_INSUFFICIENT_RESOURCES; + *syscall_data = 0; + } + else + syscall_data = m_syscall_data; + + if (drv_init) + { + // + // Get a full sys call list from the driver + // + + status = SbieApi_CallOne(API_QUERY_SYSCALLS, (ULONG_PTR)syscall_data); + if (status != 0) + return status; + + len = *syscall_data; + if ((!len) || (len & 3) || (len > 4096)) + return STATUS_INVALID_IMAGE_FORMAT; + } + else + { + // + // Create a minimalistic driverless data + // + + *syscall_data = 4 + 4 + 232; // size 4, offset 4, work area sizeof(INJECT_DATA) + + const char* NtdllExports[] = { "NtDelayExecution", "NtDeviceIoControlFile", "NtFlushInstructionCache", "NtProtectVirtualMemory" }; + for (ULONG i = 0; i < 4; ++i) { + void* func_ptr = GetProcAddress(Dll_Ntdll, NtdllExports[i]); + memcpy((void*)((ULONG_PTR)syscall_data + (4 + 4) + (32 * i)), func_ptr, 32); + } + + len = *syscall_data; + } + + // + // the second ULONG in syscall_data points to extra data appended + // by us here on top of what the driver returned + // + + extra = (SBIELOW_EXTRA_DATA *)((ULONG_PTR)syscall_data + len); + + syscall_data[1] = len; + + // + // write an ASCII string for LdrLoadDll (see core/low/inject.c) + // + + ptr = (WCHAR *)((ULONG_PTR)extra + sizeof(SBIELOW_EXTRA_DATA)); + + strcpy((char *)ptr, "LdrLoadDll"); + + extra->LdrLoadDll_offset = ULONG_DIFF(ptr, extra); + ptr += 16 / sizeof(WCHAR); + + // + // write an ASCII string for LdrGetProcedureAddress + // + + strcpy((char *)ptr, "LdrGetProcedureAddress"); + + extra->LdrGetProcAddr_offset = ULONG_DIFF(ptr, extra); + ptr += 28 / sizeof(WCHAR); + + // + // write an ASCII string for NtRaiseHardError + // + + strcpy((char *)ptr, "NtRaiseHardError"); + + extra->NtRaiseHardError_offset = ULONG_DIFF(ptr, extra); + ptr += 20 / sizeof(WCHAR); + + // + // write an ASCII string for RtlFindActivationContextSectionString + // + + strcpy((char *)ptr, "RtlFindActivationContextSectionString"); + + extra->RtlFindActCtx_offset = ULONG_DIFF(ptr, extra); + ptr += 44 / sizeof(WCHAR); + + // + // ntdll loads kernel32 without a path, we will do the same + // in our hook for RtlFindActivationContextSectionString, + // see entry.asm + // + + wcscpy(ptr, L"kernel32.dll"); + + len = wcslen(ptr); + extra->KernelDll_offset = ULONG_DIFF(ptr, extra);; + extra->KernelDll_length = len * sizeof(WCHAR); + ptr += len + 1; + + // + // append paths for native and wow64 SbieDll to the syscall buffer + // + + wcscpy(ptr, sbie_home); + wcscat(ptr, _SbieDll); + + len = wcslen(ptr); + extra->NativeSbieDll_offset = ULONG_DIFF(ptr, extra);; + extra->NativeSbieDll_length = len * sizeof(WCHAR); + ptr += len + 1; + +#ifdef _WIN64 + + wcscpy(ptr, sbie_home); + wcscat(ptr, L"\\32"); + wcscat(ptr, _SbieDll); + + len = wcslen(ptr); + extra->Wow64SbieDll_offset = ULONG_DIFF(ptr, extra); + extra->Wow64SbieDll_length = len * sizeof(WCHAR); + ptr += len + 1; + +#endif _WIN64 + + // + // adjust size of syscall buffer to include path strings + // + + *syscall_data = ULONG_DIFF(ptr, syscall_data); + +#undef ULONG_DIFF + + m_syscall_data = syscall_data; + + return STATUS_SUCCESS; +} + + +//--------------------------------------------------------------------------- +// FindWOW64_Ntdll +//--------------------------------------------------------------------------- + + +ULONG64 SbieDll_FindWOW64_Ntdll(_In_ HANDLE ProcessHandle) +{ + /*typedef NTSTATUS(*P_NtQueryVirtualMemory)( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN MEMORY_INFORMATION_CLASS MemoryInformationClass, + OUT PVOID MemoryInformation, + IN SIZE_T MemoryInformationLength, + OUT PSIZE_T ReturnLength OPTIONAL); + + P_NtQueryVirtualMemory __sys_NtQueryVirtualMemory = (P_NtQueryVirtualMemory)GetProcAddress(_Ntdll, "NtQueryVirtualMemory");*/ + + static const WCHAR *_Ntdll32 = L"\\syswow64\\ntdll.dll"; // 19 chars + + char buffer[512]; + + for (PVOID baseAddress = NULL;;) + { + MEMORY_BASIC_INFORMATION basicInfo; + if (!NT_SUCCESS(NtQueryVirtualMemory( + ProcessHandle, + baseAddress, + MemoryBasicInformation, + &basicInfo, + sizeof(MEMORY_BASIC_INFORMATION), + NULL + ))) + { + break; + } + + baseAddress = (PVOID)((ULONG_PTR)(baseAddress)+(ULONG_PTR)(basicInfo.RegionSize)); + + if (NT_SUCCESS(NtQueryVirtualMemory( + ProcessHandle, + basicInfo.AllocationBase, + MemoryMappedFilenameInformation, + buffer, + sizeof(buffer), + NULL + ))) + { + UNICODE_STRING *FullImageName = (UNICODE_STRING*)buffer; + if (FullImageName->Length > 19 * sizeof(WCHAR)) { + + WCHAR *path = FullImageName->Buffer + + FullImageName->Length / sizeof(WCHAR) + - 19; + if (_wcsicmp(path, _Ntdll32) == 0) { + + return (ULONG64)basicInfo.AllocationBase; + } + } + } + } + + return 0; +} + + +//--------------------------------------------------------------------------- +// InjectLow +//--------------------------------------------------------------------------- + + +_FX ULONG SbieDll_InjectLow(HANDLE hProcess, BOOLEAN is_wow64, BOOLEAN bHostInject, BOOLEAN dup_drv_handle) +{ + //SVC_PROCESS_MSG *msg = (SVC_PROCESS_MSG *)_msg; + ULONG errlvl = 0; + + // + // verify all aspects of initialization were successful + // + if ((!m_sbielow_ptr) || (!m_syscall_data)) { + + SetLastError(ERROR_NOT_READY); + errlvl = 0xFF; + goto finish; + } + + // + // prepare the lowdata paramters area to copy into target process + // + + SBIELOW_DATA lowdata; + memzero(&lowdata, sizeof(lowdata)); + +#ifdef _WIN64 + if (is_wow64)//(msg->is_wow64) + lowdata.ntdll_wow64_base = SbieDll_FindWOW64_Ntdll(hProcess); +#endif + lowdata.ntdll_base = (ULONG64)(ULONG_PTR)Dll_Ntdll; + + lowdata.is_wow64 = is_wow64; //msg->is_wow64; + lowdata.bHostInject = bHostInject; //msg->bHostInject; + + lowdata.RealNtDeviceIoControlFile = (ULONG64)GetProcAddress((HMODULE)lowdata.ntdll_base, "NtDeviceIoControlFile"); + // + // on 64-bit Windows 8, there might be a difference of more than + // 2GB bytes between ntdll and the injected SbieLow, which requires + // use of longer jump sequences than the 5-byte 0xE9 relative jump + // + if (Dll_Windows >= 10) { + lowdata.is_win10 = TRUE; + } + + void *remote_addr = SbieDll_InjectLow_CopyCode(hProcess, lowdata.is_wow64, lowdata.LdrInitializeThunk_tramp, sizeof(lowdata.LdrInitializeThunk_tramp)); + if (!remote_addr) { + errlvl = 0x33; + goto finish; + } + // if (lowdata.is_wow64 && (m_addr_high != m_addr_high_32)) +#ifdef _WIN64 + lowdata.long_diff = TRUE; + if (SbieDll_Has32BitJumpHorizon((void *)m_LdrInitializeThunk, remote_addr)) { + lowdata.long_diff = FALSE; + } +#else + lowdata.long_diff = FALSE; +#endif + + if (dup_drv_handle) + { + // + // duplicate the SbieDrv API file device handle into target process + // + + lowdata.api_device_handle = (ULONG64)(ULONG_PTR) + SbieDll_InjectLow_SendHandle(hProcess); + if (!lowdata.api_device_handle) { + + errlvl = 0x22; + goto finish; + } + + lowdata.api_sbiedrv_ctlcode = API_SBIEDRV_CTLCODE; + + lowdata.api_invoke_syscall = API_INVOKE_SYSCALL; + } + + // + // the driver sent us a copy of some functions from ntdll in the + // syscall_data buffer, copy that code to SbieLow through the + // lowdata area (see also core/drv/syscall.c and core/low/lowdata.h) + // + + memcpy(lowdata.NtDelayExecution_code, &m_syscall_data[2], (32 * 4)); + + // + // allocate space for and write the lowlevel (SbieLow) code + // and copy code at LdrInitializeThunk from target process + // + +#ifdef _WIN64 + lowdata.Sbie64bitJumpTable = (SBIELOW_J_TABLE *)((ULONG_PTR)remote_addr + m_sbielow_len + 0x400); //(0x400 - (m_sbielow_len & 0x3ff))+ m_sbielow_len; +#endif + + // + // remove hard coded data block offset + ULONG_PTR tramp_remote_addr = // calculate address in remote process + (ULONG_PTR)remote_addr + + m_sbielow_data_offset // offset of args area + + FIELD_OFFSET(SBIELOW_DATA, LdrInitializeThunk_tramp); + + if (!SbieDll_InjectLow_BuildTramp(lowdata.long_diff, + lowdata.LdrInitializeThunk_tramp, tramp_remote_addr)) { + + //UCHAR *code = lowdata.LdrInitializeThunk_tramp; + //SbieApi_LogEx(msg->session_id, 2335, + // L"%S [%02X %02X %02X %02X %02X %02X" + // L" %02X %02X %02X %02X %02X %02X]", + // msg->process_name, + // code[0], code[1], code[2], code[3], code[4], code[5], + // code[6], code[7], code[8], code[9], code[10], code[11]); + + SetLastError(ERROR_UNKNOWN_PRODUCT); + + errlvl = 0x44; + goto finish; + } + + // + // copy the syscall data buffer (m_syscall_data) to target process + // + + void *remote_syscall_data = SbieDll_InjectLow_CopySyscalls(hProcess); + if (!remote_syscall_data) { + + errlvl = 0x55; + goto finish; + } + + lowdata.syscall_data = (ULONG64)(ULONG_PTR)remote_syscall_data; + + // + // write lowdata parameter area, including the converted trampoline + // code, into target process, and make it execute-read + // + if (!SbieDll_InjectLow_CopyData(hProcess, remote_addr, &lowdata)) { + + errlvl = 0x66; + goto finish; + } + + // + // overwrite the top of LdrInitializeThunk to jump to injected code + // note that we have to skip the 8-byte signature (.HEAD.00) + // + // Removed hard coded dependency on (.HEAD.00). No longer need to add 8 to + // the remote_addr + if (!SbieDll_InjectLow_WriteJump(hProcess, (UCHAR *)remote_addr + m_sbielow_start_offset, lowdata.long_diff, &lowdata)) { + errlvl = 0x77; + goto finish; + } + + // + // finish + // + +finish: + + return errlvl; +} + + +//--------------------------------------------------------------------------- +// InjectLow_SendHandle +//--------------------------------------------------------------------------- + + +_FX HANDLE SbieDll_InjectLow_SendHandle(HANDLE hProcess) +{ + NTSTATUS status; + HANDLE HandleLocal, HandleRemote; + UNICODE_STRING uni; + OBJECT_ATTRIBUTES objattrs; + IO_STATUS_BLOCK MyIoStatusBlock; + + // + // open the Sandboxie driver API file handle + // + + RtlInitUnicodeString(&uni, API_DEVICE_NAME); + InitializeObjectAttributes( + &objattrs, &uni, OBJ_CASE_INSENSITIVE, NULL, NULL); + + status = NtOpenFile( + &HandleLocal, FILE_GENERIC_READ, &objattrs, &MyIoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0); + + if (NT_SUCCESS(status)) { + + // + // duplicate opened handle into new process + // + + BOOL ok = DuplicateHandle(NtCurrentProcess(), HandleLocal, + hProcess, &HandleRemote, 0, FALSE, + DUPLICATE_SAME_ACCESS); + + CloseHandle(HandleLocal); + + if (ok) { + + return HandleRemote; + } + } + + return NULL; +} + + +//--------------------------------------------------------------------------- +// InjectLow_CopyCode +//--------------------------------------------------------------------------- + + +_FX void *SbieDll_InjectLow_CopyCode(HANDLE hProcess, BOOLEAN iswow64, UCHAR *code, ULONG code_len) +{ + SIZE_T region_size; + SIZE_T lowLevel_size; + void *remote_addr = NULL; +#ifdef _WIN64 + lowLevel_size = m_sbielow_len + sizeof(SBIELOW_J_TABLE) + 0x400; +#else + lowLevel_size = m_sbielow_len; +#endif + region_size = lowLevel_size; + + for (int i = 8; !remote_addr && i > 2; i--) { + NTSTATUS status = NtAllocateVirtualMemory(hProcess, &remote_addr, i, ®ion_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(status)) { + remote_addr = NULL; + region_size = lowLevel_size; + } + } + if (remote_addr) { + + // + // copy SbieLow into the allocated region in the new process + // + + SIZE_T len1 = m_sbielow_len; + SIZE_T len2 = 0; + BOOL vm_ok = WriteProcessMemory( + hProcess, remote_addr, m_sbielow_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, (void *)m_LdrInitializeThunk, code, + len1, &len2); + + if (vm_ok && len1 == len2) { + + return remote_addr; + } + } + } + + return NULL; +} + + +//--------------------------------------------------------------------------- +// InjectLow_BuildTramp +//--------------------------------------------------------------------------- + + +_FX BOOLEAN SbieDll_InjectLow_BuildTramp( + BOOLEAN long_diff, UCHAR *code, ULONG_PTR addr) +{ + +#define IS_1BYTE(a) ( code[offset + 0] == (a)) +#define IS_2BYTE(a,b) (IS_1BYTE(a) && code[offset + 1] == (b)) +#define IS_3BYTE(a,b,c) (IS_2BYTE(a,b) && code[offset + 2] == (c)) + + // + // skip past several bytes in the code copied from the top of the + // LdrInitializeThunk fuction, where we will inject a jmp sequence. + // + // a simple E9 relative JMP five byte instruction in most cases, + // a slightly longer seven byte version in case there is a long + // distance between ntdll and SbieLow, i.e. on 64-bit Windows 8 + // + + ULONG code_len = (long_diff ? 7 : 5); + + ULONG offset = 0; + while (offset < code_len) { + + ULONG inst_len = 0; + + if (0) + ; + + // push ebp + else if (IS_1BYTE(0x55)) + inst_len = 1; + + // mov ebp, esp + else if (IS_2BYTE(0x8B, 0xEC)) + inst_len = 2; + + // mov edi, edi + else if (IS_2BYTE(0x8B, 0xFF)) + inst_len = 2; + + // push ebx + else if (IS_2BYTE(0xFF, 0xF3)) + inst_len = 2; + + // push rbx (Windows 8.1) + else if (IS_2BYTE(0x40, 0x53)) + inst_len = 2; + + // mov dword ptr [esp+imm8],eax + else if (IS_3BYTE(0x89, 0x44, 0x24)) + inst_len = 4; + + // lea eax, esp+imm8 + else if (IS_3BYTE(0x8D, 0x44, 0x24)) + inst_len = 4; + + // sub rsp, imm8 + else if (IS_3BYTE(0x48, 0x83, 0xEC)) + inst_len = 4; + + // mov rbx, rcx + else if (IS_3BYTE(0x48, 0x8B, 0xD9)) + inst_len = 3; + + /* + else if (IS_3BYTE(0x48, 0x8B, 0x04)) + inst_len = 4; + */ + // + // abort if we don't recognize the instruction + // + + if (!inst_len) { + + return FALSE; + } + + offset += inst_len; + } + +#undef IS_3BYTE +#undef IS_2BYTE +#undef IS_1BYTE + + // + // append a jump instruction at the bottom of our trampoline for + // LdrInitializeThunk, which jumps back to the real LdrInitializeThunk + // + // note that on Windows 8 the difference between the address of + // LdrInitializeThunk in the 64-bit ntdll and where SbieLow was copied + // may be greater than 32-bit, so we use JMP QWORD rather than the + // 5-byte 0xE9 relative JMP + // +#ifdef _WIN64 + if (!long_diff) { + + if (Dll_Windows >= 10) { + code[offset] = 0x48; + code[offset + 1] = 0xE9; + *(ULONG *)&code[offset + 2] = (ULONG) + (m_LdrInitializeThunk + offset - (addr + offset + 6)); + + } + else { + code[offset] = 0xe9; + *(ULONG *)&code[offset + 1] = (ULONG) + (m_LdrInitializeThunk + offset - (addr + offset + 5)); + } + } + else { + + *(USHORT *)&code[offset] = 0x25FF; // jmp qword ptr + *(ULONG *)&code[offset + 2] = 0; + *(ULONG64 *)&code[offset + 6] = m_LdrInitializeThunk + offset; + } +#else + code[offset] = 0xE9; + + *(ULONG *)&code[offset + 1] = (ULONG) + (m_LdrInitializeThunk + offset - (addr + offset + 5)); +#endif + return TRUE; +} + + +//--------------------------------------------------------------------------- +// InjectLow_CopySyscalls +//--------------------------------------------------------------------------- + + +_FX void *SbieDll_InjectLow_CopySyscalls(HANDLE hProcess) +{ + // + // allocate virtual memory somewhere in the process. to force an + // address in the low 24-bits of the address space, we have to use + // NtAllocateVirtalMemory and specify ZeroBits = 8 (32 - 8 = 24) + // + + void *remote_addr = NULL; + SIZE_T region_size = *m_syscall_data; + int i; + NTSTATUS status; + + for (i = 8; !remote_addr && i > 2; i--) { + status = NtAllocateVirtualMemory(hProcess, &remote_addr, i, ®ion_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(status)) { + remote_addr = NULL; + region_size = *m_syscall_data; + } + } + + if (!NT_SUCCESS(status)) { + remote_addr = NULL; + SetLastError(RtlNtStatusToDosError(status)); + } + if (remote_addr) { + + // + // copy the syscall data buffer into the new process + // + + SIZE_T len1 = *m_syscall_data; + SIZE_T len2 = 0; + BOOL vm_ok = WriteProcessMemory( + hProcess, remote_addr, m_syscall_data, len1, &len2); + if (vm_ok && len1 == len2) { + + return remote_addr; + } + } + + return NULL; +} + + +//--------------------------------------------------------------------------- +// InjectLow_CopyData +//--------------------------------------------------------------------------- + + +_FX BOOLEAN SbieDll_InjectLow_CopyData( + HANDLE hProcess, void *remote_addr, void *local_data) +{ + // + // copy SBIELOW_DATA data into the area reserved within SbieLow + // (i.e. at offset SBIELOW_DATA_OFFSET) in the new process + // + + void *data_addr = (void *)((ULONG_PTR)remote_addr + m_sbielow_data_offset); + SIZE_T len1 = sizeof(SBIELOW_DATA); + SIZE_T len2 = 0; + BOOL vm_ok = WriteProcessMemory( + hProcess, data_addr, local_data, len1, &len2); + if (vm_ok && len1 == len2) { + + ULONG protect; + vm_ok = VirtualProtectEx(hProcess, remote_addr, m_sbielow_len, + PAGE_EXECUTE_READ, &protect); + if (vm_ok) { + return TRUE; + } + } + + return FALSE; +} + +#ifdef _WIN64 + +_FX BOOLEAN SbieDll_Has32BitJumpHorizon(void * target, void * detour) +{ + ULONG_PTR diff; + long long delta; + diff = (ULONG_PTR)((ULONG_PTR)target - (ULONG_PTR)detour); + delta = diff; + delta < 0 ? delta *= -1 : delta; + //is DetourFunc in 32bit jump range + if (delta < 0x80000000) { + return TRUE; + } + return FALSE; +} + +_FX void * SbieDll_InjectLow_getPage(HANDLE hProcess, void *remote_addr) +{ + SIZE_T mySize; + ULONG_PTR tempAddr; + void * myTable = 0; + UCHAR *func; + ULONG myProtect; + short myBuffer[1024]; + SIZE_T readSize; + BOOL myVM; + HANDLE myKernel32; + HANDLE myNtDll; + //HANDLE myTestDll; + func = (UCHAR *)((ULONG_PTR)m_LdrInitializeThunk); + myKernel32 = GetModuleHandleA("kernel32.dll"); + myNtDll = GetModuleHandleA("ntdll.dll"); + // myTestDll = 0; + + /* + if(myTestDll) { + //for testing remove this code! + sprintf(buffer,"Dll Collision Test: address %p\n",myTestDll); + OutputDebugStringA(buffer); + myTable = VirtualAllocEx(hProcess,myTestDll,0x100, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); + } + else { + */ + tempAddr = ((ULONG_PTR)myNtDll < (ULONG_PTR)myKernel32 ? (ULONG_PTR)myNtDll : (ULONG_PTR)myKernel32) - 0x10000; + myTable = VirtualAllocEx(hProcess, (void *)tempAddr, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + // } + /* + else { + //use hack if all else fails + //OutputDebugStringA("Unable to allocate page!\n"); + max_attempts = 0; + } + */ + + if (myTable) { + mySize = 0; + if (SbieDll_Has32BitJumpHorizon(myTable, func)) { + WriteProcessMemory(hProcess, myTable, &remote_addr, 8, &mySize); + /* + sprintf(buffer,"myPage = %p, kernel32 = %p, ntdll = %p\n",myTable,myKernel32,myNtDll); + OutputDebugStringA(buffer); + */ + if (mySize == 8) { + return myTable; + } + } + } + /* + sprintf(buffer,"Failed to find table for target address %p, func = %p\n",myTable,func); + OutputDebugStringA(buffer); + */ + + readSize = 1; + tempAddr = (ULONG_PTR)func - 8; + ReadProcessMemory(hProcess, (void *)((ULONG_PTR)tempAddr), &myBuffer, 8, &readSize); + + // if hot patch area + if (*((ULONG_PTR *)&myBuffer) == 0x9090909090909090 || *((ULONG_PTR *)&myBuffer) == 0xcccccccccccccccc) { + //OutputDebugStringA("Using hotpatch area\n"); + myTable = (void *)tempAddr; + } + else { //not hot patch area: This is a hack + //patch area in .rdata section of ntdll + ReadProcessMemory(hProcess, (void *)((ULONG_PTR)tempAddr + 0x100000), myBuffer, sizeof(myBuffer), &readSize); + if (readSize != sizeof(myBuffer)) { + //OutputDebugStringA("Error reading Memory\n"); + return NULL; + } + for (int i = 0; i < sizeof(myBuffer) && !myTable; i++) { + if (*((ULONG_PTR*)&myBuffer[i]) == 0x9090909090909090 || + *((ULONG_PTR*)&myBuffer[i]) == 0xcccccccccccccccc) { + myTable = (void *)((ULONG_PTR)tempAddr + i); + /* + sprintf(buffer,"HACK: table found at %p, index %x\n",myTable, i); + OutputDebugStringA(buffer); + */ + } + } + if (!myTable) { + //OutputDebugStringA("Table not found\n"); + return NULL; + } + + } //end else not hotpatch area + + myVM = VirtualProtectEx(hProcess, myTable, sizeof(void *), PAGE_READWRITE, &myProtect); + if (myVM) { + SIZE_T len2 = 0; + myVM = WriteProcessMemory(hProcess, myTable, &remote_addr, 8, &len2); + if (myVM && 8 == len2) { + myVM = VirtualProtectEx(hProcess, myTable, 8, myProtect, &myProtect); + if (myVM) { + return myTable; + } + } + } + + return NULL; +} +#endif //#ifdef _WIN64 + +//--------------------------------------------------------------------------- +// InjectLow_WriteJump +//--------------------------------------------------------------------------- +_FX BOOLEAN SbieDll_InjectLow_WriteJump(HANDLE hProcess, void *remote_addr, BOOLEAN long_diff, void *localdata) +{ + // + // prepare a short prolog code that jumps to the injected SbieLow + // + UCHAR jump_code[16]; + void * detour = (void *)remote_addr; + UCHAR *func = (UCHAR *)((ULONG_PTR)m_LdrInitializeThunk);; + SIZE_T len1; + BOOL myVM; + ULONG myProtect; + +#ifdef _WIN64 + if (!long_diff) { + if (Dll_Windows >= 10) { + len1 = 6; + jump_code[0] = 0x48; //jump to entry code in entry.asm + jump_code[1] = 0xE9; //jump to entry code in entry.asm + *(ULONG *)(jump_code + 2) = (ULONG)((ULONG_PTR)detour - (m_LdrInitializeThunk + 6)); + //remote_addr = (void *)m_LdrInitializeThunk; + } + else { + len1 = 5; + jump_code[0] = 0xe9; //jump to entry code in entry.asm + *(ULONG *)(jump_code + 1) = (ULONG)((ULONG_PTR)detour - (m_LdrInitializeThunk + 5)); + } + } + + else { + void * myTable = 0; + if (!((ULONG_PTR)remote_addr & 0xffffffff00000000)) { + len1 = 7; + jump_code[0] = 0xB8; + *(ULONG *)(jump_code + 1) = (ULONG)(ULONG_PTR)remote_addr; + *(USHORT *)(jump_code + 5) = 0xE0FF; // jmp rax + } + else { + ULONG_PTR target; + ULONG_PTR diff; + + len1 = 6; + target = (ULONG_PTR)&func[6]; + myTable = SbieDll_InjectLow_getPage(hProcess, remote_addr); + if (!myTable) { + //OutputDebugStringA("Error: Table not set!\n"); + return FALSE; + } + + diff = (ULONG_PTR) &((ULONG_PTR *)myTable)[0]; + diff = diff - target; + + *(USHORT *)&jump_code[0] = 0x25ff; + *(ULONG *)&jump_code[2] = (ULONG)diff; + } + } +#else + len1 = 5; + jump_code[0] = 0xE9; //jump to entry code in entry.asm + *(ULONG *)(jump_code + 1) = (ULONG)((ULONG_PTR)detour - (m_LdrInitializeThunk + 5)); + //remote_addr = (void *)m_LdrInitializeThunk; +#endif + // + // modify the bytes at LdrInitializeThunk with the prolog code + // + + myVM = VirtualProtectEx(hProcess, func, len1, PAGE_READWRITE, &myProtect); + if (myVM) { + SIZE_T len2 = 0; + myVM = WriteProcessMemory(hProcess, func, jump_code, len1, &len2); + /* + sprintf(buffer,"WriteJump: len2 = %d\n",len2); + OutputDebugStringA(buffer); + */ + if (myVM && len1 == len2) { + myVM = VirtualProtectEx(hProcess, func, len1, myProtect, &myProtect); + if (myVM) { + return TRUE; + } + } + } + return FALSE; +} diff --git a/Sandboxie/core/dll/sbieapi.c b/Sandboxie/core/dll/sbieapi.c index a740289d93..8e76f61d9d 100644 --- a/Sandboxie/core/dll/sbieapi.c +++ b/Sandboxie/core/dll/sbieapi.c @@ -850,7 +850,7 @@ _FX LONG SbieApi_DisableForceProcess( //--------------------------------------------------------------------------- -_FX LONG SbieApi_HookTramp(void *Source, void *Trampoline) +/*_FX LONG SbieApi_HookTramp(void *Source, void *Trampoline) { NTSTATUS status; __declspec(align(8)) ULONG64 parms[API_NUM_ARGS]; @@ -861,7 +861,7 @@ _FX LONG SbieApi_HookTramp(void *Source, void *Trampoline) status = SbieApi_Ioctl(parms); return status; -} +}*/ //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/dll/sbiedll.h b/Sandboxie/core/dll/sbiedll.h index 9468a93d43..ef359f93be 100644 --- a/Sandboxie/core/dll/sbiedll.h +++ b/Sandboxie/core/dll/sbiedll.h @@ -192,6 +192,10 @@ SBIEDLL_EXPORT BOOLEAN SbieDll_RegisterDllCallback(void *Callback); SBIEDLL_EXPORT BOOLEAN SbieDll_ExpandAndRunProgram(const WCHAR *Command); +SBIEDLL_EXPORT ULONG SbieDll_InjectLow_InitHelper(); +SBIEDLL_EXPORT ULONG SbieDll_InjectLow_InitSyscalls(BOOLEAN drv_init); +SBIEDLL_EXPORT ULONG SbieDll_InjectLow(HANDLE hProcess, BOOLEAN is_wow64, BOOLEAN bHostInject, BOOLEAN dup_drv_handle); + //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/drv/SboxDrv.vcxproj b/Sandboxie/core/drv/SboxDrv.vcxproj index ddb7ddcebb..7a99f5d3e5 100644 --- a/Sandboxie/core/drv/SboxDrv.vcxproj +++ b/Sandboxie/core/drv/SboxDrv.vcxproj @@ -239,6 +239,18 @@ true true + + true + true + true + true + + + true + true + true + true + @@ -267,11 +279,18 @@ true true - - - - - + + true + true + + + true + true + + + true + true + @@ -301,7 +320,10 @@ - + + true + true + @@ -366,6 +388,12 @@ true true + + true + true + true + true + diff --git a/Sandboxie/core/drv/api.c b/Sandboxie/core/drv/api.c index 93f027b123..40e0581bc7 100644 --- a/Sandboxie/core/drv/api.c +++ b/Sandboxie/core/drv/api.c @@ -185,7 +185,7 @@ _FX BOOLEAN Api_Init(void) Api_SetFunction(API_UNLOAD_DRIVER, Driver_Api_Unload); - Api_SetFunction(API_HOOK_TRAMP, Hook_Api_Tramp); + //Api_SetFunction(API_HOOK_TRAMP, Hook_Api_Tramp); if ((! Api_Functions) || (Api_Functions == (void *)-1)) return FALSE; diff --git a/Sandboxie/core/drv/api_defs.h b/Sandboxie/core/drv/api_defs.h index 4c038e2840..869f3b35e7 100644 --- a/Sandboxie/core/drv/api_defs.h +++ b/Sandboxie/core/drv/api_defs.h @@ -97,7 +97,7 @@ enum { API_QUERY_PATH_LIST, API_ENUM_PROCESSES, API_DISABLE_FORCE_PROCESS, - API_HOOK_TRAMP, + API_HOOK_TRAMP, // deprecated API_UNMOUNT_HIVES, // deprecated API_QUERY_CONF, API_RELOAD_CONF, diff --git a/Sandboxie/core/drv/driver.c b/Sandboxie/core/drv/driver.c index 77510a6bf5..89b4f78a0f 100644 --- a/Sandboxie/core/drv/driver.c +++ b/Sandboxie/core/drv/driver.c @@ -256,12 +256,12 @@ _FX BOOLEAN Driver_CheckOsVersion(void) // // make sure we're running on Windows XP (v5.1) or later (32-bit) - // or Windows Vista (v6.0) or later (64-bit) + // or Windows 7 (v6.1) or later (64-bit) // #ifdef _WIN64 const ULONG MajorVersionMin = 6; - const ULONG MinorVersionMin = 0; + const ULONG MinorVersionMin = 1; #else const ULONG MajorVersionMin = 5; const ULONG MinorVersionMin = 1; @@ -601,28 +601,30 @@ _FX BOOLEAN Driver_FindHomePath(UNICODE_STRING *RegistryPath) _FX BOOLEAN Driver_FindMissingServices(void) { - void *ptr; - WCHAR err_txt[128]; UNICODE_STRING uni; // // Windows 7 kernel exports ZwSetInformationToken // on earlier versions of Windows, we search for it // +#ifndef _WIN64 + if (Driver_OsVersion < DRIVER_WINDOWS_7) { + + void *ptr; + WCHAR err_txt[128]; - if (Driver_OsVersion >= DRIVER_WINDOWS_7) { - - RtlInitUnicodeString(&uni, L"ZwSetInformationToken"); - ZwSetInformationToken = (P_NtSetInformationToken) - MmGetSystemRoutineAddress(&uni); - if (! ZwSetInformationToken) { - Log_Msg1(MSG_1108, uni.Buffer); - return FALSE; - } - - } else { + FIND_SERVICE(ZwSetInformationToken, 4); - FIND_SERVICE(ZwSetInformationToken, 4); + } else +#endif + { + RtlInitUnicodeString(&uni, L"ZwSetInformationToken"); + ZwSetInformationToken = (P_NtSetInformationToken) + MmGetSystemRoutineAddress(&uni); + if (!ZwSetInformationToken) { + Log_Msg1(MSG_1108, uni.Buffer); + return FALSE; + } } return TRUE; diff --git a/Sandboxie/core/drv/hook.c b/Sandboxie/core/drv/hook.c index fed5b328b4..c668dfe804 100644 --- a/Sandboxie/core/drv/hook.c +++ b/Sandboxie/core/drv/hook.c @@ -24,6 +24,10 @@ #include "hook.h" #include "dll.h" +#include "util.h" +#define KERNEL_MODE +#include "../dll/hook_inst.c" +#include "../dll/hook_tramp.c" //--------------------------------------------------------------------------- // Defines diff --git a/Sandboxie/core/drv/hook.h b/Sandboxie/core/drv/hook.h index 475c9cbae0..9484271a54 100644 --- a/Sandboxie/core/drv/hook.h +++ b/Sandboxie/core/drv/hook.h @@ -21,78 +21,12 @@ #ifndef _MY_HOOK_H -#define _MY_HOOK_H +//#define _MY_HOOK_H // defined by "../dll/hook.h" #include "driver.h" - -//--------------------------------------------------------------------------- -// Structures and Types -//--------------------------------------------------------------------------- - - -#ifdef HOOK_WITH_PRIVATE_PARTS - - -enum HOOK_KIND { - - INST_UNKNOWN = 0, - INST_MOVE, - INST_CTLXFER, // jmp/jcc/call with 32-bit disp - INST_CTLXFER_REG, // jmp/call reg or [reg] - INST_CALL_MEM, // call [mem] - INST_JUMP_MEM, // jmp [mem] - INST_SYSCALL, - INST_RET -}; - - -typedef struct _HOOK_INST { - - ULONG len; - UCHAR kind; - UCHAR op1, op2; - ULONG64 parm; - LONG *rel32; // --> 32-bit relocation for control-xfer - UCHAR *modrm; - ULONG flags; - -} HOOK_INST; - - -#endif // HOOK_WITH_PRIVATE_PARTS - - -//--------------------------------------------------------------------------- -// HOOK_TRAMP -//--------------------------------------------------------------------------- - - -#pragma pack(push) -#pragma pack(1) - -typedef struct _HOOK_TRAMP { - - ULONG eyecatcher; // (0,4) signature - - ULONG size; // (4,4) tramp size (multiple of 16) - - void *target; // (8,4/8) branch target in source - - __declspec(align(16)) - UCHAR code[64]; // (16) source code + extra jmp - - ULONG count; // original length of relocated code - -} HOOK_TRAMP; - -#pragma pack(pop) - - -#define HOOK_TRAMP_CODE_TO_TRAMP_HEAD(x) \ - (HOOK_TRAMP *)((ULONG_PTR)x - FIELD_OFFSET(HOOK_TRAMP, code)) - +#include "../dll/hook.h" //--------------------------------------------------------------------------- // Functions @@ -111,49 +45,12 @@ LONG Hook_GetServiceIndex(void *DllProc, LONG *SkipIndexes); // kernel-mode Zw dispatcher stub (ZwXxx). BOOLEAN Hook_GetService( - void *DllProc, LONG *SkipIndexes, ULONG ParamCount, - void **NtService, void **ZwService); - - -// Hook_BuildTramp constructs a detour trampoline that will jump to -// SourceFunc + n, where n is the length, in bytes, of the first few -// instructions at SourceFunc that would be damaged by placing a jump -// instruction at the top of SourceFunc. The jump instruction is assumed -// to be 5 bytes long in 32-bit mode and 12 bytes long in 64-bit mode. -// The damaged instructions are copied to the detour trampoline. -// Returns the address to the start of the code in the detour trampoline. -// The function being redirected to, through the overwriting jump -// instruction, should jump to the returned value, to invoke the -// original code. The trampoline is built on the address specified -// in Trampoline. Kernel-mode code should pass a NULL address to -// use a system space trampoline. - -void *Hook_BuildTramp( - void *SourceFunc, void *Trampoline, BOOLEAN is64, BOOLEAN probe); - - -// Hook_BuildJump1 will write a 'jmp DestFunc' instruction at -// the address specified by WritableAddr. In case WritableAddr was -// generated using MmGetSystemAddressForMdlSafe, then ExecutableAddr -// specifies the corresponding "real" address which will be used to -// generate a 32-bit jump offset. (Note that 64-bit code does not -// use jump offsets and disregards ExecutableAddr.) - -void Hook_BuildJump( - void *WritableAddr, void *ExecutableAddr, void *JumpTarget); + void *DllProc, LONG *SkipIndexes, ULONG ParamCount, + void **NtService, void **ZwService); #ifdef HOOK_WITH_PRIVATE_PARTS - -// Analyze a single instruction at the specified address - -BOOLEAN Hook_Analyze( - void *address, - BOOLEAN probe_address, - BOOLEAN is64, - HOOK_INST *inst); - // Returns the address of the NTOS kernel service identified by the // specified service index. It must take exactly as many parameters // as indicated. This routine is implemented differently for 32-bit diff --git a/Sandboxie/core/low/inject.c b/Sandboxie/core/low/inject.c index 77e8ed9989..17f10553d3 100644 --- a/Sandboxie/core/low/inject.c +++ b/Sandboxie/core/low/inject.c @@ -247,12 +247,20 @@ _FX void InitInject(SBIELOW_DATA *data, void * RtlFindActivationContextSectionSt if (data->is_wow64) { - extern ULONG64 SbieApi_QueryProcessInfo( - SBIELOW_DATA *data, ULONG info_type); - - ULONG ntdll32_base = (ULONG)SbieApi_QueryProcessInfo(data, 'nt32'); - - ntdll_base = (void *)(ULONG_PTR)ntdll32_base; + // + // Instead of requiering the driver for this task, we can simplify it + // and use NtQueryVirtualMemory to find the mapped image directly. + // We do that in the injector, but we could also have done it here ourselves. + // + + ntdll_base = (void *)data->ntdll_wow64_base; + + //extern ULONG64 SbieApi_QueryProcessInfo( + // SBIELOW_DATA *data, ULONG info_type); + // + //ULONG ntdll32_base = (ULONG)SbieApi_QueryProcessInfo(data, 'nt32'); + // + //ntdll_base = (void *)(ULONG_PTR)ntdll32_base; // // (prior to Windows 8, the base address of ntdll32 is recorded diff --git a/Sandboxie/core/low/lowdata.h b/Sandboxie/core/low/lowdata.h index 6aca4c6a2e..02431179e8 100644 --- a/Sandboxie/core/low/lowdata.h +++ b/Sandboxie/core/low/lowdata.h @@ -68,6 +68,7 @@ typedef struct _SBIELOW_DATA { ULONG64 RealNtDeviceIoControlFile; #ifdef _WIN64 SBIELOW_J_TABLE * Sbie64bitJumpTable; + ULONG64 ntdll_wow64_base; #endif } SBIELOW_DATA; diff --git a/Sandboxie/core/svc/DriverAssist.h b/Sandboxie/core/svc/DriverAssist.h index 5ccd62d66c..7002a9d2fd 100644 --- a/Sandboxie/core/svc/DriverAssist.h +++ b/Sandboxie/core/svc/DriverAssist.h @@ -104,27 +104,10 @@ class DriverAssist // functions to inject low level code layer into new process // - bool InjectLow_Init(); - bool InjectLow_InitHelper(ULONG *errlvl); - static ULONG_PTR InjectLow_FindHighestAddress(); - ULONG InjectLow_InitSyscalls(); + bool InjectLow_Init(); void InjectLow(void *_msg); - HANDLE InjectLow_OpenProcess(void *_msg); - HANDLE InjectLow_SendHandle(HANDLE hProcess); - void *InjectLow_CopyCode(HANDLE hProcess, BOOLEAN iswow64, - UCHAR *code, ULONG code_len); - bool InjectLow_BuildTramp( - void *_msg, BOOLEAN long_diff, UCHAR *code, ULONG_PTR addr); - void *InjectLow_CopySyscalls(HANDLE hProcess); - bool InjectLow_CopyData( - HANDLE hProcess, void *remote_addr, void *local_data); -#ifdef _WIN64 - void * InjectLow_getPage(HANDLE hProcess,void *remote_addr); - bool DriverAssist::Has32BitJumpHorizon(void * target, void * detour); -#endif - bool InjectLow_WriteJump( - HANDLE hProcess, void *remote_addr, BOOLEAN long_diff, void * local_data); + HANDLE InjectLow_OpenProcess(void *_msg); // // data @@ -148,21 +131,6 @@ class DriverAssist CRITICAL_SECTION m_LogMessage_CritSec; CRITICAL_SECTION m_critSecHostInjectedSvcs; - // - // DriverAssistInject data - // - - void *m_sbielow_ptr; - //adding two offsets variables to replace the "head" and "tail" dependency - ULONG m_sbielow_start_offset; - ULONG m_sbielow_data_offset; - - ULONG m_sbielow_len; - - ULONG *m_syscall_data; - - ULONG_PTR m_LdrInitializeThunk; - }; diff --git a/Sandboxie/core/svc/DriverAssistInject.cpp b/Sandboxie/core/svc/DriverAssistInject.cpp index 89d057def0..02ad95a25e 100644 --- a/Sandboxie/core/svc/DriverAssistInject.cpp +++ b/Sandboxie/core/svc/DriverAssistInject.cpp @@ -35,16 +35,8 @@ bool DriverAssist::InjectLow_Init() { - ULONG level = 0; - - m_sbielow_start_offset = 0; - m_sbielow_data_offset = 0; - m_sbielow_ptr = NULL; - m_sbielow_len = 0; - m_syscall_data = NULL; - - ULONG errlvl = 0; - if (! InjectLow_InitHelper(&errlvl)) { + ULONG errlvl = SbieDll_InjectLow_InitHelper(); + if (errlvl != 0) { LogEvent(MSG_9234, 0x9241, errlvl); return false; } @@ -53,414 +45,35 @@ bool DriverAssist::InjectLow_Init() } -//--------------------------------------------------------------------------- -// InjectLow_InitHelper -//--------------------------------------------------------------------------- - - - -typedef struct _MY_TARGETS { - unsigned long long entry; - unsigned long long data; -} MY_TARGETS; - -extern ULONG Dll_Windows; - -bool DriverAssist::InjectLow_InitHelper(ULONG *errlvl) -{ - // - // 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; - IMAGE_DATA_DIRECTORY *data_dirs = 0; - ULONG_PTR imageBase = 0; - MY_TARGETS *targets = 0; - - *errlvl = 0x11; - - HRSRC hrsrc = FindResource(NULL, L"LOWLEVEL", RT_RCDATA); - if (! hrsrc) - return false; - - ULONG binsize = SizeofResource(NULL, hrsrc); - if (! binsize) - return false; - - HGLOBAL hglob = LoadResource(NULL, hrsrc); - if (! hglob) - return false; - - UCHAR *bindata = (UCHAR *)LockResource(hglob); - if (! bindata) - return false; - - *errlvl = 0x22; - dos_hdr = (IMAGE_DOS_HEADER *)bindata; - - 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 false; - } - } - else { - - return false; - } - } - - if (imageBase) { - return false; - } - - section = IMAGE_FIRST_SECTION(nt_hdrs); - if (nt_hdrs->FileHeader.NumberOfSections < 2) return false; - if (strncmp((char *)section[0].Name, SBIELOW_INJECTION_SECTION, strlen(SBIELOW_INJECTION_SECTION)) || - strncmp((char *)section[1].Name, SBIELOW_SYMBOL_SECTION, strlen(SBIELOW_SYMBOL_SECTION))) { - return false; - } - - - targets = (MY_TARGETS *)& bindata[section[1].PointerToRawData]; - m_sbielow_start_offset = (ULONG)targets->entry - section[0].VirtualAddress; - m_sbielow_data_offset = (ULONG)targets->data - 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); - - if ((!m_sbielow_start_offset) || (!m_sbielow_data_offset)) - return false; - - // - // record information about ntdll and the virtual memory system - // - - *errlvl = 0x33; - - m_LdrInitializeThunk = (ULONG_PTR) GetProcAddress(_Ntdll, "LdrInitializeThunk"); - - if (! m_LdrInitializeThunk) - return false; - -#ifdef _WIN64 - if (Dll_Windows >= 10) { - unsigned char * code; - code = (unsigned char *)m_LdrInitializeThunk; - if (*(ULONG *)&code[0] == 0x24048b48 && code[0xa] == 0x48) { - m_LdrInitializeThunk += 0xa; - } - } -#endif - - return true; -} - - -// InjectLow_InitSyscalls -//--------------------------------------------------------------------------- - -ULONG DriverAssist::InjectLow_InitSyscalls() -{ - const WCHAR *_SbieDll = L"\\" SBIEDLL L".dll"; - ULONG status; - ULONG len; - SBIELOW_EXTRA_DATA *extra; - WCHAR *ptr; - ULONG *syscall_data; - -#define ULONG_DIFF(b,a) ((ULONG)((ULONG_PTR)(b) - (ULONG_PTR)(a))) - - // - // get the list of syscall from the driver - // - - if (! m_syscall_data) { - syscall_data = (ULONG *)HeapAlloc(GetProcessHeap(), 0, 8192); - if (! syscall_data) - return STATUS_INSUFFICIENT_RESOURCES; - *syscall_data = 0; - } else - syscall_data = m_syscall_data; - - status = SbieApi_CallOne(API_QUERY_SYSCALLS, (ULONG_PTR)syscall_data); - if (status != 0) - return status; - - len = *syscall_data; - if ((! len) || (len & 3) || (len > 4096)) - return STATUS_INVALID_IMAGE_FORMAT; - - // - // the second ULONG in syscall_data points to extra data appended - // by us here on top of what the driver returned - // - - extra = (SBIELOW_EXTRA_DATA *)((ULONG_PTR)syscall_data + len); - - syscall_data[1] = len; - - // - // write an ASCII string for LdrLoadDll (see core/low/inject.c) - // - - ptr = (WCHAR *)((ULONG_PTR)extra + sizeof(SBIELOW_EXTRA_DATA)); - - strcpy((char *)ptr, "LdrLoadDll"); - - extra->LdrLoadDll_offset = ULONG_DIFF(ptr, extra); - ptr += 16 / sizeof(WCHAR); - - // - // write an ASCII string for LdrGetProcedureAddress - // - - strcpy((char *)ptr, "LdrGetProcedureAddress"); - - extra->LdrGetProcAddr_offset = ULONG_DIFF(ptr, extra); - ptr += 28 / sizeof(WCHAR); - - // - // write an ASCII string for NtRaiseHardError - // - - strcpy((char *)ptr, "NtRaiseHardError"); - - extra->NtRaiseHardError_offset = ULONG_DIFF(ptr, extra); - ptr += 20 / sizeof(WCHAR); - - // - // write an ASCII string for RtlFindActivationContextSectionString - // - - strcpy((char *)ptr, "RtlFindActivationContextSectionString"); - - extra->RtlFindActCtx_offset = ULONG_DIFF(ptr, extra); - ptr += 44 / sizeof(WCHAR); - - // - // ntdll loads kernel32 without a path, we will do the same - // in our hook for RtlFindActivationContextSectionString, - // see entry.asm - // - - wcscpy(ptr, L"kernel32.dll"); - - len = wcslen(ptr); - extra->KernelDll_offset = ULONG_DIFF(ptr, extra);; - extra->KernelDll_length = len * sizeof(WCHAR); - ptr += len + 1; - - // - // append paths for native and wow64 SbieDll to the syscall buffer - // - - status = SbieApi_GetHomePath(NULL, 0, ptr, 512); - if (status != 0) - return status; - wcscat(ptr, _SbieDll); - - len = wcslen(ptr); - extra->NativeSbieDll_offset = ULONG_DIFF(ptr, extra);; - extra->NativeSbieDll_length = len * sizeof(WCHAR); - ptr += len + 1; - -#ifdef _WIN64 - - status = SbieApi_GetHomePath(NULL, 0, ptr, 512); - if (status != 0) - return status; - wcscat(ptr, L"\\32"); - wcscat(ptr, _SbieDll); - - len = wcslen(ptr); - extra->Wow64SbieDll_offset = ULONG_DIFF(ptr, extra); - extra->Wow64SbieDll_length = len * sizeof(WCHAR); - ptr += len + 1; - -#endif _WIN64 - - // - // adjust size of syscall buffer to include path strings - // - - *syscall_data = ULONG_DIFF(ptr, syscall_data); - -#undef ULONG_DIFF - - m_syscall_data = syscall_data; - - return STATUS_SUCCESS; -} - - //--------------------------------------------------------------------------- // InjectLow //--------------------------------------------------------------------------- + void DriverAssist::InjectLow(void *_msg) { - SVC_PROCESS_MSG *msg = (SVC_PROCESS_MSG *)_msg; - ULONG errlvl; - - // - // verify all aspects of initialization were successful - // - if ((! m_sbielow_ptr) || (! m_syscall_data)) { - - SetLastError(ERROR_NOT_READY); - errlvl = 0xFF; - goto finish; - } + SVC_PROCESS_MSG *msg = (SVC_PROCESS_MSG *)_msg; - // - // open new process and verify process creation time - // + ULONG errlvl = 0; + + // + // open new process and verify process creation time + // - HANDLE hProcess = InjectLow_OpenProcess(_msg); - if (! hProcess) { + HANDLE hProcess = InjectLow_OpenProcess(_msg); + if (!hProcess) { - errlvl = 0x11; - goto finish; - } + errlvl = 0x11; + goto finish; + } - // - // prepare the lowdata paramters area to copy into target process - // + // + // inject the lowlevel.dll into the target process + // - SBIELOW_DATA lowdata; - memzero(&lowdata, sizeof(lowdata)); - - lowdata.ntdll_base = (ULONG64)(ULONG_PTR)_Ntdll; - - lowdata.is_wow64 = msg->is_wow64; - lowdata.bHostInject = msg->bHostInject; - - lowdata.RealNtDeviceIoControlFile = (ULONG64) GetProcAddress((HMODULE) lowdata.ntdll_base,"NtDeviceIoControlFile"); - // - // on 64-bit Windows 8, there might be a difference of more than - // 2GB bytes between ntdll and the injected SbieLow, which requires - // use of longer jump sequences than the 5-byte 0xE9 relative jump - // - if (Dll_Windows >= 10) { - lowdata.is_win10 = TRUE; - } - - void *remote_addr = InjectLow_CopyCode(hProcess, lowdata.is_wow64, lowdata.LdrInitializeThunk_tramp, sizeof(lowdata.LdrInitializeThunk_tramp)); - if (!remote_addr) { - errlvl = 0x33; - goto finish; - } - // if (lowdata.is_wow64 && (m_addr_high != m_addr_high_32)) -#ifdef _WIN64 - lowdata.long_diff = TRUE; - if (Has32BitJumpHorizon((void *)m_LdrInitializeThunk, remote_addr)) { - lowdata.long_diff = FALSE; - } -#else - lowdata.long_diff = FALSE; -#endif - - // - // duplicate the SbieDrv API file device handle into target process - // - - lowdata.api_device_handle = (ULONG64)(ULONG_PTR) - InjectLow_SendHandle(hProcess); - if (! lowdata.api_device_handle) { - - errlvl = 0x22; - goto finish; - } - - lowdata.api_sbiedrv_ctlcode = API_SBIEDRV_CTLCODE; - - lowdata.api_invoke_syscall = API_INVOKE_SYSCALL; - - // - // the driver sent us a copy of some functions from ntdll in the - // syscall_data buffer, copy that code to SbieLow through the - // lowdata area (see also core/drv/syscall.c and core/low/lowdata.h) - // - - memcpy(lowdata.NtDelayExecution_code, &m_syscall_data[2], (32 * 4)); - - // - // allocate space for and write the lowlevel (SbieLow) code - // and copy code at LdrInitializeThunk from target process - // - -#ifdef _WIN64 - lowdata.Sbie64bitJumpTable = (SBIELOW_J_TABLE *) ((ULONG_PTR) remote_addr +m_sbielow_len+0x400); //(0x400 - (m_sbielow_len & 0x3ff))+ m_sbielow_len; -#endif - - // - // remove hard coded data block offset - ULONG_PTR tramp_remote_addr = // calculate address in remote process - (ULONG_PTR)remote_addr - + m_sbielow_data_offset // offset of args area - + FIELD_OFFSET(SBIELOW_DATA, LdrInitializeThunk_tramp); - - if (! InjectLow_BuildTramp(_msg, lowdata.long_diff, - lowdata.LdrInitializeThunk_tramp, tramp_remote_addr)) { - - errlvl = 0x44; - goto finish; - } - - // - // copy the syscall data buffer (m_syscall_data) to target process - // - - void *remote_syscall_data = InjectLow_CopySyscalls(hProcess); - if (! remote_syscall_data) { - - errlvl = 0x55; - goto finish; - } - - lowdata.syscall_data = (ULONG64)(ULONG_PTR)remote_syscall_data; - - // - // write lowdata parameter area, including the converted trampoline - // code, into target process, and make it execute-read - // - if (! InjectLow_CopyData(hProcess, remote_addr, &lowdata)) { - - errlvl = 0x66; - goto finish; - } - - // - // overwrite the top of LdrInitializeThunk to jump to injected code - // note that we have to skip the 8-byte signature (.HEAD.00) - // - // Removed hard coded dependency on (.HEAD.00). No longer need to add 8 to - // the remote_addr - if (!InjectLow_WriteJump(hProcess, (UCHAR *)remote_addr + m_sbielow_start_offset, lowdata.long_diff, &lowdata)) { - errlvl = 0x77; - goto finish; - } + errlvl = SbieDll_InjectLow(hProcess, msg->is_wow64, msg->bHostInject, TRUE); + if(errlvl != 0) + goto finish; // // put process into a job for win32 restrictions @@ -544,540 +157,3 @@ HANDLE DriverAssist::InjectLow_OpenProcess(void *_msg) return NULL; } - -//--------------------------------------------------------------------------- -// InjectLow_SendHandle -//--------------------------------------------------------------------------- - - -HANDLE DriverAssist::InjectLow_SendHandle(HANDLE hProcess) -{ - NTSTATUS status; - HANDLE HandleLocal, HandleRemote; - UNICODE_STRING uni; - OBJECT_ATTRIBUTES objattrs; - IO_STATUS_BLOCK MyIoStatusBlock; - - // - // open the Sandboxie driver API file handle - // - - RtlInitUnicodeString(&uni, API_DEVICE_NAME); - InitializeObjectAttributes( - &objattrs, &uni, OBJ_CASE_INSENSITIVE, NULL, NULL); - - status = NtOpenFile( - &HandleLocal, FILE_GENERIC_READ, &objattrs, &MyIoStatusBlock, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0); - - if (NT_SUCCESS(status)) { - - // - // duplicate opened handle into new process - // - - BOOL ok = DuplicateHandle(NtCurrentProcess(), HandleLocal, - hProcess, &HandleRemote, 0, FALSE, - DUPLICATE_SAME_ACCESS); - - CloseHandle(HandleLocal); - - if (ok) { - - return HandleRemote; - } - } - - return NULL; -} - - -//--------------------------------------------------------------------------- -// InjectLow_CopyCode -//--------------------------------------------------------------------------- - - -void *DriverAssist::InjectLow_CopyCode(HANDLE hProcess, BOOLEAN iswow64, UCHAR *code, ULONG code_len) -{ - SIZE_T region_size; - SIZE_T lowLevel_size; - void *remote_addr = NULL; -#ifdef _WIN64 - lowLevel_size = m_sbielow_len + sizeof(SBIELOW_J_TABLE) + 0x400; -#else - lowLevel_size = m_sbielow_len; -#endif - region_size = lowLevel_size; - - for (int i = 8; !remote_addr && i > 2; i--) { - NTSTATUS status = NtAllocateVirtualMemory(hProcess, &remote_addr, i, ®ion_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (!NT_SUCCESS(status)) { - remote_addr = NULL; - region_size = lowLevel_size; - } - } - if (remote_addr) { - - // - // copy SbieLow into the allocated region in the new process - // - - SIZE_T len1 = m_sbielow_len; - SIZE_T len2 = 0; - BOOL vm_ok = WriteProcessMemory( - hProcess, remote_addr, m_sbielow_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, (void *)m_LdrInitializeThunk, code, - len1, &len2); - - if (vm_ok && len1 == len2) { - - return remote_addr; - } - } - } - - return NULL; -} - - -//--------------------------------------------------------------------------- -// InjectLow_BuildTramp -//--------------------------------------------------------------------------- - - -bool DriverAssist::InjectLow_BuildTramp( - void *_msg, BOOLEAN long_diff, UCHAR *code, ULONG_PTR addr) -{ - -#define IS_1BYTE(a) ( code[offset + 0] == (a)) -#define IS_2BYTE(a,b) (IS_1BYTE(a) && code[offset + 1] == (b)) -#define IS_3BYTE(a,b,c) (IS_2BYTE(a,b) && code[offset + 2] == (c)) - - // - // skip past several bytes in the code copied from the top of the - // LdrInitializeThunk fuction, where we will inject a jmp sequence. - // - // a simple E9 relative JMP five byte instruction in most cases, - // a slightly longer seven byte version in case there is a long - // distance between ntdll and SbieLow, i.e. on 64-bit Windows 8 - // - - ULONG code_len = (long_diff ? 7 : 5); - - ULONG offset = 0; - while (offset < code_len) { - - ULONG inst_len = 0; - - if (0) - ; - - // push ebp - else if (IS_1BYTE(0x55)) - inst_len = 1; - - // mov ebp, esp - else if (IS_2BYTE(0x8B, 0xEC)) - inst_len = 2; - - // mov edi, edi - else if (IS_2BYTE(0x8B, 0xFF)) - inst_len = 2; - - // push ebx - else if (IS_2BYTE(0xFF, 0xF3)) - inst_len = 2; - - // push rbx (Windows 8.1) - else if (IS_2BYTE(0x40, 0x53)) - inst_len = 2; - - // mov dword ptr [esp+imm8],eax - else if (IS_3BYTE(0x89, 0x44, 0x24)) - inst_len = 4; - - // lea eax, esp+imm8 - else if (IS_3BYTE(0x8D, 0x44, 0x24)) - inst_len = 4; - - // sub rsp, imm8 - else if (IS_3BYTE(0x48, 0x83, 0xEC)) - inst_len = 4; - - // mov rbx, rcx - else if (IS_3BYTE(0x48, 0x8B, 0xD9)) - inst_len = 3; - - /* - else if (IS_3BYTE(0x48, 0x8B, 0x04)) - inst_len = 4; - */ - // - // abort if we don't recognize the instruction - // - - if (! inst_len) { - - SVC_PROCESS_MSG *msg = (SVC_PROCESS_MSG *)_msg; - - SbieApi_LogEx(msg->session_id, 2335, - L"%S [%02X %02X %02X %02X %02X %02X" - L" %02X %02X %02X %02X %02X %02X]", - msg->process_name, - code[0], code[1], code[2], code[3], code[4], code[5], - code[6], code[7], code[8], code[9], code[10], code[11]); - - SetLastError(ERROR_UNKNOWN_PRODUCT); - - return false; - } - - offset += inst_len; - } - -#undef IS_3BYTE -#undef IS_2BYTE -#undef IS_1BYTE - - // - // append a jump instruction at the bottom of our trampoline for - // LdrInitializeThunk, which jumps back to the real LdrInitializeThunk - // - // note that on Windows 8 the difference between the address of - // LdrInitializeThunk in the 64-bit ntdll and where SbieLow was copied - // may be greater than 32-bit, so we use JMP QWORD rather than the - // 5-byte 0xE9 relative JMP - // -#ifdef _WIN64 - if (!long_diff) { - - if (Dll_Windows >= 10) { - code[offset] = 0x48; - code[offset + 1] = 0xE9; - *(ULONG *)&code[offset + 2] = (ULONG) - (m_LdrInitializeThunk + offset - (addr + offset + 6)); - - } - else { - code[offset] = 0xe9; - *(ULONG *)&code[offset + 1] = (ULONG) - (m_LdrInitializeThunk + offset - (addr + offset + 5)); - } - } - else { - - *(USHORT *)&code[offset] = 0x25FF; // jmp qword ptr - *(ULONG *)&code[offset + 2] = 0; - *(ULONG64 *)&code[offset + 6] = m_LdrInitializeThunk + offset; - } -#else - code[offset] = 0xE9; - - *(ULONG *)&code[offset + 1] = (ULONG) - (m_LdrInitializeThunk + offset - (addr + offset + 5)); -#endif - return true; -} - - -//--------------------------------------------------------------------------- -// InjectLow_CopySyscalls -//--------------------------------------------------------------------------- - - -void *DriverAssist::InjectLow_CopySyscalls(HANDLE hProcess) -{ - // - // allocate virtual memory somewhere in the process. to force an - // address in the low 24-bits of the address space, we have to use - // NtAllocateVirtalMemory and specify ZeroBits = 8 (32 - 8 = 24) - // - - void *remote_addr = NULL; - SIZE_T region_size = *m_syscall_data; - int i; - NTSTATUS status; - - for (i = 8; !remote_addr && i > 2; i--) { - status = NtAllocateVirtualMemory(hProcess, &remote_addr, i, ®ion_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (!NT_SUCCESS(status)) { - remote_addr = NULL; - region_size = *m_syscall_data; - } - } - - if (!NT_SUCCESS(status)) { - remote_addr = NULL; - SetLastError(RtlNtStatusToDosError(status)); - } - if (remote_addr) { - - // - // copy the syscall data buffer into the new process - // - - SIZE_T len1 = *m_syscall_data; - SIZE_T len2 = 0; - BOOL vm_ok = WriteProcessMemory( - hProcess, remote_addr, m_syscall_data, len1, &len2); - if (vm_ok && len1 == len2) { - - return remote_addr; - } - } - - return NULL; -} - - -//--------------------------------------------------------------------------- -// InjectLow_CopyData -//--------------------------------------------------------------------------- - - -bool DriverAssist::InjectLow_CopyData( - HANDLE hProcess, void *remote_addr, void *local_data) -{ - // - // copy SBIELOW_DATA data into the area reserved within SbieLow - // (i.e. at offset SBIELOW_DATA_OFFSET) in the new process - // - - void *data_addr = (void *)((ULONG_PTR)remote_addr + m_sbielow_data_offset); - SIZE_T len1 = sizeof(SBIELOW_DATA); - SIZE_T len2 = 0; - BOOL vm_ok = WriteProcessMemory( - hProcess, data_addr, local_data, len1, &len2); - if (vm_ok && len1 == len2) { - - ULONG protect; - vm_ok = VirtualProtectEx(hProcess, remote_addr, m_sbielow_len, - PAGE_EXECUTE_READ, &protect); - if (vm_ok) { - return true; - } - } - - return false; -} - -#ifdef _WIN64 - -bool DriverAssist::Has32BitJumpHorizon(void * target, void * detour) { - ULONG_PTR diff; - long long delta; - diff = (ULONG_PTR)((ULONG_PTR)target - (ULONG_PTR)detour); - delta = diff; - delta < 0 ? delta *= -1 : delta; - //is DetourFunc in 32bit jump range - if (delta < 0x80000000) { - return TRUE; - } - return FALSE; -} - -void * DriverAssist::InjectLow_getPage(HANDLE hProcess, void *remote_addr) -{ - SIZE_T mySize; - ULONG_PTR tempAddr; - void * myTable = 0; - UCHAR *func; - ULONG myProtect; - short myBuffer[1024]; - SIZE_T readSize; - BOOL myVM; - HANDLE myKernel32; - HANDLE myNtDll; - //HANDLE myTestDll; - func = (UCHAR *)((ULONG_PTR)m_LdrInitializeThunk); - myKernel32 = GetModuleHandleA("kernel32.dll"); - myNtDll = GetModuleHandleA("ntdll.dll"); - // myTestDll = 0; - - /* - if(myTestDll) { - //for testing remove this code! - sprintf(buffer,"Dll Collision Test: address %p\n",myTestDll); - OutputDebugStringA(buffer); - myTable = VirtualAllocEx(hProcess,myTestDll,0x100, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); - } - else { - */ - (ULONG_PTR)myNtDll < (ULONG_PTR)myKernel32 ? tempAddr = (ULONG_PTR)myNtDll - 0x10000 : tempAddr = (ULONG_PTR)myKernel32 - 0x10000; - myTable = VirtualAllocEx(hProcess, (void *)tempAddr, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - // } - /* - else { - //use hack if all else fails - //OutputDebugStringA("Unable to allocate page!\n"); - max_attempts = 0; - } - */ - - if (myTable) { - mySize = 0; - if (Has32BitJumpHorizon(myTable, func)) { - WriteProcessMemory(hProcess, myTable, &remote_addr, 8, &mySize); - /* - sprintf(buffer,"myPage = %p, kernel32 = %p, ntdll = %p\n",myTable,myKernel32,myNtDll); - OutputDebugStringA(buffer); - */ - if (mySize == 8) { - return myTable; - } - } - } - /* - sprintf(buffer,"Failed to find table for target address %p, func = %p\n",myTable,func); - OutputDebugStringA(buffer); - */ - - readSize = 1; - tempAddr = (ULONG_PTR)func - 8; - ReadProcessMemory(hProcess, (void *)((ULONG_PTR)tempAddr), &myBuffer, 8, &readSize); - - // if hot patch area - if (*((ULONG_PTR *)&myBuffer) == 0x9090909090909090 || *((ULONG_PTR *)&myBuffer) == 0xcccccccccccccccc) { - //OutputDebugStringA("Using hotpatch area\n"); - myTable = (void *)tempAddr; - } - else { //not hot patch area: This is a hack - //patch area in .rdata section of ntdll - ReadProcessMemory(hProcess, (void *)((ULONG_PTR)tempAddr + 0x100000), myBuffer, sizeof(myBuffer), &readSize); - if (readSize != sizeof(myBuffer)) { - //OutputDebugStringA("Error reading Memory\n"); - return NULL; - } - for (int i = 0; i < sizeof(myBuffer) && !myTable; i++) { - if (*((ULONG_PTR*)&myBuffer[i]) == 0x9090909090909090 || - *((ULONG_PTR*)&myBuffer[i]) == 0xcccccccccccccccc) { - myTable = (void *)((ULONG_PTR)tempAddr + i); - /* - sprintf(buffer,"HACK: table found at %p, index %x\n",myTable, i); - OutputDebugStringA(buffer); - */ - } - } - if (!myTable) { - //OutputDebugStringA("Table not found\n"); - return NULL; - } - - } //end else not hotpatch area - - myVM = VirtualProtectEx(hProcess, myTable, sizeof(void *), PAGE_READWRITE, &myProtect); - if (myVM) { - SIZE_T len2 = 0; - myVM = WriteProcessMemory(hProcess, myTable, &remote_addr, 8, &len2); - if (myVM && 8 == len2) { - myVM = VirtualProtectEx(hProcess, myTable, 8, myProtect, &myProtect); - if (myVM) { - return myTable; - } - } - } - - return NULL; -} -#endif //#ifdef _WIN64 - -//--------------------------------------------------------------------------- -// InjectLow_WriteJump -//--------------------------------------------------------------------------- -bool DriverAssist::InjectLow_WriteJump(HANDLE hProcess, void *remote_addr, BOOLEAN long_diff, void *localdata) -{ - // - // prepare a short prolog code that jumps to the injected SbieLow - // - UCHAR jump_code[16]; - void * detour = (void *)remote_addr; - UCHAR *func = (UCHAR *)((ULONG_PTR)m_LdrInitializeThunk);; - SIZE_T len1; - BOOL myVM; - ULONG myProtect; - -#ifdef _WIN64 - if (!long_diff) { - if (Dll_Windows >= 10) { - len1 = 6; - jump_code[0] = 0x48; //jump to entry code in entry.asm - jump_code[1] = 0xE9; //jump to entry code in entry.asm - *(ULONG *)(jump_code + 2) = (ULONG)((ULONG_PTR)detour - (m_LdrInitializeThunk + 6)); - //remote_addr = (void *)m_LdrInitializeThunk; - } - else { - len1 = 5; - jump_code[0] = 0xe9; //jump to entry code in entry.asm - *(ULONG *)(jump_code + 1) = (ULONG)((ULONG_PTR)detour - (m_LdrInitializeThunk + 5)); - } - } - - else { - void * myTable = 0; - if (!((ULONG_PTR)remote_addr & 0xffffffff00000000)) { - len1 = 7; - jump_code[0] = 0xB8; - *(ULONG *)(jump_code + 1) = (ULONG)(ULONG_PTR)remote_addr; - *(USHORT *)(jump_code + 5) = 0xE0FF; // jmp rax - } - else { - ULONG_PTR target; - ULONG_PTR diff; - - len1 = 6; - target = (ULONG_PTR)&func[6]; - myTable = InjectLow_getPage(hProcess, remote_addr); - if (!myTable) { - //OutputDebugStringA("Error: Table not set!\n"); - return false; - } - - diff = (ULONG_PTR) &((ULONG_PTR *)myTable)[0]; - diff = diff - target; - - *(USHORT *)&jump_code[0] = 0x25ff; - *(ULONG *)&jump_code[2] = (ULONG)diff; - } - } -#else - len1 = 5; - jump_code[0] = 0xE9; //jump to entry code in entry.asm - *(ULONG *)(jump_code + 1) = (ULONG)((ULONG_PTR)detour - (m_LdrInitializeThunk + 5)); - //remote_addr = (void *)m_LdrInitializeThunk; -#endif - // - // modify the bytes at LdrInitializeThunk with the prolog code - // - - myVM = VirtualProtectEx(hProcess, func, len1, PAGE_READWRITE, &myProtect); - if (myVM) { - SIZE_T len2 = 0; - myVM = WriteProcessMemory(hProcess, func, jump_code, len1, &len2); - /* - sprintf(buffer,"WriteJump: len2 = %d\n",len2); - OutputDebugStringA(buffer); - */ - if (myVM && len1 == len2) { - myVM = VirtualProtectEx(hProcess, func, len1, myProtect, &myProtect); - if (myVM) { - return true; - } - } - } - return false; -} diff --git a/Sandboxie/core/svc/DriverAssistStart.cpp b/Sandboxie/core/svc/DriverAssistStart.cpp index a3e124b98e..9f9777c056 100644 --- a/Sandboxie/core/svc/DriverAssistStart.cpp +++ b/Sandboxie/core/svc/DriverAssistStart.cpp @@ -158,7 +158,7 @@ ULONG DriverAssist::StartDriverAsync(void *arg) } if (ok) { - rc = m_instance->InjectLow_InitSyscalls(); + SbieDll_InjectLow_InitSyscalls(TRUE); if (rc != 0) { LogEvent(MSG_9234, 0x9362, rc); ok = false; diff --git a/Sandboxie/core/svc/SboxSvc.vcxproj b/Sandboxie/core/svc/SboxSvc.vcxproj index 44ac001d10..9f0416bd40 100644 --- a/Sandboxie/core/svc/SboxSvc.vcxproj +++ b/Sandboxie/core/svc/SboxSvc.vcxproj @@ -268,7 +268,6 @@ - diff --git a/SandboxiePlus/QSbieAPI/SbieAPI.cpp b/SandboxiePlus/QSbieAPI/SbieAPI.cpp index 5605488bda..bf52c67d2d 100644 --- a/SandboxiePlus/QSbieAPI/SbieAPI.cpp +++ b/SandboxiePlus/QSbieAPI/SbieAPI.cpp @@ -197,7 +197,7 @@ SB_STATUS CSbieAPI::Connect() m->lastRecordNum = 0; #ifndef _DEBUG - QStringList CompatVersions = QStringList () << "5.43" << "5.43.5"; + QStringList CompatVersions = QStringList () << "5.43" << "5.43.5" << "5.44.0"; QString CurVersion = GetVersion(); if (!CompatVersions.contains(CurVersion)) { diff --git a/SandboxiePlus/SandMan/SandMan.h b/SandboxiePlus/SandMan/SandMan.h index 5828643e33..319f3bcc06 100644 --- a/SandboxiePlus/SandMan/SandMan.h +++ b/SandboxiePlus/SandMan/SandMan.h @@ -12,7 +12,7 @@ #define VERSION_MJR 0 #define VERSION_MIN 4 -#define VERSION_REV 3 +#define VERSION_REV 4 #define VERSION_UPD 0