This commit is contained in:
DavidXanatos 2021-12-15 23:31:28 +01:00
parent 93ae00aba1
commit db2b095d6c
9 changed files with 281 additions and 257 deletions

View File

@ -9,7 +9,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Changed ### Changed
- mechanism to hook Win32 system calls now also works for 32 bit applications running under WoW64 - mechanism to hook Win32 system calls now also works for 32 bit applications running under WoW64
- cleaned up low level hooking code a bit

View File

@ -406,6 +406,7 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\apps\com\common.h" /> <ClInclude Include="..\..\apps\com\common.h" />
<ClInclude Include="..\..\common\map.h" /> <ClInclude Include="..\..\common\map.h" />
<ClInclude Include="..\..\common\my_version.h" />
<ClInclude Include="..\..\common\ntproto.h" /> <ClInclude Include="..\..\common\ntproto.h" />
<ClInclude Include="..\..\common\str_util.h" /> <ClInclude Include="..\..\common\str_util.h" />
<ClInclude Include="..\..\common\my_wsa.h" /> <ClInclude Include="..\..\common\my_wsa.h" />

View File

@ -295,6 +295,9 @@
<ClInclude Include="..\..\common\wow64ext\wow64ext.h"> <ClInclude Include="..\..\common\wow64ext\wow64ext.h">
<Filter>common\wow64ext</Filter> <Filter>common\wow64ext</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\common\my_version.h">
<Filter>common</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="resource.rc" /> <ResourceCompile Include="resource.rc" />

View File

