📄 verifier.c
字号:
LPSHIMINFO pShimInfoTemp;
//
// We can't use the info in the registry, since that could have changed
// since this module was loaded.
//
if ((BaseAddr == (DWORD) pCurProc->BasePtr) && !pCurProc->pShimInfo) {
// This is a process, and is not shimmed
return TRUE;
}
// If we're here, this is either a shimmed process, or a dll. Either way,
// we need to get some more info.
if (!GetNameFromE32 (eptr, szModuleName, MAX_PATH, & pMod)) {
// Couldn't find the module??
return FALSE;
}
if (pMod && !pMod->pShimInfo) {
// This is a dll, and is not shimmed
return FALSE;
}
DEBUGMSG (ZONE_ENTRY, (TEXT("++UnDoDepends 0x%08x 0x%08x %s\r\n"), eptr, BaseAddr, szModuleName));
// Walk the list of shim modules injected into this image
pShimInfo = pMod ? ((LPSHIMREF)pMod->pShimInfo)->pShimInfo [pCurProc->procnum] : pCurProc->pShimInfo;
while (pShimInfo) {
// Free the shims
g_fUnLoadingShim = TRUE;
g_Imports.FreeOneLibrary (pShimInfo->pMod, 1);
g_fUnLoadingShim = FALSE;
pShimInfoTemp = pShimInfo;
pShimInfo = pShimInfo->pNext;
g_Imports.FreeMem (pShimInfoTemp, pShimInfoTemp->wPool);
}
if (pMod) {
// Remove the list for this process
((LPSHIMREF)pMod->pShimInfo)->pShimInfo [pCurProc->procnum] = NULL;
}
// Note: The kernel does not notify dll's anymore. It now keeps a list of
// dll's that need to be notified, and coredll walks that list. Re-order
// the list in GetProcModList.
return TRUE;
}
BOOL ShimIoControl(
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned
)
{
switch (dwIoControlCode) {
}
return FALSE;
}
BOOL ShimGetProcModList (PDLLMAININFO pList, DWORD nMods)
{
DLLMAININFO DllMainInfoTemp;
DWORD idx;
DWORD idx2;
PDLLMAININFO pCurr;
PDLLMAININFO pWalk;
struct ImpHdr *blockptr;
TCHAR imp_lookupw [MAX_DLLNAME_LEN];
BOOL fSwapped = FALSE;
if (nMods == 1) {
// A list of 1 is already sorted
return TRUE;
}
// Reorder this list, making sure that the app's dll's are notified
// before the shims and their helpers. This will prevent some false
// leak information. Also reorder so the shim's dependent dll's are called
// after the shim.
// We only need to reorder the list of dll's if the process is exiting.
if (pIsExiting && *(LPDWORD)MapPtrProc(pIsExiting,pCurProc)) {
// Print out the current list
if (ZONE_NOTIFYLIST) {
RETAILMSG (1, (_T("Old list:\r\n")));
for (idx = 0; idx < nMods; idx ++) {
RETAILMSG (1, (_T("%02u: %s (%s)\r\n"), idx, ((PMODULE)pList[idx].hLib)->lpszModName,
IsShimDll ((PMODULE) pList[idx].hLib) ? _T("shim") : _T("normal")));
}
}
// Order by shim vs. non-shim. pCurr will point to the next position
// that will contain a shim. pWalk will be used to walk through the list.
for (pWalk = pList, pCurr = & pList [nMods - 1]; pWalk < pCurr; ) {
if (IsShimDll ((LPMODULE)(pWalk->hLib))) {
// Move the shim to the end of the list, shifting the rest of
// the non-moved modules down one slot.
memcpy (& DllMainInfoTemp, pWalk, sizeof (DLLMAININFO));
memcpy (pWalk, pWalk + 1, (pCurr - pWalk) * sizeof (DLLMAININFO));
memcpy (pCurr, & DllMainInfoTemp, sizeof (DLLMAININFO));
pCurr--;
}
else {
// Move on to the next position.
pWalk++;
}
}
// Print out the current list
if (ZONE_NOTIFYLIST) {
RETAILMSG (1, (_T("Intermediate list:\r\n")));
for (idx = 0; idx < nMods; idx ++) {
RETAILMSG (1, (_T("%02u: %s (%s)\r\n"), idx, ((PMODULE)pList[idx].hLib)->lpszModName,
IsShimDll ((PMODULE) pList[idx].hLib) ? _T("shim") : _T("normal")));
}
}
// Now resolve dependency orders for shims, leaving non-shim dll's in
// the kernel's order.
for (idx = 0, pCurr = & pList [nMods - 1]; (idx < nMods) && IsShimDll ((LPMODULE)(pCurr->hLib)); idx++, pCurr--) {
DEBUGMSG (ZONE_NOTIFYLIST, (_T("pCurr: %s\r\n"), ((LPMODULE)(pCurr->hLib))->lpszModName));
for (idx2 = idx + 1, pWalk = pCurr - 1; (idx2 < nMods) && IsShimDll ((LPMODULE)(pWalk->hLib)); idx2++, pWalk--) {
DEBUGMSG (ZONE_NOTIFYLIST, (_T(" pWalk: %s\r\n"), ((LPMODULE)(pWalk->hLib))->lpszModName));
blockptr = (struct ImpHdr *)(ZeroPtr (((BYTE *)((LPMODULE)(pCurr->hLib))->BasePtr)+((LPMODULE)(pCurr->hLib))->e32.e32_unit[IMP].rva));
while (blockptr->imp_lookup) {
g_Imports.KAsciiToUnicode (imp_lookupw, (LPCHAR)((LPMODULE)(pCurr->hLib))->BasePtr+blockptr->imp_dllname, MAX_DLLNAME_LEN);
DEBUGMSG (ZONE_NOTIFYLIST, (_T(" imp_lookup: %s\r\n"), imp_lookupw));
fSwapped = FALSE;
if (!vrf_wcsicmp (imp_lookupw, ((LPMODULE)(pWalk->hLib))->lpszModName)) {
DEBUGMSG (ZONE_NOTIFYLIST, (_T("---> Swapping '%s' and '%s'\r\n"),
((LPMODULE)(pCurr->hLib))->lpszModName,
((LPMODULE)(pWalk->hLib))->lpszModName));
// Swap the two modules
memcpy (& DllMainInfoTemp, pCurr, sizeof (DLLMAININFO));
memcpy (pCurr, pWalk, sizeof (DLLMAININFO));
memcpy (pWalk, & DllMainInfoTemp, sizeof (DLLMAININFO));
fSwapped = TRUE;
break;
}
blockptr ++;
}
if (fSwapped)
break;
}
}
if (ZONE_NOTIFYLIST) {
// Print out the new list
RETAILMSG (1, (_T("New list:\r\n")));
for (idx = 0; idx < nMods; idx ++) {
RETAILMSG (1, (_T("%02u: %s (%s)\r\n"), idx, ((PMODULE)pList[idx].hLib)->lpszModName,
IsShimDll ((PMODULE) pList[idx].hLib) ? _T("shim") : _T("normal")));
}
}
}
return TRUE;
}
void
ShimCloseModule(
PMODULE pMod
)
{
// Note: Most of pMod is invalid already (including lpszName)
DEBUGMSG (ZONE_ENTRY, (TEXT("++ShimCloseModule 0x%08x\r\n"), pMod));
if (pMod && pMod->pShimInfo) {
g_Imports.FreeMem (pMod->pShimInfo, HEAP_SHIMREF);
pMod->pShimInfo = NULL;
}
}
void
ShimCloseProcess(
HANDLE hProc
)
{
PMODULELIST pList;
LPSHIMINFO pShimInfo;
LPSHIMINFO pShimInfoTemp;
DEBUGMSG (ZONE_ENTRY, (TEXT("++ShimCloseProcess 0x%08x\r\n"), hProc));
// Walk the list of dll's, freeing up the list of applied shims, if needed.
for (pList = pCurProc->pLastModList; pList; pList = pList->pNext) {
if (pList->pMod->pShimInfo) {
pShimInfo = ((LPSHIMREF)pList->pMod->pShimInfo)->pShimInfo [pCurProc->procnum];
while (pShimInfo) {
pShimInfoTemp = pShimInfo;
pShimInfo = pShimInfo->pNext;
g_Imports.FreeMem (pShimInfoTemp, pShimInfoTemp->wPool);
}
((LPSHIMREF)pList->pMod->pShimInfo)->pShimInfo [pCurProc->procnum] = NULL;
}
}
}
BOOL static
DeInitLibrary(
FARPROC pfnKernelLibIoControl
)
{
VerifierExportTable exports;
// Zero out all the pointers to exported functions
memset (& exports, 0, sizeof (VerifierExportTable));
pfnKernelLibIoControl ((HANDLE) KMOD_VERIFIER, IOCTL_VERIFIER_REGISTER, & exports, sizeof (VerifierExportTable), NULL, 0, NULL);
return TRUE;
}
//------------------------------------------------------------------------------
// Hook up function pointers and initialize logging
//------------------------------------------------------------------------------
BOOL static
InitLibrary(
FARPROC pfnKernelLibIoControl
)
{
VerifierExportTable exports;
//
// KernelLibIoControl provides the back doors we need to obtain kernel
// function pointers and register logging functions.
//
// Get imports from kernel
g_Imports.dwVersion = VERIFIER_IMPORT_VERSION;
if (!pfnKernelLibIoControl((HANDLE)KMOD_VERIFIER, IOCTL_VERIFIER_IMPORT, &g_Imports,
sizeof(VerifierImportTable), NULL, 0, NULL)) {
// Can't DEBUGMSG or anything here b/c we need the import table to do that
return FALSE;
}
// Register logging functions with the kernel
exports.dwVersion = VERIFIER_EXPORT_VERSION;
exports.pfnShimInitModule = (FARPROC) ShimInitModule;
exports.pfnShimWhichMod = (FARPROC) ShimWhichMod;
exports.pfnShimUndoDepends = (FARPROC) ShimUnDoDepends;
exports.pfnShimGetProcModList = (FARPROC) ShimGetProcModList;
exports.pfnShimCloseModule = (FARPROC) ShimCloseModule;
exports.pfnShimCloseProcess = (FARPROC) ShimCloseProcess;
exports.pfnShimIoControl = (FARPROC) ShimIoControl;
if (!pfnKernelLibIoControl((HANDLE)KMOD_VERIFIER, IOCTL_VERIFIER_REGISTER, &exports,
sizeof(VerifierExportTable), NULL, 0, NULL)) {
RETAILMSG(1, (TEXT("Verifier: Unable to register logging functions with kernel\r\n")));
WIN32CALL(SetLastError, (ERROR_ALREADY_EXISTS));
return FALSE;
}
// Get coredll's flag indicating whether or not the process is exiting
hCoreDll = (HANDLE) g_Imports.LoadOneLibraryW (L"coredll.dll",LLIB_NO_PAGING,0);
pIsExiting = (LPDWORD) WIN32CALL(GetProcAddressA, (hCoreDll, (LPCSTR)159)); // IsExiting
// Get some string manipulation functions
#pragma warning (push)
#pragma warning (disable : 4047)
vrf_wcslen = WIN32CALL(GetProcAddressA, (hCoreDll, "wcslen"));
vrf_wcscpy = WIN32CALL(GetProcAddressA, (hCoreDll, "wcscpy"));
vrf_wcsncpy = WIN32CALL(GetProcAddressA, (hCoreDll, "wcsncpy"));
vrf_tolower = WIN32CALL(GetProcAddressA, (hCoreDll, "tolower"));
vrf_wcsnicmp = WIN32CALL(GetProcAddressA, (hCoreDll, "_wcsnicmp"));
vrf_wcsicmp = WIN32CALL(GetProcAddressA, (hCoreDll, "_wcsicmp"));
// Initialize the linked list cs
g_Imports.InitializeCriticalSection (& llcs);
if (!(vrf_wcslen && vrf_wcscpy && vrf_wcsncpy && vrf_tolower && vrf_wcsnicmp && vrf_wcsicmp)) {
RETAILMSG(1, (TEXT("--------------------------------------------------------------------------------\r\n")));
RETAILMSG(1, (TEXT("Shim engine not activated - error getting functions\r\n")));
RETAILMSG(1, (TEXT("--------------------------------------------------------------------------------\r\n")));
return FALSE;
}
#pragma warning (pop)
WIN32CALL(RegisterDbgZones, (gDllInstance, & dpCurSettings));
RETAILMSG(1, (TEXT("--------------------------------------------------------------------------------\r\n")));
RETAILMSG(1, (TEXT("Shim engine activated.\r\n")));
RETAILMSG(1, (TEXT("--------------------------------------------------------------------------------\r\n")));
g_fInit = TRUE;
return TRUE;
}
//------------------------------------------------------------------------------
// DLL entry
BOOL WINAPI
VerifierDLLEntry(HINSTANCE DllInstance, INT Reason, LPVOID Reserved)
{
switch (Reason) {
case DLL_PROCESS_ATTACH:
if (!g_fInit) {
// Reserved parameter is a pointer to KernelLibIoControl function
gDllInstance = DllInstance;
if (!InitLibrary((FARPROC)Reserved)) {
DeInitLibrary ((FARPROC)Reserved);
return FALSE;
}
}
break;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -