Changeset 52943 in vbox
- Timestamp:
- Oct 4, 2014 1:54:58 AM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 96383
- Location:
- trunk
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/nt/nt.h
r52941 r52943 1772 1772 NTSYSAPI NTSTATUS NTAPI NtQuerySecurityObject(HANDLE, ULONG, PSECURITY_DESCRIPTOR, ULONG, PULONG); 1773 1773 1774 #ifdef IPRT_NT_USE_WINTERNL 1775 typedef enum _EVENT_TYPE 1776 { 1777 /* Manual reset event. */ 1778 NotificationEvent = 0, 1779 /* Automaitc reset event. */ 1780 SynchronizationEvent 1781 } EVENT_TYPE; 1782 #endif 1783 NTSYSAPI NTSTATUS NTAPI NtCreateEvent(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, EVENT_TYPE, BOOLEAN); 1784 NTSYSAPI NTSTATUS NTAPI NtOpenEvent(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); 1785 NTSYSAPI NTSTATUS NTAPI NtClearEvent(HANDLE); 1786 NTSYSAPI NTSTATUS NTAPI NtResetEvent(HANDLE, PULONG); 1787 NTSYSAPI NTSTATUS NTAPI NtSetEvent(HANDLE, PULONG); 1788 typedef enum _EVENT_INFORMATION_CLASS 1789 { 1790 EventBasicInformation = 0 1791 } EVENT_INFORMATION_CLASS; 1792 /** Data returned by NtQueryEvent + EventBasicInformation. */ 1793 typedef struct EVENT_BASIC_INFORMATION 1794 { 1795 EVENT_TYPE EventType; 1796 ULONG EventState; 1797 } EVENT_BASIC_INFORMATION; 1798 typedef EVENT_BASIC_INFORMATION *PEVENT_BASIC_INFORMATION; 1799 NTSYSAPI NTSTATUS NTAPI NtQueryEvent(HANDLE, EVENT_INFORMATION_CLASS, PVOID, ULONG, PULONG); 1774 1800 1775 1801 #ifdef IPRT_NT_USE_WINTERNL -
trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h
r52941 r52943 313 313 { 314 314 SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED = 0, 315 SUPR3HARDENEDMAINSTATE_WIN_VM_INIT_CALLED, 316 SUPR3HARDENEDMAINSTATE_WIN_EARLY_IMPORTS_RESOLVED, 317 SUPR3HARDENEDMAINSTATE_WIN_EARLY_DEVICE_OPENED, 315 318 SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED, 316 319 SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED, 317 320 SUPR3HARDENEDMAINSTATE_WIN_VERSION_INITIALIZED, 318 SUPR3HARDENEDMAINSTATE_VERIFY_TRUST_READY, 321 SUPR3HARDENEDMAINSTATE_WIN_VERIFY_TRUST_READY, 322 SUPR3HARDENEDMAINSTATE_HARDENED_MAIN_CALLED, 319 323 SUPR3HARDENEDMAINSTATE_INIT_RUNTIME, 320 324 SUPR3HARDENEDMAINSTATE_GET_TRUSTED_MAIN, 321 325 SUPR3HARDENEDMAINSTATE_CALLED_TRUSTED_MAIN, 322 SUPR3HARDENEDMAINSTATE_END 326 SUPR3HARDENEDMAINSTATE_END, 327 SUPR3HARDENEDMAINSTATE_32BIT_HACK = 0x7fffffff 323 328 } SUPR3HARDENEDMAINSTATE; 324 329 … … 336 341 #endif 337 342 extern DECLHIDDEN(SUPR3HARDENEDMAINSTATE) g_enmSupR3HardenedMainState; 343 #ifdef RT_OS_WINDOWS 344 extern DECLHIDDEN(bool) g_fSupEarlyVmProcessInit; 345 #endif 338 346 339 347 … … 437 445 438 446 #ifdef RT_OS_WINDOWS 439 DECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags );447 DECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags, bool fAvastKludge); 440 448 DECLHIDDEN(void) supR3HardenedWinInitVersion(void); 441 449 DECLHIDDEN(void) supR3HardenedWinInitImports(void); 450 DECLHIDDEN(void) supR3HardenedWinInitImportsEarly(uintptr_t uNtDllAddr); 442 451 DECLHIDDEN(PFNRT) supR3HardenedWinGetRealDllSymbol(const char *pszDll, const char *pszProcedure); 443 452 DECLHIDDEN(void) supR3HardenedWinVerifyProcess(void); … … 456 465 # endif 457 466 DECLHIDDEN(void) supR3HardenedWinCompactHeaps(void); 467 DECLHIDDEN(void) supR3HardenedMainOpenDevice(void); 468 DECLHIDDEN(void) supR3HardenedWinReportErrorToParent(int rc, const char *pszFormat, va_list va); 458 469 #endif 459 470 -
trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
r52941 r52943 159 159 /** The current SUPR3HardenedMain state / location. */ 160 160 SUPR3HARDENEDMAINSTATE g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED; 161 AssertCompileSize(g_enmSupR3HardenedMainState, sizeof(uint32_t)); 161 162 162 163 … … 253 254 if (hStdOut != NULL) 254 255 { 255 # if 0 /* Windows 7 and earlier uses fake handles, with the last two bits set ((hStdOut & 3) == 3). */ 256 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 257 NtWriteFile(hStdOut, NULL /*Event*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/, 258 &Ios, (PVOID)pch, (ULONG)cch, NULL /*ByteOffset*/, NULL /*Key*/); 259 # else 260 DWORD cbWritten; 261 WriteFile(hStdOut, pch, (DWORD)cch, &cbWritten, NULL); 262 # endif 256 if (g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) 257 { 258 DWORD cbWritten; 259 WriteFile(hStdOut, pch, (DWORD)cch, &cbWritten, NULL); 260 } 261 /* Windows 7 and earlier uses fake handles, with the last two bits set ((hStdOut & 3) == 3). */ 262 else if (NtWriteFile != NULL && ((uintptr_t)hStdOut & 3) == 0) 263 { 264 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 265 NtWriteFile(hStdOut, NULL /*Event*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/, 266 &Ios, (PVOID)pch, (ULONG)cch, NULL /*ByteOffset*/, NULL /*Key*/); 267 } 263 268 } 264 269 #else … … 1095 1100 } 1096 1101 1102 /* 1103 * Don't call TrustedError if it's too early. 1104 */ 1105 if (g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) 1106 { 1097 1107 #ifdef SUP_HARDENED_SUID 1098 /*1099 * Drop any root privileges we might be holding, this won't return1100 * if it fails but end up calling supR3HardenedFatal[V].1101 */1102 supR3HardenedMainDropPrivileges();1103 #endif /* SUP_HARDENED_SUID */1104 1105 /*1106 * Now try resolve and call the TrustedError entry point if we can1107 * find it. We'll fork before we attempt this because that way the1108 * session management in main will see us exiting immediately (if1109 * it's involved with us).1110 */1108 /* 1109 * Drop any root privileges we might be holding, this won't return 1110 * if it fails but end up calling supR3HardenedFatal[V]. 1111 */ 1112 supR3HardenedMainDropPrivileges(); 1113 #endif 1114 1115 /* 1116 * Now try resolve and call the TrustedError entry point if we can 1117 * find it. We'll fork before we attempt this because that way the 1118 * session management in main will see us exiting immediately (if 1119 * it's involved with us). 1120 */ 1111 1121 #if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2) 1112 int pid = fork(); 1113 if (pid <= 0) 1114 #endif 1115 { 1116 static volatile bool s_fRecursive = false; /* Loader hooks may cause recursion. */ 1117 if (!s_fRecursive) 1122 int pid = fork(); 1123 if (pid <= 0) 1124 #endif 1118 1125 { 1119 s_fRecursive = true; 1120 1121 PFNSUPTRUSTEDERROR pfnTrustedError = supR3HardenedMainGetTrustedError(g_pszSupLibHardenedProgName); 1122 if (pfnTrustedError) 1123 pfnTrustedError(pszWhere, enmWhat, rc, pszMsgFmt, va); 1124 1125 s_fRecursive = false; 1126 static volatile bool s_fRecursive = false; /* Loader hooks may cause recursion. */ 1127 if (!s_fRecursive) 1128 { 1129 s_fRecursive = true; 1130 1131 PFNSUPTRUSTEDERROR pfnTrustedError = supR3HardenedMainGetTrustedError(g_pszSupLibHardenedProgName); 1132 if (pfnTrustedError) 1133 pfnTrustedError(pszWhere, enmWhat, rc, pszMsgFmt, va); 1134 1135 s_fRecursive = false; 1136 } 1126 1137 } 1127 1138 } 1139 #if defined(RT_OS_WINDOWS) 1140 /* 1141 * Report the error to the parent if this happens during early VM init. 1142 */ 1143 else if ( g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED 1144 && g_enmSupR3HardenedMainState != SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED) 1145 supR3HardenedWinReportErrorToParent(rc, pszMsgFmt, va); 1146 #endif 1128 1147 1129 1148 /* … … 1151 1170 va_end(vaCopy); 1152 1171 1153 suplibHardenedPrintPrefix(); 1154 suplibHardenedPrintFV(pszFormat, va); 1172 #if defined(RT_OS_WINDOWS) 1173 /* 1174 * Report the error to the parent if this happens during early VM init. 1175 */ 1176 if ( g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED 1177 && g_enmSupR3HardenedMainState != SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED) 1178 supR3HardenedWinReportErrorToParent(VERR_INTERNAL_ERROR, pszFormat, va); 1179 else 1180 #endif 1181 { 1182 suplibHardenedPrintPrefix(); 1183 suplibHardenedPrintFV(pszFormat, va); 1184 } 1185 1155 1186 suplibHardenedExit(RTEXITCODE_FAILURE); 1156 1187 } … … 1199 1230 * @remarks This function will not return on failure. 1200 1231 */ 1201 static voidsupR3HardenedMainOpenDevice(void)1232 DECLHIDDEN(void) supR3HardenedMainOpenDevice(void) 1202 1233 { 1203 1234 int rc = suplibOsInit(&g_SupPreInitData.Data, false /*fPreInit*/, true /*fUnrestricted*/); … … 1671 1702 { 1672 1703 SUP_DPRINTF(("SUPR3HardenedMain: pszProgName=%s fFlags=%#x\n", pszProgName, fFlags)); 1704 g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_HARDENED_MAIN_CALLED; 1673 1705 1674 1706 /* … … 1678 1710 g_pszSupLibHardenedProgName = pszProgName; 1679 1711 g_fSupHardenedMain = fFlags; 1680 g_SupPreInitData.u32Magic = SUPPREINITDATA_MAGIC; 1681 g_SupPreInitData.Data.hDevice = SUP_HDEVICE_NIL; 1682 g_SupPreInitData.u32EndMagic = SUPPREINITDATA_MAGIC; 1712 #ifdef RT_OS_WINDOWS 1713 if (!g_fSupEarlyVmProcessInit) 1714 #endif 1715 { 1716 g_SupPreInitData.u32Magic = SUPPREINITDATA_MAGIC; 1717 g_SupPreInitData.Data.hDevice = SUP_HDEVICE_NIL; 1718 g_SupPreInitData.u32EndMagic = SUPPREINITDATA_MAGIC; 1719 } 1683 1720 1684 1721 #ifdef SUP_HARDENED_SUID … … 1689 1726 */ 1690 1727 supR3HardenedGetFullExePath(); 1691 1692 1728 # endif 1693 1729 … … 1714 1750 * at dropping compatibility layers and process "security" solutions. 1715 1751 */ 1716 if ( !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV) 1752 if ( !g_fSupEarlyVmProcessInit 1753 && !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV) 1717 1754 && supR3HardenedWinIsReSpawnNeeded(1 /*iWhich*/, argc, argv)) 1718 1755 { 1719 1756 SUP_DPRINTF(("SUPR3HardenedMain: Respawn #1\n")); 1720 supR3HardenedWinInit(SUPSECMAIN_FLAGS_DONT_OPEN_DEV );1757 supR3HardenedWinInit(SUPSECMAIN_FLAGS_DONT_OPEN_DEV, true /*fAvastKludge*/); 1721 1758 supR3HardenedVerifyAll(true /* fFatal */, pszProgName); 1722 1759 return supR3HardenedWinReSpawn(1 /*iWhich*/); … … 1726 1763 * Windows: Initialize the image verification global data so we can verify the 1727 1764 * signature of the process image and hook the core of the DLL loader API so we 1728 * can check the signature of all DLLs mapped into the process. 1729 */ 1730 supR3HardenedWinInit(fFlags); 1765 * can check the signature of all DLLs mapped into the process. (Already done 1766 * by early VM process init.) 1767 */ 1768 if (!g_fSupEarlyVmProcessInit) 1769 supR3HardenedWinInit(fFlags, true /*fAvastKludge*/); 1731 1770 #endif /* RT_OS_WINDOWS */ 1732 1771 … … 1738 1777 /* 1739 1778 * The next steps are only taken if we actually need to access the support 1740 * driver. 1741 */ 1742 if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)) 1743 { 1779 * driver. (Already done by early VM process init.) 1780 */ 1744 1781 #ifdef RT_OS_WINDOWS 1745 /* 1746 * Windows: Verify the process (repeated by the kernel later. 1747 */ 1748 supR3HardenedWinVerifyProcess(); 1749 1750 /* 1751 * Windows: The second respawn. This time we make a special arrangement 1752 * with vboxdrv to monitor access to the new process from its inception. 1753 */ 1754 if (supR3HardenedWinIsReSpawnNeeded(2 /* iWhich*/, argc, argv)) 1782 if (!g_fSupEarlyVmProcessInit) 1783 #endif 1784 if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)) 1755 1785 { 1756 SUP_DPRINTF(("SUPR3HardenedMain: Respawn #2\n")); 1757 return supR3HardenedWinReSpawn(2 /* iWhich*/); 1786 #ifdef RT_OS_WINDOWS 1787 /* 1788 * Windows: Verify the process (repeated by the kernel later. 1789 */ 1790 supR3HardenedWinVerifyProcess(); 1791 1792 /* 1793 * Windows: The second respawn. This time we make a special arrangement 1794 * with vboxdrv to monitor access to the new process from its inception. 1795 */ 1796 if (supR3HardenedWinIsReSpawnNeeded(2 /* iWhich*/, argc, argv)) 1797 { 1798 SUP_DPRINTF(("SUPR3HardenedMain: Respawn #2\n")); 1799 return supR3HardenedWinReSpawn(2 /* iWhich*/); 1800 } 1801 SUP_DPRINTF(("SUPR3HardenedMain: Final process, opening VBoxDrv...\n")); 1802 supR3HardenedWinFlushLoaderCache(); 1803 #endif /* RT_OS_WINDOWS */ 1804 1805 /* 1806 * Open the vboxdrv device. 1807 */ 1808 supR3HardenedMainOpenDevice(); 1758 1809 } 1759 SUP_DPRINTF(("SUPR3HardenedMain: Final process, opening VBoxDrv...\n"));1760 supR3HardenedWinFlushLoaderCache();1761 #endif /* RT_OS_WINDOWS */1762 1763 /*1764 * Open the vboxdrv device.1765 */1766 supR3HardenedMainOpenDevice();1767 }1768 1810 1769 1811 #ifdef RT_OS_WINDOWS … … 1774 1816 supR3HardenedWinFlushLoaderCache(); 1775 1817 supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(g_pszSupLibHardenedProgName); 1776 g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_ VERIFY_TRUST_READY;1818 g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_VERIFY_TRUST_READY; 1777 1819 #endif 1778 1820 -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h
r52940 r52943 165 165 extern SUPSYSROOTDIRBUF g_System32NtPath; 166 166 extern SUPSYSROOTDIRBUF g_WinSxSNtPath; 167 #if def IN_RING3167 #if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE) 168 168 extern SUPSYSROOTDIRBUF g_ProgramFilesNtPath; 169 169 extern SUPSYSROOTDIRBUF g_CommonFilesNtPath; … … 172 172 extern SUPSYSROOTDIRBUF g_CommonFilesX86NtPath; 173 173 # endif 174 #endif 174 #endif /* IN_RING3 && !VBOX_PERMIT_EVEN_MORE */ 175 175 extern SUPSYSROOTDIRBUF g_SupLibHardenedExeNtPath; 176 176 extern uint32_t g_offSupLibHardenedExeNtName; -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp
r52940 r52943 122 122 /** The full \\SystemRoot\\WinSxS path. */ 123 123 SUPSYSROOTDIRBUF g_WinSxSNtPath; 124 #if def IN_RING3124 #if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE) 125 125 /** The full 'Program Files' path. */ 126 126 SUPSYSROOTDIRBUF g_ProgramFilesNtPath; … … 135 135 SUPSYSROOTDIRBUF g_CommonFilesX86NtPath; 136 136 # endif 137 #endif /* IN_RING3 */137 #endif /* IN_RING3 && !VBOX_PERMIT_MORE*/ 138 138 139 139 static union … … 1443 1443 1444 1444 1445 1446 #ifdef IN_RING3 1445 #if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE) 1447 1446 /** 1448 1447 * Initializes the windows paths. … … 1632 1631 } 1633 1632 } 1634 #endif /* IN_RING3 */1633 #endif /* IN_RING3 && !VBOX_PERMIT_EVEN_MORE */ 1635 1634 1636 1635 … … 1656 1655 SUP_DPRINTF(("System32: %ls\n", g_System32NtPath.UniStr.Buffer)); 1657 1656 SUP_DPRINTF(("WinSxS: %ls\n", g_WinSxSNtPath.UniStr.Buffer)); 1658 #if def IN_RING31657 #if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE) 1659 1658 supHardenedWinInitImageVerifierWinPaths(); 1660 1659 #endif -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
r52941 r52943 174 174 175 175 176 /** 177 * VM process parameters. 178 */ 179 typedef struct SUPR3WINPROCPARAMS 180 { 181 /** The event semaphore the child will be waiting on. */ 182 HANDLE hEvtChild; 183 /** The event semaphore the parent will be waiting on. */ 184 HANDLE hEvtParent; 185 186 /** The address of the NTDLL. */ 187 uintptr_t uNtDllAddr; 188 189 /** The last status. */ 190 int32_t rc; 191 /** Error message / path name string space. */ 192 char szErrorMsg[4096]; 193 } SUPR3WINPROCPARAMS; 194 195 176 196 /******************************************************************************* 177 197 * Global Variables * 178 198 *******************************************************************************/ 199 /** Process parameters. Specified by parent if VM process, see 200 * supR3HardenedVmProcessInit. */ 201 static SUPR3WINPROCPARAMS g_ProcParams = { NULL, NULL, 0, 0 }; 202 /** Set if supR3HardenedVmProcessInit was invoked. */ 203 bool g_fSupEarlyVmProcessInit = false; 204 179 205 /** @name Global variables initialized by suplibHardenedWindowsMain. 180 206 * @{ */ … … 4362 4388 * Initializes the windows verficiation bits. 4363 4389 * @param fFlags The main flags. 4364 */ 4365 DECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags) 4390 * @param fAvastKludge Whether to apply the avast kludge. 4391 */ 4392 DECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags, bool fAvastKludge) 4366 4393 { 4367 4394 RTErrInfoInitStatic(&g_ErrInfoStatic); … … 4373 4400 if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)) 4374 4401 { 4375 /* 4376 * Do a self purification to cure avast's weird NtOpenFile write-thru 4377 * change in GetBinaryTypeW change in kernel32. Unfortunately, avast 4378 * uses a system thread to perform the process modifications, which 4379 * means it's hard to make sure it had the chance to make them... 4380 * 4381 * We have to resort to kludge doing yield and sleep fudging for a 4382 * number of milliseconds and schedulings before we can hope that avast 4383 * and similar products have done what they need to do. If we do any 4384 * fixes, we wait for a while again and redo it until we're clean. 4385 * 4386 * This is unfortunately kind of fragile. 4387 */ 4388 uint32_t cMsFudge = g_fSupAdversaries ? 512 : 128; 4389 uint32_t cFixes; 4390 for (uint32_t iLoop = 0; iLoop < 16; iLoop++) 4391 { 4392 uint32_t cSleeps = 0; 4393 DWORD dwStart = GetTickCount(); 4394 do 4402 if (fAvastKludge) 4403 { 4404 /* 4405 * Do a self purification to cure avast's weird NtOpenFile write-thru 4406 * change in GetBinaryTypeW change in kernel32. Unfortunately, avast 4407 * uses a system thread to perform the process modifications, which 4408 * means it's hard to make sure it had the chance to make them... 4409 * 4410 * We have to resort to kludge doing yield and sleep fudging for a 4411 * number of milliseconds and schedulings before we can hope that avast 4412 * and similar products have done what they need to do. If we do any 4413 * fixes, we wait for a while again and redo it until we're clean. 4414 * 4415 * This is unfortunately kind of fragile. 4416 */ 4417 uint32_t cMsFudge = g_fSupAdversaries ? 512 : 128; 4418 uint32_t cFixes; 4419 for (uint32_t iLoop = 0; iLoop < 16; iLoop++) 4395 4420 { 4396 NtYieldExecution(); 4397 LARGE_INTEGER Time; 4398 Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */ 4399 NtDelayExecution(FALSE, &Time); 4400 cSleeps++; 4401 } while ( GetTickCount() - dwStart <= cMsFudge 4402 || cSleeps < 8); 4403 SUP_DPRINTF(("supR3HardenedWinInit: Startup delay kludge #2/%u: %u ms, %u sleeps\n", 4404 iLoop, GetTickCount() - dwStart, cSleeps)); 4405 4406 cFixes = 0; 4407 rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), SUPHARDNTVPKIND_SELF_PURIFICATION, 4408 &cFixes, NULL /*pErrInfo*/); 4409 if (RT_FAILURE(rc) || cFixes == 0) 4410 break; 4411 4412 if (!g_fSupAdversaries) 4413 g_fSupAdversaries |= SUPHARDNT_ADVERSARY_UNKNOWN; 4414 cMsFudge = 512; 4415 4416 /* Log the KiOpPrefetchPatchCount value if available, hoping it might sched some light on spider38's case. */ 4417 ULONG cPatchCount = 0; 4418 NTSTATUS rcNt = NtQuerySystemInformation(SystemInformation_KiOpPrefetchPatchCount, 4419 &cPatchCount, sizeof(cPatchCount), NULL); 4420 if (NT_SUCCESS(rcNt)) 4421 SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x cPatchCount=%#u\n", 4422 cFixes, g_fSupAdversaries, cPatchCount)); 4423 else 4424 SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x\n", cFixes, g_fSupAdversaries)); 4421 uint32_t cSleeps = 0; 4422 DWORD dwStart = GetTickCount(); 4423 do 4424 { 4425 NtYieldExecution(); 4426 LARGE_INTEGER Time; 4427 Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */ 4428 NtDelayExecution(FALSE, &Time); 4429 cSleeps++; 4430 } while ( GetTickCount() - dwStart <= cMsFudge 4431 || cSleeps < 8); 4432 SUP_DPRINTF(("supR3HardenedWinInit: Startup delay kludge #2/%u: %u ms, %u sleeps\n", 4433 iLoop, GetTickCount() - dwStart, cSleeps)); 4434 4435 cFixes = 0; 4436 rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), SUPHARDNTVPKIND_SELF_PURIFICATION, 4437 &cFixes, NULL /*pErrInfo*/); 4438 if (RT_FAILURE(rc) || cFixes == 0) 4439 break; 4440 4441 if (!g_fSupAdversaries) 4442 g_fSupAdversaries |= SUPHARDNT_ADVERSARY_UNKNOWN; 4443 cMsFudge = 512; 4444 4445 /* Log the KiOpPrefetchPatchCount value if available, hoping it might sched some light on spider38's case. */ 4446 ULONG cPatchCount = 0; 4447 NTSTATUS rcNt = NtQuerySystemInformation(SystemInformation_KiOpPrefetchPatchCount, 4448 &cPatchCount, sizeof(cPatchCount), NULL); 4449 if (NT_SUCCESS(rcNt)) 4450 SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x cPatchCount=%#u\n", 4451 cFixes, g_fSupAdversaries, cPatchCount)); 4452 else 4453 SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x\n", cFixes, g_fSupAdversaries)); 4454 } 4425 4455 } 4426 4456 … … 5061 5091 5062 5092 /* 5093 * Notify the parent process that we're probably capable of reporting our 5094 * own errors. 5095 */ 5096 if (g_ProcParams.hEvtParent || g_ProcParams.hEvtChild) 5097 { 5098 SUPR3HARDENED_ASSERT(g_fSupEarlyVmProcessInit); 5099 NtSetEvent(g_ProcParams.hEvtParent, NULL); 5100 NtClose(g_ProcParams.hEvtParent); 5101 NtClose(g_ProcParams.hEvtChild); 5102 g_ProcParams.hEvtParent = NULL; 5103 g_ProcParams.hEvtChild = NULL; 5104 } 5105 else 5106 SUPR3HARDENED_ASSERT(!g_fSupEarlyVmProcessInit); 5107 5108 /* 5063 5109 * After having resolved imports we patch the LdrInitializeThunk code so 5064 5110 * that it's more difficult to invade our privacy by CreateRemoteThread. … … 5140 5186 } 5141 5187 5188 5189 /** 5190 * Reports an error to the parent process via the process parameter structure. 5191 * 5192 * @param rc The status code to report. 5193 * @param pszFormat The format string. 5194 * @param va The format arguments. 5195 */ 5196 DECLHIDDEN(void) supR3HardenedWinReportErrorToParent(int rc, const char *pszFormat, va_list va) 5197 { 5198 RTStrPrintfV(g_ProcParams.szErrorMsg, sizeof(g_ProcParams.szErrorMsg), pszFormat, va); 5199 g_ProcParams.rc = RT_SUCCESS(rc) ? VERR_INTERNAL_ERROR_2 : rc; 5200 5201 NTSTATUS rcNt = NtSetEvent(g_ProcParams.hEvtParent, NULL); 5202 if (NT_SUCCESS(rcNt)) 5203 { 5204 LARGE_INTEGER Timeout; 5205 Timeout.QuadPart = -300000000; /* 30 second */ 5206 NTSTATUS rcNt = NtWaitForSingleObject(g_ProcParams.hEvtChild, FALSE /*Alertable*/, &Timeout); 5207 NtClearEvent(g_ProcParams.hEvtChild); 5208 } 5209 } 5210 5211 5212 /** 5213 * Routine called by the supR3HardenedVmProcessInitThunk assembly routine when 5214 * LdrInitializeThunk is executed in during process initialization. 5215 * 5216 * This initializes the VM process, hooking NTDLL APIs and opening the device 5217 * driver before any other DLLs gets loaded into the process. This greately 5218 * reduces and controls the trusted code base of the process compared to the 5219 * opening it from SUPR3HardenedMain, avoid issues with so call protection 5220 * software that is in the habit of patching half of the ntdll and kernel32 5221 * APIs in the process, making it almost indistinguishable from software that is 5222 * up to no good. Once we've opened vboxdrv, the process should be locked down 5223 * so thighly that only kernel software and csrss can mess with the process. 5224 */ 5225 DECLASM(uintptr_t) supR3HardenedVmProcessInit(void) 5226 { 5227 /* 5228 * Only let the first thread thru. 5229 */ 5230 if (!ASMAtomicCmpXchgU32((uint32_t volatile *)&g_enmSupR3HardenedMainState, 5231 SUPR3HARDENEDMAINSTATE_WIN_VM_INIT_CALLED, 5232 SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED)) 5233 { 5234 NtTerminateThread(0, 0); 5235 return 0x22; /* crash */ 5236 } 5237 g_fSupEarlyVmProcessInit = true; 5238 5239 /* 5240 * Initialize the NTDLL imports that we consider usable before the 5241 * process has been initialized. 5242 */ 5243 supR3HardenedWinInitImportsEarly(g_ProcParams.uNtDllAddr); 5244 g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_IMPORTS_RESOLVED; 5245 5246 /* 5247 * Init g_uNtVerCombined as well as we can at this point. 5248 */ 5249 supR3HardenedWinInitVersion(); 5250 5251 /* 5252 * Wait on the parent process to dispose of the full access process handle. 5253 */ 5254 LARGE_INTEGER Timeout; 5255 Timeout.QuadPart = -600000000; /* 60 second */ 5256 NTSTATUS rcNt = NtWaitForSingleObject(g_ProcParams.hEvtChild, FALSE /*Alertable*/, &Timeout); 5257 if (NT_SUCCESS(rcNt)) 5258 rcNt = NtClearEvent(g_ProcParams.hEvtChild); 5259 if (!NT_SUCCESS(rcNt)) 5260 { 5261 NtTerminateProcess(NtCurrentProcess(), 0x42); 5262 return 0x42; /* crash */ 5263 } 5264 5265 /* 5266 * Convert the arguments to UTF-8 so we can open the log file if specified. 5267 * Note! This leaks memory at present. 5268 */ 5269 PUNICODE_STRING pCmdLineStr = &NtCurrentPeb()->ProcessParameters->CommandLine; 5270 int cArgs; 5271 char **papszArgs = suplibCommandLineToArgvWStub(pCmdLineStr->Buffer, pCmdLineStr->Length / sizeof(WCHAR), &cArgs); 5272 supR3HardenedOpenLog(&cArgs, papszArgs); 5273 SUP_DPRINTF(("supR3HardenedVmProcessInit: uNtDllAddr=%p\n", g_ProcParams.uNtDllAddr)); 5274 5275 /* 5276 * Determine the executable path and name. Will NOT determine the windows style 5277 * executable path here as we don't need it. 5278 */ 5279 SIZE_T cbActual = 0; 5280 rcNt = NtQueryVirtualMemory(NtCurrentProcess(), &g_ProcParams, MemorySectionName, &g_SupLibHardenedExeNtPath, 5281 sizeof(g_SupLibHardenedExeNtPath) - sizeof(WCHAR), &cbActual); 5282 if ( !NT_SUCCESS(rcNt) 5283 || g_SupLibHardenedExeNtPath.UniStr.Length == 0 5284 || g_SupLibHardenedExeNtPath.UniStr.Length & 1) 5285 supR3HardenedFatal("NtQueryVirtualMemory/MemorySectionName failed in supR3HardenedVmProcessInit: %#x\n", rcNt); 5286 5287 /* The NT executable name offset / dir path length. */ 5288 g_offSupLibHardenedExeNtName = g_SupLibHardenedExeNtPath.UniStr.Length / sizeof(WCHAR); 5289 while ( g_offSupLibHardenedExeNtName > 1 5290 && g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] != '\\' ) 5291 g_offSupLibHardenedExeNtName--; 5292 5293 /* 5294 * Initialize the image verification stuff (hooks LdrLoadDll and NtCreateSection). 5295 */ 5296 supR3HardenedWinInit(0, false /*fAvastKludge*/); 5297 5298 /* 5299 * Open the driver. 5300 */ 5301 supR3HardenedMainOpenDevice(); 5302 g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_DEVICE_OPENED; 5303 5304 /* 5305 * Restore the LdrInitializeThunk code so we can initialize the process 5306 * normally when we return. 5307 */ 5308 PSUPHNTLDRCACHEENTRY pLdrEntry; 5309 int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry); 5310 if (RT_FAILURE(rc)) 5311 supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc); 5312 5313 RTLDRADDR uValue; 5314 rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pLdrEntry->pbBits, 0, UINT32_MAX, "LdrInitializeThunk", &uValue); 5315 if (RT_FAILURE(rc)) 5316 supR3HardenedFatal("supR3HardenedVmProcessInit: Failed to find LdrInitializeThunk (%Rrc).\n", rc); 5317 5318 PVOID pvLdrInitThunk = (uint8_t *)g_ProcParams.uNtDllAddr + (uint32_t)uValue; 5319 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pvLdrInitThunk, 16, PAGE_EXECUTE_READWRITE)); 5320 memcpy(pvLdrInitThunk, pLdrEntry->pbBits + (uint32_t)uValue, 16); 5321 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pvLdrInitThunk, 16, PAGE_EXECUTE_READ)); 5322 5323 return (uintptr_t)pvLdrInitThunk; 5324 } 5325 -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainA-win.asm
r52941 r52943 35 35 extern NAME(g_pfnNtCreateSectionJmpBack) 36 36 37 ; External code. 38 extern NAME(supR3HardenedVmProcessInit) 39 37 40 38 41 BEGINCODE … … 76 79 77 80 %endif 81 82 83 84 ;; 85 ; Alternative code for LdrInitializeThunk that performs the VM process startup. 86 ; 87 ; This does not concern itself with any arguments on stack or in registers that 88 ; may be passed to the LdrIntializeThunk routine as we just save and restore 89 ; them all before we restart the restored LdrInitializeThunk routine. 90 ; 91 BEGINPROC supR3HardenedVmProcessInitThunk 92 ; 93 ; Prologue. 94 ; 95 96 ; Reserve space for the "return" address. 97 push 0 98 99 ; Create a stack frame, saving xBP. 100 push xBP 101 SEH64_PUSH_xBP 102 mov xBP, xSP 103 SEH64_SET_FRAME_xBP 0 ; probably wrong... 104 105 ; Save all volatile registers. 106 push xAX 107 push xCX 108 push xDX 109 %ifdef RT_ARCH_AMD64 110 push r8 111 push r9 112 push r10 113 push r11 114 %endif 115 116 ; Reserve spill space and align the stack. 117 sub xSP, 20h 118 and xSP, ~0fh 119 SEH64_END_PROLOGUE 120 121 ; 122 ; Call the C/C++ code that does the actual work. This returns the 123 ; resume address in xAX, which we put in the "return" stack position. 124 ; 125 call NAME(supR3HardenedVmProcessInit) 126 mov [xBP + xCB], xAX 127 128 ; 129 ; Restore volatile registers. 130 ; 131 mov xAX, [xBP - xCB*1] 132 mov xCX, [xBP - xCB*2] 133 mov xDX, [xBP - xCB*3] 134 %ifdef RT_ARCH_AMD64 135 mov r8, [xBP - xCB*4] 136 mov r9, [xBP - xCB*5] 137 mov r10, [xBP - xCB*6] 138 mov r11, [xBP - xCB*7] 139 %endif 140 ; 141 ; Use the leave instruction to restore xBP and set up xSP to point at 142 ; the resume address. Then use the 'ret' instruction to resume process 143 ; initializaton. 144 ; 145 leave 146 ret 147 ENDPROC supR3HardenedVmProcessInitThunk 148 149 78 150 79 151 ;; -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainImports-win.cpp
r52941 r52943 229 229 /** 230 230 * All the DLLs we import from. 231 * @remarks Code ASSUMES that ntdll is the first entry. 231 232 */ 232 233 static SUPHNTIMPDLL g_aSupNtImpDlls[] = … … 546 547 547 548 549 /** 550 * Resolves NtDll functions we can trust calling before process init. 551 * 552 * @param uNtDllAddr The address of the NTDLL. 553 */ 554 DECLHIDDEN(void) supR3HardenedWinInitImportsEarly(uintptr_t uNtDllAddr) 555 { 556 /* 557 * NTDLL is the first entry in the list. 558 */ 559 g_aSupNtImpDlls[0].pbImageBase = (uint8_t const *)uNtDllAddr; 560 supR3HardenedParseModule(&g_aSupNtImpDlls[0]); 561 for (uint32_t i = 0; i < g_aSupNtImpDlls[0].cImports; i++) 562 if (!g_aSupNtImpDlls[0].paImports[i].pfnEarlyDummy) 563 { 564 const char *pszForwarder = supR3HardenedResolveImport(&g_aSupNtImpDlls[0], &g_aSupNtImpDlls[0].paImports[i]); 565 if (pszForwarder) 566 SUPHNTIMP_ERROR(32, "supR3HardenedWinInitImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, 567 "ntdll: Failed to resolve forwarder '%s'.", pszForwarder); 568 } 569 else 570 *g_aSupNtImpDlls[0].paImports[i].ppfnImport = g_aSupNtImpDlls[0].paImports[i].pfnEarlyDummy; 571 572 /* 573 * Pointer the other imports at the early init stubs. 574 */ 575 for (uint32_t iDll = 1; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) 576 for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) 577 if (!g_aSupNtImpDlls[iDll].paImports[i].fOptional) 578 *g_aSupNtImpDlls[iDll].paImports[i].ppfnImport = g_aSupNtImpDlls[iDll].paImports[i].pfnEarlyDummy; 579 else 580 *g_aSupNtImpDlls[iDll].paImports[i].ppfnImport = NULL; 581 } 582 548 583 549 584 /** -
trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h
r52941 r52943 1 1 SUPHARNT_IMPORT_SYSCALL(NtAllocateVirtualMemory, 24) 2 SUPHARNT_IMPORT_SYSCALL(NtClearEvent, 4) 2 3 SUPHARNT_IMPORT_SYSCALL(NtClose, 4) 4 SUPHARNT_IMPORT_SYSCALL(NtCreateEvent, 20) 3 5 SUPHARNT_IMPORT_SYSCALL(NtCreateFile, 44) 4 6 SUPHARNT_IMPORT_SYSCALL(NtDelayExecution, 8) … … 9 11 SUPHARNT_IMPORT_SYSCALL(NtMapViewOfSection, 40) 10 12 SUPHARNT_IMPORT_SYSCALL(NtOpenDirectoryObject, 12) 13 SUPHARNT_IMPORT_SYSCALL(NtOpenEvent, 12) 11 14 SUPHARNT_IMPORT_SYSCALL(NtOpenKey, 12) 12 15 SUPHARNT_IMPORT_SYSCALL(NtOpenProcess, 16) … … 17 20 SUPHARNT_IMPORT_SYSCALL(NtQueryDirectoryFile, 44) 18 21 SUPHARNT_IMPORT_SYSCALL(NtQueryDirectoryObject, 28) 22 SUPHARNT_IMPORT_SYSCALL(NtQueryEvent, 20) 19 23 SUPHARNT_IMPORT_SYSCALL(NtQueryInformationFile, 20) 20 24 SUPHARNT_IMPORT_SYSCALL(NtQueryInformationProcess, 20) … … 22 26 SUPHARNT_IMPORT_SYSCALL(NtQueryInformationToken, 20) 23 27 SUPHARNT_IMPORT_SYSCALL(NtQueryObject, 20) 28 SUPHARNT_IMPORT_SYSCALL(NtQuerySecurityObject, 20) 24 29 SUPHARNT_IMPORT_SYSCALL(NtQuerySystemInformation, 16) 25 SUPHARNT_IMPORT_SYSCALL(NtQuerySecurityObject, 20)26 30 SUPHARNT_IMPORT_SYSCALL(NtQueryTimerResolution, 12) 27 31 SUPHARNT_IMPORT_SYSCALL(NtQueryValueKey, 24) … … 29 33 SUPHARNT_IMPORT_SYSCALL(NtReadFile, 36) 30 34 SUPHARNT_IMPORT_SYSCALL(NtReadVirtualMemory, 20) 35 SUPHARNT_IMPORT_SYSCALL(NtResetEvent, 8) 31 36 SUPHARNT_IMPORT_SYSCALL(NtResumeProcess, 4) 32 37 SUPHARNT_IMPORT_SYSCALL(NtResumeThread, 8) 33 38 SUPHARNT_IMPORT_SYSCALL(NtSetContextThread, 8) 39 SUPHARNT_IMPORT_SYSCALL(NtSetEvent, 8) 34 40 SUPHARNT_IMPORT_SYSCALL(NtSetInformationFile, 20) 35 41 SUPHARNT_IMPORT_SYSCALL(NtSetInformationObject, 16) … … 42 48 SUPHARNT_IMPORT_SYSCALL(NtTerminateThread, 8) 43 49 SUPHARNT_IMPORT_SYSCALL(NtUnmapViewOfSection, 8) 50 SUPHARNT_IMPORT_SYSCALL(NtWaitForMultipleObjects, 20) 44 51 SUPHARNT_IMPORT_SYSCALL(NtWaitForSingleObject, 12) 45 SUPHARNT_IMPORT_SYSCALL(NtWaitForMultipleObjects, 20)46 52 SUPHARNT_IMPORT_SYSCALL(NtWriteFile, 36) 47 53 SUPHARNT_IMPORT_SYSCALL(NtWriteVirtualMemory, 20) 48 54 SUPHARNT_IMPORT_SYSCALL(NtYieldExecution, 0) 49 55 50 51 56 SUPHARNT_IMPORT_STDCALL_EARLY(NtCreateSection, 28) 52 57 SUPHARNT_IMPORT_STDCALL_EARLY(NtQueryVolumeInformationFile, 20) 58 53 59 SUPHARNT_IMPORT_STDCALL_EARLY(LdrInitializeThunk, 12) 60 54 61 SUPHARNT_IMPORT_STDCALL(RtlAddAccessAllowedAce, 16) 55 62 SUPHARNT_IMPORT_STDCALL(RtlAddAccessDeniedAce, 16) … … 74 81 SUPHARNT_IMPORT_STDCALL_EARLY(RtlGetLastWin32Error, 0) 75 82 SUPHARNT_IMPORT_STDCALL_EARLY(RtlGetVersion, 4) 76 SUPHARNT_IMPORT_STDCALL (RtlInitializeSid, 12)83 SUPHARNT_IMPORT_STDCALL_EARLY(RtlInitializeSid, 12) 77 84 SUPHARNT_IMPORT_STDCALL_EARLY(RtlNtStatusToDosError, 4) 78 85 SUPHARNT_IMPORT_STDCALL_EARLY(RtlReAllocateHeap, 16) … … 82 89 SUPHARNT_IMPORT_STDCALL_EARLY(RtlSetLastWin32ErrorAndNtStatusFromNtStatus, 4) 83 90 SUPHARNT_IMPORT_STDCALL_EARLY(RtlSizeHeap, 12) 84 SUPHARNT_IMPORT_STDCALL (RtlSubAuthoritySid, 8)91 SUPHARNT_IMPORT_STDCALL_EARLY(RtlSubAuthoritySid, 8) 85 92 -
trunk/src/VBox/Runtime/r3/win/ntdll-mini-implib.def
r52942 r52943 33 33 34 34 NtAllocateVirtualMemory ;;= _NtAllocateVirtualMemory@24 35 NtClearEvent ;;= _NtClearEvent@4 35 36 NtClose ;;= _NtClose@4 37 NtCreateEvent ;;= _NtCreateEvent@20 36 38 NtCreateFile ;;= _NtCreateFile@44 37 39 NtCreateSection ;;= _NtCreateSection@28 … … 43 45 NtMapViewOfSection ;;= _NtMapViewOfSection@40 44 46 NtOpenDirectoryObject ;;= _NtOpenDirectoryObject@12 47 NtOpenEvent ;;= _NtOpenEvent@12 45 48 NtOpenKey ;;= _NtOpenKey@12 46 49 NtOpenProcess ;;= _NtOpenProcess@16 … … 51 54 NtQueryDirectoryFile ;;= _NtQueryDirectoryFile@44 52 55 NtQueryDirectoryObject ;;= _NtQueryDirectoryObject@28 56 NtQueryEvent ;;= _NtQueryEvent@20 53 57 NtQueryInformationFile ;;= _NtQueryInformationFile@20 54 58 NtQueryInformationProcess ;;= _NtQueryInformationProcess@20 … … 64 68 NtReadFile ;;= _NtReadFile@36 65 69 NtReadVirtualMemory ;;= _NtReadVirtualMemory@20 70 NtResetEvent ;;= _NtResetEvent@8 66 71 NtResumeProcess ;;= _NtResumeProcess@4 67 72 NtResumeThread ;;= _NtResumeThread@8 68 73 NtSetContextThread ;;= _NtSetContextThread@8 74 NtSetEvent ;;= _NtSetEvent@8 69 75 NtSetInformationFile ;;= _NtSetInformationFile@20 70 76 NtSetInformationObject ;;= _NtSetInformationObject@16 … … 77 83 NtTerminateThread ;;= _NtTerminateThread@8 78 84 NtUnmapViewOfSection ;;= _NtUnmapViewOfSection@8 85 NtWaitForMultipleObjects ;;= _NtWaitForMultipleObjects@20 79 86 NtWaitForSingleObject ;;= _NtWaitForSingleObject@12 80 NtWaitForMultipleObjects ;;= _NtWaitForMultipleObjects@2081 87 NtWriteFile ;;= _NtWriteFile@36 82 88 NtWriteVirtualMemory ;;= _NtWriteVirtualMemory@20
Note:
See TracChangeset
for help on using the changeset viewer.