@ -25,16 +25,18 @@
#include "common\pattern.h" #include "common\pattern.h"
#define HOOK_WIN32K
#ifdef HOOK_WIN32K
#include "core/drv/api_defs.h" #include "core/drv/api_defs.h"
#include "core/low/lowdata.h" #include "core/low/lowdata.h"
SBIELOW_DATA* SbieApi_data = NULL; SBIELOW_DATA* SbieApi_data = NULL;
#define SBIELOW_CALL(x) ((P_##x)&data->x##_code) #define SBIELOW_CALL(x) ((P_##x)&data->x##_code)
//---------------------------------------------------------------------------
// SbieDll_HookWin32SysCalls
//---------------------------------------------------------------------------
_FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base) _FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base)
{ {
UCHAR *SystemServiceAsm, *ZwXxxPtr; UCHAR *SystemServiceAsm, *ZwXxxPtr;
@ -102,7 +104,6 @@ _FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base)
SyscallNum = SyscallPtr[0]; SyscallNum = SyscallPtr[0];
#ifdef _WIN64 #ifdef _WIN64
SyscallNum &= 0xFFFF; // clear the not needed param count
ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber
ZwXxxPtr[1] = 0xC7; ZwXxxPtr[1] = 0xC7;
@ -112,7 +113,7 @@ _FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base)
if (data->flags.is_win10) { if (data->flags.is_win10) {
ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm
ZwXxxPtr[8] = 0xE9; // jmp SystemServiceAsm ZwXxxPtr[8] = 0xE9;
*(ULONG *)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (ZwXxxPtr + 13)); *(ULONG *)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (ZwXxxPtr + 13));
} }
else { else {
@ -129,7 +130,7 @@ _FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base)
#else ! _WIN64 #else ! _WIN64
ZwXxxPtr[0] = 0xB8; // mov eax, SyscallNumber ZwXxxPtr[0] = 0xB8; // mov eax, SyscallNumber, with param count in the highest byte
*(ULONG *)&ZwXxxPtr[1] = SyscallNum; *(ULONG *)&ZwXxxPtr[1] = SyscallNum;
ZwXxxPtr[5] = 0xE9; // jmp SystemServiceAsm ZwXxxPtr[5] = 0xE9; // jmp SystemServiceAsm
*(ULONG *)&ZwXxxPtr[6] = *(ULONG *)&ZwXxxPtr[6] =
@ -148,72 +149,12 @@ _FX BOOLEAN SbieDll_HookWin32SysCalls(HMODULE win32u_base)
return TRUE; return TRUE;
} }
#ifndef _WIN64
BOOLEAN SbieDll_HookWoW64SysCalls(); //---------------------------------------------------------------------------
// Win32_WoW64_GetSysCallNumber
#endif //---------------------------------------------------------------------------
#endif
_FX BOOLEAN Win32_Init(HMODULE hmodule)
{
#ifdef HOOK_WIN32K
// In Windows 10 all Win32k.sys calls are located in win32u.dll
if (Dll_OsBuild < 10041 || !SbieApi_QueryConfBool(NULL, L"EnableWin32kHooks", FALSE))
return TRUE; // just return on older builds
// NoSysCallHooks BEGIN
if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSysCallHooks", FALSE))
return TRUE;
// NoSysCallHooks END
// disable Electron Workaround when we are ready to hook the required win32k syscalls
extern BOOL Dll_ElectronWorkaround;
Dll_ElectronWorkaround = FALSE;
//
// chrome needs for a working GPU acceleration the GdiDdDDI* win32k syscalls to have the right user token
//
WCHAR* cmdline = GetCommandLine();
if ((wcsstr(cmdline, L"--type=gpu-process") != NULL && wcsstr(cmdline, L"--gpu-preferences=") != NULL)
|| SbieDll_GetSettingsForName_bool(NULL, Dll_ImageName, L"AlwaysUseWin32kHooks", FALSE)) {
#ifndef _WIN64 #ifndef _WIN64
if (Dll_IsWow64)
SbieDll_HookWoW64SysCalls();
else
#endif
SbieDll_HookWin32SysCalls(hmodule);
}
#endif
return TRUE;
}
#ifdef HOOK_WIN32K
#ifndef _WIN64
//#include "../../common/wow64ext/wow64ext.h"
DWORD64 __cdecl X64Call(DWORD64 func, int argC, ...);
DWORD64 __cdecl GetModuleHandle64(const wchar_t* lpModuleName);
DWORD64 __cdecl getNTDLL64();
DWORD64 __cdecl GetProcAddress64(DWORD64 hModule, const char* funcName);
SIZE_T __cdecl VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength);
DWORD64 __cdecl VirtualAllocEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
BOOL __cdecl VirtualFreeEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD dwFreeType);
BOOL __cdecl VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect);
BOOL __cdecl ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead);
BOOL __cdecl WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten);
//BOOL __cdecl GetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext);
//BOOL __cdecl SetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext);
VOID __cdecl SetLastErrorFromX64Call(DWORD64 status);
ULONG Win32_WoW64_GetSysCallNumber(DWORD64 pos, UCHAR* dll_data) ULONG Win32_WoW64_GetSysCallNumber(DWORD64 pos, UCHAR* dll_data)
{ {
// 4C 8B D1 - r10,rcx // 4C 8B D1 - r10,rcx
@ -247,13 +188,52 @@ ULONG Win32_WoW64_GetSysCallNumber(DWORD64 pos, UCHAR* dll_data)
if (!(dll_data[pos + 23] == 0xc3)) if (!(dll_data[pos + 23] == 0xc3))
return 0; return 0;
// 0F 1F 84 00 00 00 00 00
// //
return syscall_index; return syscall_index;
} }
_FX BOOLEAN SbieDll_HookWoW64SysCalls()
//---------------------------------------------------------------------------
// SbieDll_HasSysCallHook
//---------------------------------------------------------------------------
_FX BOOLEAN SbieDll_HasSysCallHook(UCHAR* syscall_data, ULONG syscall_index)
{
ULONG *SyscallPtr;
ULONG SyscallNum;
SyscallPtr = (ULONG *)(syscall_data + sizeof(ULONG)); // size of buffer
while (SyscallPtr[0] || SyscallPtr[1]) {
SyscallNum = SyscallPtr[0];
SyscallNum &= 0xFFFF; // clear the not needed param count
if (SyscallNum == syscall_index)
return TRUE;
SyscallPtr += 2;
}
return FALSE;
}
//---------------------------------------------------------------------------
// SbieDll_HookWin32WoW64
//---------------------------------------------------------------------------
//#include "../../common/wow64ext/wow64ext.h"
DWORD64 __cdecl X64Call(DWORD64 func, int argC, ...);
DWORD64 __cdecl GetModuleHandle64(const wchar_t* lpModuleName);
BOOL __cdecl VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect);
BOOL __cdecl ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead);
BOOL __cdecl WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten);
_FX BOOLEAN SbieDll_HookWin32WoW64()
{ {
BOOLEAN ok = FALSE; BOOLEAN ok = FALSE;
UCHAR* dll_data = NULL; UCHAR* dll_data = NULL;
@ -261,20 +241,28 @@ _FX BOOLEAN SbieDll_HookWoW64SysCalls()
DWORD64 BaseAddress = GetModuleHandle64(L"wow64win.dll"); DWORD64 BaseAddress = GetModuleHandle64(L"wow64win.dll");
SIZE_T SizeOfImage = 0x00100000; // 1 MB should be more than enough SIZE_T SizeOfImage = 0x00100000; // 1 MB should be more than enough
if (!BaseAddress) if (!BaseAddress) {
SbieApi_Log(2303, L"win32k, wow64win.dll base not found");
return FALSE; return FALSE;
}
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
if (hProcess == INVALID_HANDLE_VALUE) if (hProcess == INVALID_HANDLE_VALUE) {
SbieApi_Log(2303, L"win32k, can't open process");
return FALSE; return FALSE;
}
dll_data = (UCHAR *)HeapAlloc(GetProcessHeap(), 0, (SIZE_T)SizeOfImage); dll_data = (UCHAR *)HeapAlloc(GetProcessHeap(), 0, (SIZE_T)SizeOfImage);
if (!dll_data) if (!dll_data) {
SbieApi_Log(2303, L"win32k, alloc failed (1)");
goto finish; goto finish;
}
SIZE_T SizeRead; SIZE_T SizeRead;
if (!ReadProcessMemory64(hProcess, (PVOID64)BaseAddress, dll_data, SizeOfImage, &SizeRead)) if (!ReadProcessMemory64(hProcess, (PVOID64)BaseAddress, dll_data, SizeOfImage, &SizeRead)) {
SbieApi_Log(2303, L"win32k, wow64win.dll read failed");
goto finish; goto finish;
}
DWORD64 FuncTable = 0; DWORD64 FuncTable = 0;
@ -285,12 +273,13 @@ _FX BOOLEAN SbieDll_HookWoW64SysCalls()
} }
} }
if (FuncTable == 0) if (FuncTable == 0) {
SbieApi_Log(2303, L"win32k, wow64win.dll sys call table not found");
goto finish; goto finish;
}
DWORD64 SystemServiceAsm; DWORD64 SystemServiceAsm;
UCHAR ZwXxxPtr[16]; UCHAR ZwXxxPtr[16];
ULONG *SyscallPtr;
ULONG SyscallNum; ULONG SyscallNum;
DWORD64 RegionBase; DWORD64 RegionBase;
SIZE_T RegionSize; SIZE_T RegionSize;
@ -300,43 +289,30 @@ _FX BOOLEAN SbieDll_HookWoW64SysCalls()
SystemServiceAsm = data->pSystemService; SystemServiceAsm = data->pSystemService;
syscall_data = (UCHAR *)HeapAlloc(GetProcessHeap(), 0, 16384); // enough room for over 2000 syscalls syscall_data = (UCHAR *)HeapAlloc(GetProcessHeap(), 0, 16384); // enough room for over 2000 syscalls
if (!syscall_data) if (!syscall_data) {
SbieApi_Log(2303, L"win32k, alloc failed (2)");
goto finish; goto finish;
}
if (!NT_SUCCESS(SbieApi_Call(API_QUERY_SYSCALLS, 2, (ULONG_PTR)syscall_data, 1))) { if (!NT_SUCCESS(SbieApi_Call(API_QUERY_SYSCALLS, 2, (ULONG_PTR)syscall_data, 1))) {
HeapFree(GetProcessHeap(), 0, syscall_data); SbieApi_Log(2303, L"win32k, syscall query failed");
goto finish; goto finish;
} }
for (DWORD64 pos = FuncTable; pos < SizeRead - 0x20; ) for (DWORD64 pos = FuncTable; pos < SizeRead - 0x20; )
{ {
ULONG syscall_index = Win32_WoW64_GetSysCallNumber(pos, dll_data); SyscallNum = Win32_WoW64_GetSysCallNumber(pos, dll_data);
if (syscall_index) if (SyscallNum)
{
if(SbieDll_HasSysCallHook(syscall_data, SyscallNum))
{ {
SyscallPtr = (ULONG *)(syscall_data + sizeof(ULONG)); // size of buffer
while (SyscallPtr[0] || SyscallPtr[1]) {
SyscallNum = SyscallPtr[0];
SyscallNum &= 0xFFFF; // clear the not needed param count
if (SyscallNum == syscall_index){
RegionBase = BaseAddress + pos; RegionBase = BaseAddress + pos;
// _WIN64
RegionSize = 14; RegionSize = 14;
// ! _WIN64
if (!ReadProcessMemory64(hProcess, RegionBase, ZwXxxPtr, RegionSize, &SizeRead))
goto finish;
// //
// overwrite the ZwXxx export to call our SystemServiceAsm, // prepare call to call our SystemServiceAsm
// and then restore the original page protection
// //
// _WIN64
ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber
ZwXxxPtr[1] = 0xC7; ZwXxxPtr[1] = 0xC7;
ZwXxxPtr[2] = 0xC2; ZwXxxPtr[2] = 0xC2;
@ -345,7 +321,7 @@ _FX BOOLEAN SbieDll_HookWoW64SysCalls()
if (data->flags.is_win10) { if (data->flags.is_win10) {
ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm
ZwXxxPtr[8] = 0xE9; // jmp SystemServiceAsm ZwXxxPtr[8] = 0xE9;
*(ULONG *)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (RegionBase + 13)); *(ULONG *)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (RegionBase + 13));
} }
else { else {
@ -359,20 +335,27 @@ _FX BOOLEAN SbieDll_HookWoW64SysCalls()
*(ULONG *)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)SystemServiceAsm; *(ULONG *)&ZwXxxPtr[8] = (ULONG)(ULONG_PTR)SystemServiceAsm;
*(USHORT *)&ZwXxxPtr[12] = 0xE0FF; // jmp rax *(USHORT *)&ZwXxxPtr[12] = 0xE0FF; // jmp rax
} }
// ! _WIN64
if (!VirtualProtectEx64(hProcess, RegionBase, RegionSize, PAGE_EXECUTE_READWRITE, &OldProtect)) //
goto finish; // overwrite the ZwXxx export to call our SystemServiceAsm,
// and then restore the original page protection
//
if (!WriteProcessMemory64(hProcess, RegionBase, ZwXxxPtr, RegionSize, &SizeRead)) if (!VirtualProtectEx64(hProcess, RegionBase, RegionSize, PAGE_EXECUTE_READWRITE, &OldProtect)) {
goto finish; SbieApi_Log(2303, L"win32k %d (1)", SyscallNum);
if (!VirtualProtectEx64(hProcess, RegionBase, RegionSize, OldProtect, &OldProtect))
goto finish; goto finish;
} }
SyscallPtr += 2; if (!WriteProcessMemory64(hProcess, RegionBase, ZwXxxPtr, RegionSize, &SizeRead)) {
SbieApi_Log(2303, L"win32k %d (2)", SyscallNum);
goto finish;
}
if (!VirtualProtectEx64(hProcess, RegionBase, RegionSize, OldProtect, &OldProtect)) {
SbieApi_Log(2303, L"win32k %d (3)", SyscallNum);
goto finish;
}
} }
pos += 0x20; pos += 0x20;
@ -385,7 +368,6 @@ _FX BOOLEAN SbieDll_HookWoW64SysCalls()
pos++; pos++;
} }
finish: finish:
if(syscall_data) if(syscall_data)
@ -398,7 +380,44 @@ finish:
return ok; return ok;
} }
#endif #endif
//---------------------------------------------------------------------------
// Win32_Init
//---------------------------------------------------------------------------
_FX BOOLEAN Win32_Init(HMODULE hmodule)
{
// In Windows 10 all Win32k.sys calls are located in win32u.dll
if (Dll_OsBuild < 10041 || !SbieApi_QueryConfBool(NULL, L"EnableWin32kHooks", FALSE))
return TRUE; // just return on older builds
// NoSysCallHooks BEGIN
if ((Dll_ProcessFlags & SBIE_FLAG_APP_COMPARTMENT) != 0 || SbieApi_QueryConfBool(NULL, L"NoSysCallHooks", FALSE))
return TRUE;
// NoSysCallHooks END
// disable Electron Workaround when we are ready to hook the required win32k syscalls
extern BOOL Dll_ElectronWorkaround;
Dll_ElectronWorkaround = FALSE;
//
// chrome needs for a working GPU acceleration the GdiDdDDI* win32k syscalls to have the right user token
//
WCHAR* cmdline = GetCommandLine();
if ((wcsstr(cmdline, L"--type=gpu-process") != NULL && wcsstr(cmdline, L"--gpu-preferences=") != NULL)
|| SbieDll_GetSettingsForName_bool(NULL, Dll_ImageName, L"AlwaysUseWin32kHooks", FALSE)) {
#ifndef _WIN64
if (Dll_IsWow64)
SbieDll_HookWin32WoW64(); // WoW64 hooks
else
#endif #endif
SbieDll_HookWin32SysCalls(hmodule); // Native x86/x64 hooks
}
return TRUE;
}

