windows-nt/Source/XPSP1/NT/base/ntsetup/winnt32/dll/amd64/protect.c
2020-09-26 16:20:57 +08:00

292 lines
6.1 KiB
C

#include "precomp.h"
#include <tlhelp32.h>
#ifndef MYASSERT
#define MYASSERT(x)
#endif
typedef HANDLE (WINAPI * CREATETOOLHELP32SNAPSHOT)(DWORD Flags, DWORD ProcessId);
typedef BOOL (WINAPI * MODULE32FIRST)(HANDLE Snapshot, LPMODULEENTRY32 lpme);
typedef BOOL (WINAPI * MODULE32NEXT)(HANDLE Snapshot, LPMODULEENTRY32 lpme);
BOOL
pIsLegalPage (
IN DWORD Protect
)
{
//
// Page must be actually in memory to protect it, and it
// cannot be any type of write-copy.
//
if ((Protect & PAGE_GUARD) ||
(Protect == PAGE_NOACCESS) ||
(Protect == PAGE_WRITECOPY) ||
(Protect == PAGE_EXECUTE_WRITECOPY)
) {
return FALSE;
}
return TRUE;
}
BOOL
pIsKnownSection (
IN const IMAGE_SECTION_HEADER *Section,
IN const IMAGE_NT_HEADERS *NtHeaders
)
{
//
// Return TRUE if section is code or code data
//
if (Section->Characteristics & (IMAGE_SCN_MEM_EXECUTE|
IMAGE_SCN_MEM_DISCARDABLE|
IMAGE_SCN_MEM_WRITE|
IMAGE_SCN_MEM_READ)
) {
return TRUE;
}
//
// Return TRUE if section is resources
//
if (NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress ==
Section->VirtualAddress
) {
return TRUE;
}
//
// Unknown section
//
return FALSE;
}
VOID
pPutRegionInSwapFile (
IN PVOID Address,
IN DWORD Size
)
{
MEMORY_BASIC_INFORMATION mbi;
DWORD PageSize;
PVOID EndPtr;
PVOID RegionEnd;
DWORD d;
DWORD OldPermissions;
volatile DWORD *v;
SYSTEM_INFO si;
//
// Get system virtual page size
//
GetSystemInfo(&si);
PageSize = si.dwPageSize;
//
// Compute the pointer to the end of the region
//
EndPtr = (PBYTE) Address + Size;
//
// For each page in the region, mark it as e/r/w, modify it, and restore the permissions
//
while (Address < EndPtr) {
d = VirtualQuery (Address, &mbi, sizeof(mbi));
if (d == sizeof(mbi)) {
//
// We assume the module wasn't loaded with one of the following
// conditions (which break as a result of VirtualProtect)
//
RegionEnd = (PBYTE) mbi.BaseAddress + mbi.RegionSize;
if (RegionEnd > EndPtr) {
RegionEnd = EndPtr;
}
if (mbi.State == MEM_COMMIT && pIsLegalPage (mbi.Protect)) {
//
// Switch to e/r/w
//
if (VirtualProtect (
mbi.BaseAddress,
(PBYTE) RegionEnd - (PBYTE) mbi.BaseAddress,
PAGE_EXECUTE_READWRITE,
&OldPermissions
)) {
//
// Touch every page in the region.
//
for (Address = mbi.BaseAddress; Address < RegionEnd ; Address = (PBYTE) Address + PageSize) {
v = Address;
*v = *v;
}
//
// Switch back
//
VirtualProtect (
mbi.BaseAddress,
(PBYTE) RegionEnd - (PBYTE) mbi.BaseAddress,
OldPermissions,
&d
);
}
}
Address = RegionEnd;
} else {
MYASSERT (FALSE);
break;
}
}
}
VOID
pProtectModule (
HANDLE Module
)
{
TCHAR Path[MAX_PATH];
BOOL IsNetDrive;
const IMAGE_DOS_HEADER *DosHeader;
const IMAGE_NT_HEADERS *NtHeaders;
const IMAGE_SECTION_HEADER *SectHeader;
UINT u;
IsNetDrive = FALSE;
//
// Get module info
//
if( GetModuleFileName (Module, Path, MAX_PATH) ){
//
// Determine if the module is running on the net
//
if (Path[0] == TEXT('\\')) {
IsNetDrive = TRUE;
} else if (GetDriveType (Path) == DRIVE_REMOTE) {
IsNetDrive = TRUE;
}
}
if (!IsNetDrive) {
return;
}
//
// Enumerate all sections in the PE header
//
DosHeader = (const IMAGE_DOS_HEADER *) Module;
NtHeaders = (const IMAGE_NT_HEADERS *) ((PBYTE) Module + DosHeader->e_lfanew);
for (u = 0 ; u < NtHeaders->FileHeader.NumberOfSections ; u++) {
SectHeader = IMAGE_FIRST_SECTION (NtHeaders) + u;
if (pIsKnownSection (SectHeader, NtHeaders)) {
pPutRegionInSwapFile (
(PBYTE) Module + SectHeader->VirtualAddress,
SectHeader->Misc.VirtualSize
);
}
}
}
VOID
ProtectAllModules (
VOID
)
{
HANDLE Library;
HANDLE Snapshot;
MODULEENTRY32 me32;
CREATETOOLHELP32SNAPSHOT fnCreateToolhelp32Snapshot;
MODULE32FIRST fnModule32First;
MODULE32NEXT fnModule32Next;
//
// Load toohelp dynamically (for NT 4, NT 3.51 compatibility)
//
Library = LoadLibrary (TEXT("toolhelp.dll"));
if (!Library) {
return;
}
(FARPROC) fnCreateToolhelp32Snapshot = GetProcAddress (Library, "CreateToolhelp32Snapshot");
(FARPROC) fnModule32First = GetProcAddress (Library, "Module32First");
(FARPROC) fnModule32Next = GetProcAddress (Library, "Module32Next");
if (!fnCreateToolhelp32Snapshot || !fnModule32First || !fnModule32Next) {
FreeLibrary (Library);
return;
}
//
// Protect each loaded module
//
Snapshot = fnCreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
MYASSERT (Snapshot != INVALID_HANDLE_VALUE);
if (Snapshot == INVALID_HANDLE_VALUE) {
return;
}
me32.dwSize = sizeof (me32);
if (fnModule32First (Snapshot, &me32)) {
do {
pProtectModule (me32.hModule);
} while (fnModule32Next (Snapshot, &me32));
}
//
// Done
//
CloseHandle (Snapshot);
FreeLibrary (Library);
}