View File

@ -130,7 +130,7 @@ _FX void *SbieDll_Hook(
// (this helps to co-exist with Cisco Security Agent) // (this helps to co-exist with Cisco Security Agent)
// //
if (*(UCHAR *)SourceFunc == 0xEB) { if (*(UCHAR *)SourceFunc == 0xEB) { // jmp xx;
signed char offset = *((signed char *)SourceFunc + 1); signed char offset = *((signed char *)SourceFunc + 1);
SourceFunc = (UCHAR *)SourceFunc + offset + 2; SourceFunc = (UCHAR *)SourceFunc + offset + 2;
} }
@ -142,7 +142,7 @@ _FX void *SbieDll_Hook(
// otherwise (for 32-bit code) just replace the jump target // otherwise (for 32-bit code) just replace the jump target
// //
while (*(UCHAR *)SourceFunc == 0xE9) { while (*(UCHAR *)SourceFunc == 0xE9) { // jmp xx xx xx xx;
diff = *(LONG *)((ULONG_PTR)SourceFunc + 1); diff = *(LONG *)((ULONG_PTR)SourceFunc + 1);
target = (ULONG_PTR)SourceFunc + diff + 5; target = (ULONG_PTR)SourceFunc + diff + 5;
@ -192,15 +192,15 @@ skip_e9_rewrite: ;
// can process it // can process it
// //
if (*(USHORT *)SourceFunc == 0xE990) { if (*(USHORT *)SourceFunc == 0xE990) { // nop; jmp xx xx xx xx;
diff = *(LONG *)((ULONG_PTR)SourceFunc + 2); diff = *(LONG *)((ULONG_PTR)SourceFunc + 2);
target = (ULONG_PTR)SourceFunc + diff + 6; target = (ULONG_PTR)SourceFunc + diff + 6;
if (*(USHORT *)target == 0x25FF) if (*(USHORT *)target == 0x25FF) // jmp QWORD PTR [rip+xx xx xx xx];
SourceFunc = (void *)target; SourceFunc = (void *)target;
} }
// //
// DX: this simplification fails for delay loaded libraries, see coments about SetSecurityInfo, // DX: this simplification fails for delay loaded libraries, see comments about SetSecurityInfo,
// resulting in an endless loop, so just dont do that // resulting in an endless loop, so just dont do that
// //
@ -211,13 +211,13 @@ skip_e9_rewrite: ;
// 12 bytes. // 12 bytes.
// //
if (*(UCHAR *)SourceFunc == 0x48 && if (*(UCHAR *)SourceFunc == 0x48 && // rex.W
*(USHORT *)((UCHAR *)SourceFunc + 1) == 0x25FF) { *(USHORT *)((UCHAR *)SourceFunc + 1) == 0x25FF) { // jmp QWORD PTR [rip+xx xx xx xx];
// 4825FF is same as 25FF // 48 FF 25 is same as FF 25
SourceFunc = (UCHAR *)SourceFunc + 1; SourceFunc = (UCHAR *)SourceFunc + 1;
} }
if (*(USHORT *)SourceFunc == 0x25FF) { if (*(USHORT *)SourceFunc == 0x25FF) { // jmp QWORD PTR [rip+xx xx xx xx];
void *orig_addr; void *orig_addr;
/* /*
@ -254,7 +254,7 @@ skip_e9_rewrite: ;
#ifdef _WIN64 #ifdef _WIN64
if (*(USHORT *)SourceFunc == 0x15FF) { if (*(USHORT *)SourceFunc == 0x15FF) { // call QWORD PTR [rip+xx xx xx xx];
// //
// the call instruction pushes a qword into the stack, we need // the call instruction pushes a qword into the stack, we need
@ -312,8 +312,8 @@ skip_e9_rewrite: ;
return NULL; return NULL;
} }
ULONG ByteCount = *(ULONG*)(tramp + 80); //ULONG ByteCount = *(ULONG*)(tramp + 80);
ULONG UsedCount = 0; //ULONG UsedCount = 0;
// //
// create the detour // create the detour
@ -351,22 +351,20 @@ skip_e9_rewrite: ;
OutputDebugStringA(buffer); OutputDebugStringA(buffer);
*/ */
if (Dll_Windows >= 10) { if (Dll_Windows >= 10) {
func[0] = 0x48; // 32bit relative JMP DetourFunc func[0] = 0x48; // 32bit relative rex.W JMP DetourFunc
func[1] = 0xE9; // 32bit relative JMP DetourFunc func[1] = 0xE9;
*(ULONG *)(&func[2]) = (ULONG)diff; *(ULONG *)(&func[2]) = (ULONG)diff;
UsedCount = 1 + 1 + 4; //UsedCount = 1 + 1 + 4;
} }
else { else {
func[0] = 0xE9; // 32bit relative JMP DetourFunc func[0] = 0xE9; // 32bit relative JMP DetourFunc
*(ULONG *)(&func[1]) = (ULONG)diff; *(ULONG *)(&func[1]) = (ULONG)diff;
UsedCount = 1 + 4; //UsedCount = 1 + 4;
} }
} }
else { else {
BOOLEAN hookset = FALSE; BOOLEAN hookset = FALSE;
BOOLEAN defaultRange = FALSE; BOOLEAN defaultRange = FALSE;
int i; int i;
@ -377,12 +375,12 @@ skip_e9_rewrite: ;
//default step size //default step size
for (i = 0; i < NUM_VTABLES && !hookset; i++, ptrVTable++) { for (i = 0; i < NUM_VTABLES && !hookset; i++, ptrVTable++) {
if (!ptrVTable->offset) { if (!ptrVTable->offset) { // if the vtable is not yet initialized initialize it
ULONG_PTR tempAddr; ULONG_PTR tempAddr;
ULONG_PTR step = 0x20000;// + VTABLE_SIZE; ULONG_PTR step = 0x20000;// + VTABLE_SIZE;
ULONG_PTR max_attempts = 0x4000000 / step; ULONG_PTR max_attempts = 0x4000000 / step;
// optimization for windows 7 and low memory DLL's
// optimization for windows 7 and low memory DLL's
if ((ULONG_PTR)func < 0x80000000 && ((ULONG_PTR)func > 0x4000000)) { if ((ULONG_PTR)func < 0x80000000 && ((ULONG_PTR)func > 0x4000000)) {
step = 0x200000; step = 0x200000;
} }
@ -414,7 +412,7 @@ skip_e9_rewrite: ;
ptrVTable->index = 0; ptrVTable->index = 0;
ptrVTable->maxEntries = VTABLE_SIZE / sizeof(void *); ptrVTable->maxEntries = VTABLE_SIZE / sizeof(void *);
} }
if (ptrVTable->offset) { if (ptrVTable->offset) { // check if we have an nitialized vtable
target = (ULONG_PTR)&func[6]; target = (ULONG_PTR)&func[6];
diff = (ULONG_PTR) &((ULONG_PTR *)ptrVTable->offset)[ptrVTable->index]; diff = (ULONG_PTR) &((ULONG_PTR *)ptrVTable->offset)[ptrVTable->index];
diff = diff - target; diff = diff - target;
@ -424,14 +422,14 @@ skip_e9_rewrite: ;
// is DetourFunc in 32bit jump range // is DetourFunc in 32bit jump range
if (delta < 0x80000000 && ptrVTable->index <= ptrVTable->maxEntries) { if (delta < 0x80000000 && ptrVTable->index <= ptrVTable->maxEntries) {
((ULONG_PTR *)ptrVTable->offset)[ptrVTable->index] = (ULONG_PTR)DetourFunc; ((ULONG_PTR *)ptrVTable->offset)[ptrVTable->index] = (ULONG_PTR)DetourFunc;
*(USHORT *)&func[0] = 0x25ff; *(USHORT *)&func[0] = 0x25ff; // jmp QWORD PTR [rip+diff];
*(ULONG *)&func[2] = (ULONG)diff; *(ULONG *)&func[2] = (ULONG)diff;
UsedCount = 2 + 4; //UsedCount = 2 + 4;
ptrVTable->index++; ptrVTable->index++;
hookset = TRUE; hookset = TRUE;
} }
} }
else { else { // fail and disable vtable if it could not be initialized
bVTableEable = FALSE; bVTableEable = FALSE;
SbieApi_Log(2303, _fmt1, SourceFuncName, 888); SbieApi_Log(2303, _fmt1, SourceFuncName, 888);
LeaveCriticalSection(&VT_CriticalSection); LeaveCriticalSection(&VT_CriticalSection);
@ -529,9 +527,10 @@ ULONGLONG * SbieDll_findChromeTarget(unsigned char* addr)
_FX void *SbieDll_Hook_CheckChromeHook(void *SourceFunc) _FX void *SbieDll_Hook_CheckChromeHook(void *SourceFunc)
{ {
#ifndef _WIN64 if (!SourceFunc)
return NULL;
UCHAR *func = (UCHAR *)SourceFunc; UCHAR *func = (UCHAR *)SourceFunc;
#ifndef _WIN64
if (func[0] == 0xB8 && // mov eax,? if (func[0] == 0xB8 && // mov eax,?
func[5] == 0xBA && // mov edx,? func[5] == 0xBA && // mov edx,?
*(USHORT *)&func[10] == 0xE2FF) // jmp edx *(USHORT *)&func[10] == 0xE2FF) // jmp edx
@ -551,10 +550,7 @@ _FX void *SbieDll_Hook_CheckChromeHook(void *SourceFunc)
} }
} }
#else if #else if
UCHAR *func = (UCHAR *)SourceFunc;
ULONGLONG *chrome64Target = NULL; ULONGLONG *chrome64Target = NULL;
if (!SourceFunc)
return NULL;
if (func[0] == 0x50 && //push rax if (func[0] == 0x50 && //push rax
func[1] == 0x48 && //mov rax,? func[1] == 0x48 && //mov rax,?
@ -576,7 +572,8 @@ _FX void *SbieDll_Hook_CheckChromeHook(void *SourceFunc)
} }
/*sboxie 64bit jtable hook signature */ /*sboxie 64bit jtable hook signature */
/* // use this to hook jtable location (useful for debugging) /* // use this to hook jtable location (useful for debugging)
else if(func[0] == 0x51 && func[1] == 0x48 && func[2] == 0xb8 ) { //else if(func[0] == 0x51 && func[1] == 0x48 && func[2] == 0xb8 ) {
else if(func[0] == 0x90 && func[1] == 0x48 && func[2] == 0xb8 ) {
long long addr; long long addr;
addr = (ULONG_PTR) *(ULONGLONG **)&func[3] ; addr = (ULONG_PTR) *(ULONGLONG **)&func[3] ;
SourceFunc = (void *) addr; SourceFunc = (void *) addr;

View File

@ -55,7 +55,7 @@ typedef struct _MY_TARGETS {
SBIEDLL_EXPORT HANDLE SbieDll_InjectLow_SendHandle(HANDLE hProcess); SBIEDLL_EXPORT HANDLE SbieDll_InjectLow_SendHandle(HANDLE hProcess);
SBIEDLL_EXPORT void *SbieDll_InjectLow_CopyCode( SBIEDLL_EXPORT void *SbieDll_InjectLow_CopyCode(
HANDLE hProcess, BOOLEAN iswow64, UCHAR *code, ULONG code_len); HANDLE hProcess, SIZE_T lowLevel_size, UCHAR *code, ULONG code_len);
SBIEDLL_EXPORT BOOLEAN SbieDll_InjectLow_BuildTramp( SBIEDLL_EXPORT BOOLEAN SbieDll_InjectLow_BuildTramp(
BOOLEAN long_diff, UCHAR *code, ULONG_PTR addr); BOOLEAN long_diff, UCHAR *code, ULONG_PTR addr);
SBIEDLL_EXPORT void *SbieDll_InjectLow_CopySyscalls(HANDLE hProcess); SBIEDLL_EXPORT void *SbieDll_InjectLow_CopySyscalls(HANDLE hProcess);
@ -519,7 +519,16 @@ _FX ULONG SbieDll_InjectLow(HANDLE hProcess, ULONG init_flags, BOOLEAN dup_drv_h
lowdata.flags.is_win10 = 1; lowdata.flags.is_win10 = 1;
} }
void *remote_addr = SbieDll_InjectLow_CopyCode(hProcess, lowdata.flags.is_wow64 == 1, lowdata.LdrInitializeThunk_tramp, sizeof(lowdata.LdrInitializeThunk_tramp)); SIZE_T lowLevel_size;
#ifdef _WIN64
BOOLEAN use_jump_Table = FALSE;
if(use_jump_Table)
lowLevel_size = m_sbielow_len + sizeof(SBIELOW_J_TABLE) + 0x400;
else
#endif
lowLevel_size = m_sbielow_len;
void *remote_addr = SbieDll_InjectLow_CopyCode(hProcess, lowLevel_size, lowdata.LdrInitializeThunk_tramp, sizeof(lowdata.LdrInitializeThunk_tramp));
if (!remote_addr) { if (!remote_addr) {
errlvl = 0x33; errlvl = 0x33;
goto finish; goto finish;
@ -570,6 +579,7 @@ _FX ULONG SbieDll_InjectLow(HANDLE hProcess, ULONG init_flags, BOOLEAN dup_drv_h
// //
#ifdef _WIN64 #ifdef _WIN64
if(use_jump_Table)
lowdata.Sbie64bitJumpTable = (SBIELOW_J_TABLE *)((ULONG_PTR)remote_addr + m_sbielow_len + 0x400); //(0x400 - (m_sbielow_len & 0x3ff))+ m_sbielow_len; lowdata.Sbie64bitJumpTable = (SBIELOW_J_TABLE *)((ULONG_PTR)remote_addr + m_sbielow_len + 0x400); //(0x400 - (m_sbielow_len & 0x3ff))+ m_sbielow_len;
#endif #endif
@ -693,16 +703,10 @@ _FX HANDLE SbieDll_InjectLow_SendHandle(HANDLE hProcess)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
_FX void *SbieDll_InjectLow_CopyCode(HANDLE hProcess, BOOLEAN iswow64, UCHAR *code, ULONG code_len) _FX void *SbieDll_InjectLow_CopyCode(HANDLE hProcess, SIZE_T lowLevel_size, UCHAR *code, ULONG code_len)
{ {
SIZE_T region_size; SIZE_T region_size;
SIZE_T lowLevel_size;
void *remote_addr = NULL; 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; region_size = lowLevel_size;
//for (int i = 8; !remote_addr && i > 2; i--) { //for (int i = 8; !remote_addr && i > 2; i--) {
@ -1097,7 +1101,7 @@ _FX BOOLEAN SbieDll_InjectLow_WriteJump(HANDLE hProcess, void *remote_addr, BOOL
// //
UCHAR jump_code[16]; UCHAR jump_code[16];
void * detour = (void *)remote_addr; void * detour = (void *)remote_addr;
UCHAR *func = (UCHAR *)((ULONG_PTR)m_LdrInitializeThunk);; UCHAR *func = (UCHAR *)((ULONG_PTR)m_LdrInitializeThunk);
SIZE_T len1; SIZE_T len1;
BOOL myVM; BOOL myVM;
ULONG myProtect; ULONG myProtect;

View File

@ -208,7 +208,7 @@ _FX void WaitForDebugger(SBIELOW_DATA *data)
ULONGLONG * findChromeTarget(unsigned char* addr) ULONGLONG * findChromeTarget(unsigned char* addr)
{ {
int i = 0; int i = 0;
ULONGLONG target = 0; ULONGLONG target;
ULONG_PTR * ChromeTarget = NULL; ULONG_PTR * ChromeTarget = NULL;
if (!addr) return NULL; if (!addr) return NULL;
//Look for mov rcx,[target 4 byte offset] or in some cases mov rax,[target 4 byte offset] //Look for mov rcx,[target 4 byte offset] or in some cases mov rax,[target 4 byte offset]
@ -234,6 +234,55 @@ ULONGLONG * findChromeTarget(unsigned char* addr)
} }
#endif #endif
void *Hook_CheckChromeHook(void *SourceFunc)
{
if (!SourceFunc)
return NULL;
UCHAR *ZwXxxPtr = (UCHAR *)SourceFunc;
#ifndef _WIN64 //if not _WIN64
if (ZwXxxPtr[0] == 0xB8 && // mov eax,?
ZwXxxPtr[5] == 0xBA && // mov edx,?
*(USHORT *)&ZwXxxPtr[10] == 0xE2FF) // jmp edx
{
ULONG i = 0;
ULONG *longs = *(ULONG **)&ZwXxxPtr[6];
for (i = 0; i < 20; i++, longs++)
{
if (longs[0] == 0x5208EC83 && longs[1] == 0x0C24548B &&
longs[2] == 0x08245489 && longs[3] == 0x0C2444C7 &&
longs[5] == 0x042444C7)
{
ZwXxxPtr = (UCHAR *)longs[4];
break;
}
}
}
#else // _WIN64
ULONGLONG *chrome64Target = NULL;
if (ZwXxxPtr[0] == 0x50 && //push rax
ZwXxxPtr[1] == 0x48 && //mov rax,?
ZwXxxPtr[2] == 0xb8) {
ULONGLONG* longlongs = *(ULONGLONG**)&ZwXxxPtr[3];
chrome64Target = findChromeTarget((unsigned char*)longlongs);
}
// Chrome 49+ 64bit hook
// mov rax, <target>
// jmp rax
else if (ZwXxxPtr[0] == 0x48 && //mov rax,<target>
ZwXxxPtr[1] == 0xb8 &&
*(USHORT*)&ZwXxxPtr[10] == 0xe0ff)/* jmp rax */ {
ULONGLONG* longlongs = *(ULONGLONG**)&ZwXxxPtr[2];
chrome64Target = findChromeTarget((unsigned char*)longlongs);
}
if (chrome64Target != NULL) {
ZwXxxPtr = (UCHAR *)chrome64Target;
}
#endif
return ZwXxxPtr;
}
_FX void PrepSyscalls(SBIELOW_DATA *data, void * SystemService) _FX void PrepSyscalls(SBIELOW_DATA *data, void * SystemService)
{ {
UCHAR *SystemServiceAsm; UCHAR *SystemServiceAsm;
@ -278,9 +327,6 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService)
void *RegionBase; void *RegionBase;
SIZE_T RegionSize; SIZE_T RegionSize;
ULONG OldProtect; ULONG OldProtect;
#ifdef _WIN64
ULONGLONG *chrome64Target = NULL;
#endif
SystemServiceAsm = (UCHAR *)SystemService; SystemServiceAsm = (UCHAR *)SystemService;
@ -310,54 +356,16 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService)
// saved by chrome, rather than the chrome hook itself (32-bit only) // saved by chrome, rather than the chrome hook itself (32-bit only)
// //
#ifndef _WIN64 //if not _WIN64 ZwXxxPtr = Hook_CheckChromeHook(ZwXxxPtr);
if (ZwXxxPtr[0] == 0xB8 && // mov eax,?
ZwXxxPtr[5] == 0xBA && // mov edx,?
*(USHORT *)&ZwXxxPtr[10] == 0xE2FF) // jmp edx
{
ULONG i = 0;
ULONG *longs = *(ULONG **)&ZwXxxPtr[6];
for (i = 0; i < 20; i++, longs++)
{
if (longs[0] == 0x5208EC83 && longs[1] == 0x0C24548B &&
longs[2] == 0x08245489 && longs[3] == 0x0C2444C7 &&
longs[5] == 0x042444C7)
{
ZwXxxPtr = (UCHAR *)longs[4];
break;
}
}
}
#else // _WIN64
if (ZwXxxPtr[0] == 0x50 && //push rax
ZwXxxPtr[1] == 0x48 && //mov rax,?
ZwXxxPtr[2] == 0xb8) {
ULONGLONG *longlongs = *(ULONGLONG **)&ZwXxxPtr[3];
chrome64Target = findChromeTarget((unsigned char *)longlongs);
}
// Chrome 49+ 64bit hook
// mov rax, <target>
// jmp rax
else if (ZwXxxPtr[0] == 0x48 && //mov rax,<target>
ZwXxxPtr[1] == 0xb8 &&
*(USHORT *)&ZwXxxPtr[10] == 0xe0ff)/* jmp rax */ {
ULONGLONG *longlongs = *(ULONGLONG **)&ZwXxxPtr[2];
chrome64Target = findChromeTarget((unsigned char *)longlongs);
}
#endif
// //
// make the syscall address writable // make the syscall address writable
// //
RegionBase = ZwXxxPtr; RegionBase = ZwXxxPtr;
#ifdef _WIN64 #ifdef _WIN64
RegionSize = 14; RegionSize = data->Sbie64bitJumpTable ? 13 : 14; // 16;
if (!chrome64Target) {
chrome64Target = (ULONG_PTR*)ZwXxxPtr;
}
#else ! _WIN64 #else ! _WIN64
RegionSize = 10; RegionSize = 10;
#endif _WIN64 #endif _WIN64
@ -371,21 +379,18 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService)
// and then restore the original page protection // and then restore the original page protection
// //
SyscallNum = SyscallPtr[0];
#ifdef _WIN64
SyscallNum &= 0xFFFF; // clear the not needed param count
if (chrome64Target && data->Sbie64bitJumpTable) {
RegionSize = 16;
ZwXxxPtr = (UCHAR *)chrome64Target;
RegionBase = ZwXxxPtr;
SBIELOW_CALL(NtProtectVirtualMemory)( SBIELOW_CALL(NtProtectVirtualMemory)(
NtCurrentProcess(), &RegionBase, &RegionSize, NtCurrentProcess(), &RegionBase, &RegionSize,
PAGE_EXECUTE_READWRITE, &OldProtect); PAGE_EXECUTE_READWRITE, &OldProtect);
unsigned char * jTableTarget = (unsigned char *)&data->Sbie64bitJumpTable->entry[SyscallNum & 0x3ff]; SyscallNum = SyscallPtr[0];
#ifdef _WIN64
if (data->Sbie64bitJumpTable) {
// bytes overwriten /*16*/ 13;
unsigned char * jTableTarget = (unsigned char *)&data->Sbie64bitJumpTable->entry[SyscallNum & 0x3ff]; // jump table is sized for up to 1024 entries
// write new patch for jump table // write new patch for jump table
// The jTable is now injected in the same memory module with lowlevel; no need for a 64 bit long jump // The jTable is now injected in the same memory module with lowlevel; no need for a 64 bit long jump
// mov r10, <4 byte SyscallNum> // mov r10, <4 byte SyscallNum>
@ -427,16 +432,9 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService)
// jmp rax // jmp rax
ZwXxxPtr[11] = 0xFF; ZwXxxPtr[11] = 0xFF;
ZwXxxPtr[12] = 0xE0; ZwXxxPtr[12] = 0xE0;
chrome64Target = NULL;
} }
else else {
{ // bytes overwriten 14;
RegionBase = ZwXxxPtr;
SBIELOW_CALL(NtProtectVirtualMemory)(
NtCurrentProcess(), &RegionBase, &RegionSize,
PAGE_EXECUTE_READWRITE, &OldProtect);
ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber ZwXxxPtr[0] = 0x49; // mov r10, SyscallNumber
ZwXxxPtr[1] = 0xC7; ZwXxxPtr[1] = 0xC7;
@ -446,7 +444,7 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService)
if (data->flags.is_win10) { if (data->flags.is_win10) {
ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm ZwXxxPtr[7] = 0x48; // jmp SystemServiceAsm
ZwXxxPtr[8] = 0xE9; // jmp SystemServiceAsm ZwXxxPtr[8] = 0xE9;
*(ULONG *)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (ZwXxxPtr + 13)); *(ULONG *)&ZwXxxPtr[9] = (ULONG)(ULONG_PTR)(SystemServiceAsm - (ZwXxxPtr + 13));
} }
else { else {
@ -462,12 +460,9 @@ _FX void InitSyscalls(SBIELOW_DATA *data, void * SystemService)
} }
} }
#else ! _WIN64 #else ! _WIN64
// bytes overwriten 10;
SBIELOW_CALL(NtProtectVirtualMemory)( ZwXxxPtr[0] = 0xB8; // mov eax, SyscallNumber, with param count in the highest byte
NtCurrentProcess(), &RegionBase, &RegionSize,
PAGE_EXECUTE_READWRITE, &OldProtect);
ZwXxxPtr[0] = 0xB8; // mov eax, SyscallNumber
*(ULONG *)&ZwXxxPtr[1] = SyscallNum; *(ULONG *)&ZwXxxPtr[1] = SyscallNum;
ZwXxxPtr[5] = 0xE9; // jmp SystemServiceAsm ZwXxxPtr[5] = 0xE9; // jmp SystemServiceAsm
*(ULONG *)&ZwXxxPtr[6] = *(ULONG *)&ZwXxxPtr[6] =

View File

@ -88,7 +88,7 @@ BEGIN
BLOCK "0c0704b0" BLOCK "0c0704b0"
BEGIN BEGIN
VALUE "CompanyName", MY_COMPANY_NAME_STRING VALUE "CompanyName", MY_COMPANY_NAME_STRING
VALUE "FileDescription", "SandBox Manager" VALUE "FileDescription", "SandBoxie Manager"
VALUE "FileVersion", VERSION_STR VALUE "FileVersion", VERSION_STR
VALUE "InternalName", "SandMan.exe" VALUE "InternalName", "SandMan.exe"
VALUE "LegalCopyright", MY_COPYRIGHT_STRING VALUE "LegalCopyright", MY_COPYRIGHT_STRING

View File

@ -10,10 +10,15 @@
#define STR(X) STR2(X) #define STR(X) STR2(X)
#endif #endif
#define VERSION_BIN VERSION_MJR,VERSION_MIN,VERSION_REV,VERSION_UPD #if VERSION_UPD > 0
#define VERSION_STR STR(VERSION_MJR.VERSION_MIN.VERSION_REV.VERSION_UPD) #define VERSION_BIN VERSION_MJR,VERSION_MIN,VERSION_REV,VERSION_UPD
#define VERSION_STR STR(VERSION_MJR.VERSION_MIN.VERSION_REV.VERSION_UPD)
#else
#define VERSION_BIN VERSION_MJR,VERSION_MIN,VERSION_REV
#define VERSION_STR STR(VERSION_MJR.VERSION_MIN.VERSION_REV)
#endif
#define MY_PRODUCT_NAME_STRING "Sandboxie-Plus" #define MY_PRODUCT_NAME_STRING "Sandboxie-Plus"
#define MY_COMPANY_NAME_STRING "sandboxie-plus.com" #define MY_COMPANY_NAME_STRING "sandboxie-plus.com"
#define MY_COPYRIGHT_STRING "Copyright (C) 2020-2021 by David Xanatos (xanasoft.com)" #define MY_COPYRIGHT_STRING "Copyright (C) 2020-2022 by David Xanatos (xanasoft.com)"