标 题: 【原创】寻找原始表,恢复 ssdt 表 作 者: dummy 时 间: 2007-08-17,19:28 链 接: http://bbs.pediy.com/showthread.php?t=49848 // 只贴 ring3 部分,这也是最主要的代码,驱动只是负责把得到的原始值写到 ssdt,其他啥也不做 // 简单说一下,找 KiServiceTable 表过程, 是直接读取原始内核文件,寻找输出符号,然后结合重定位信息,谁向 KeServiceDescriptorTable 赋值,从而确定 KiServiceTable 的位置。 // 这是第一写驱动相关的代码,写的很挫,高手就不用看了。 #include <tchar.h> #include <Windows.h> #include <winioctl.h> #include "RSSDT.h" /* // RSSDT.h typedef struct _tagSST_ENTRY { ULONG cbSize; ULONG Index; ULONG OrgValue; // 类型 RVA, 传给驱动的时做 Set Value ULONG NowValue; // 类型 RVA, 传给驱动做 get value } SST_ENTRY, *PSST_ENTRY; #define IOCTL_RSSDT_ENTRY_SET CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) */ ULONG Rav2Raw(PVOID pFileData, ULONG rav) { PIMAGE_DOS_HEADER pDosH; PIMAGE_NT_HEADERS pNtH; PIMAGE_SECTION_HEADER pSectH; ULONG Index; pDosH = (PIMAGE_DOS_HEADER)pFileData; pNtH = (PIMAGE_NT_HEADERS)((ULONG)pFileData + pDosH->e_lfanew); pSectH = IMAGE_FIRST_SECTION(pNtH); if ( rav >= 0 && rav < pSectH->VirtualAddress ) return rav; for ( Index = 0; Index < pNtH->FileHeader.NumberOfSections; Index++ ) { if ( rav >= pSectH->VirtualAddress && rav < pSectH->VirtualAddress + pSectH->Misc.VirtualSize ) return rav - pSectH->VirtualAddress + pSectH->PointerToRawData; pSectH++; } return (ULONG)-1; } PVOID NTAPI GetImageDirEntry( IN ULONG ImageBase, IN ULONG DirIndex, OUT OPTIONAL PIMAGE_NT_HEADERS* ppNtH, OUT OPTIONAL PIMAGE_DATA_DIRECTORY* ppDataDir ) { PIMAGE_DOS_HEADER pDosH; PIMAGE_NT_HEADERS pNtH; PIMAGE_DATA_DIRECTORY pDataDir; pDosH = (PIMAGE_DOS_HEADER)ImageBase; if ( pDosH->e_magic != IMAGE_DOS_SIGNATURE ) { return NULL; } pNtH = (PIMAGE_NT_HEADERS)(ImageBase + pDosH->e_lfanew); if ( pNtH->Signature != IMAGE_NT_SIGNATURE ) { return NULL; } if ( ppNtH != NULL ) { *ppNtH = pNtH; } pDataDir = &pNtH->OptionalHeader.DataDirectory[DirIndex]; if ( pDataDir->VirtualAddress == 0 ) { return NULL; } if ( ppDataDir != NULL ) { *ppDataDir = pDataDir; } return (PVOID)(ImageBase + Rav2Raw((PVOID)ImageBase, pDataDir->VirtualAddress)); } typedef BOOLEAN (NTAPI* LOOPUPXREF_CALLBACK)(PULONG RefAddr, PVOID Param); ULONG NTAPI // 返回找到的引用个数 pLookupImageXRef( IN ULONG ImageBase, // 参考地址 IN PIMAGE_DATA_DIRECTORY pBrDir, IN PIMAGE_BASE_RELOCATION pBr, IN ULONG SymAddr, IN LOOPUPXREF_CALLBACK LookupXRefCallback, // 回调 IN PVOID pParam ) { ULONG nRefCount = 0; __try { ULONG Size = 0; while ( pBr->SizeOfBlock != 0 && Size < pBrDir->Size ) { PWORD pRelItem = (PWORD)(pBr + 1); PIMAGE_BASE_RELOCATION pNextBr = (PIMAGE_BASE_RELOCATION)((ULONG)pBr + pBr->SizeOfBlock); while ( (ULONG)pRelItem < (ULONG)pNextBr ) { ULONG RefBlock = Rav2Raw((PVOID)ImageBase, pBr->VirtualAddress); if ( (pRelItem[0] >> 12) == 3 ) { PULONG RefAddr = (PULONG)(ImageBase + RefBlock + (pRelItem[0] & 0x0FFF)); // 验证内存是否有效 if ( !IsBadReadPtr(RefAddr, 1) && RefAddr[0] == SymAddr ) { nRefCount++; if ( LookupXRefCallback(RefAddr, pParam) ) break; } } pRelItem++; } Size += pBr->SizeOfBlock; pBr = pNextBr; } } __except ( EXCEPTION_EXECUTE_HANDLER ) { // DbgPrint("pLookupImageXRef: Found a Exception!/n"); } return nRefCount; } ULONG NTAPI LookupImageXRef( IN ULONG ImageBase, // 有效地址 IN ULONG SymAddr, IN LOOPUPXREF_CALLBACK LookupXRefCallback, // 回调 IN PVOID Param ) { if ( LookupXRefCallback != NULL ) { PIMAGE_DATA_DIRECTORY pBrDir; PIMAGE_BASE_RELOCATION pBr; pBr = GetImageDirEntry(ImageBase, IMAGE_DIRECTORY_ENTRY_BASERELOC, NULL, &pBrDir); if ( pBr != NULL ) { return pLookupImageXRef(ImageBase, pBrDir, pBr, SymAddr, LookupXRefCallback, Param); } } return 0; } typedef struct tag_SYSTEM_SERVICE_TABLE { PULONG ServiceTable; // array of entry points PULONG CounterTable; // array of usage counters ULONG ServiceLimit; // number of table entries PCHAR ArgumentTable; // array of argument counts } SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE, **PPSYSTEM_SERVICE_TABLE; BOOLEAN WINAPI LookXRefCallback(PULONG pRefAddr, PVOID pParam) { USHORT OpCode = *((PUSHORT)pRefAddr - 1); if ( OpCode == 0x05C7 ) // mov ds:_KeServiceDescriptorTable, offset _KiServiceTable { if ( pParam != NULL ) { *(PULONG)pParam = pRefAddr[1]; // KiServiceTable } return FALSE; } return TRUE; } BOOL GetSSTEntry(PCTSTR pszServiceName, PSST_ENTRY pSSTEntry) { HANDLE hFile, hFileMap; LPVOID pFileData; HMODULE hNtdll; FARPROC pfnService; BOOL bResult; TCHAR szNtoskrnlPath[MAX_PATH]; hNtdll = GetModuleHandle(_T("ntdll.dll")); pfnService = GetProcAddress(hNtdll, pszServiceName); if ( pfnService == NULL || *(PBYTE)pfnService != 0xB8 ) return FALSE; // mov eax, ?? pSSTEntry->Index = *(PULONG)((PBYTE)pfnService + 1); GetSystemDirectory(szNtoskrnlPath, MAX_PATH); _tcscat(szNtoskrnlPath, _T("//ntoskrnl.exe")); // or ntkrnlpa.exe hFile = CreateFile(szNtoskrnlPath, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if ( hFile == INVALID_HANDLE_VALUE ) return FALSE; hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); CloseHandle(hFile); if ( hFileMap == NULL ) return FALSE; pFileData = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0); CloseHandle(hFileMap); if ( NULL == pFileData ) return FALSE; bResult = FALSE; __try { PIMAGE_DOS_HEADER pDosH; PIMAGE_NT_HEADERS pNtH; PIMAGE_EXPORT_DIRECTORY pExpDir; PULONG pFunName, pFunAddr; PUSHORT pFunNameOrd; ULONG Index; pDosH = (PIMAGE_DOS_HEADER)pFileData; pNtH = (PIMAGE_NT_HEADERS)((ULONG)pFileData + pDosH->e_lfanew); pExpDir = (PIMAGE_EXPORT_DIRECTORY)((ULONG)pFileData + pNtH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); pFunName = (PULONG)((ULONG)pFileData + Rav2Raw(pFileData, pExpDir->AddressOfNames)); pFunNameOrd = (PUSHORT)((ULONG)pFileData + Rav2Raw(pFileData, pExpDir->AddressOfNameOrdinals)); pFunAddr = (PULONG)((ULONG)pFileData + Rav2Raw(pFileData, pExpDir->AddressOfFunctions)); for ( Index = 0; Index < pExpDir->NumberOfNames; Index++ ) { PCSTR pName = (PCSTR)((ULONG)pFileData + Rav2Raw(pFileData, pFunName[Index])); if ( strcmp(pName, "KeServiceDescriptorTable") == 0 ) { ULONG _KiServiceTable, _KeServiceDescriptorTable; // 类型都是 va _KiServiceTable = 0; _KeServiceDescriptorTable = pNtH->OptionalHeader.ImageBase + pFunAddr[pFunNameOrd[Index]]; LookupImageXRef((ULONG)pFileData, _KeServiceDescriptorTable, LookXRefCallback, &_KiServiceTable); if ( _KiServiceTable != 0 ) { PULONG ServiceTable; _KiServiceTable -= pNtH->OptionalHeader.ImageBase; ServiceTable = (PULONG)((ULONG)pFileData + Rav2Raw(pFileData, _KiServiceTable)); pSSTEntry->OrgValue = ServiceTable[pSSTEntry->Index] - pNtH->OptionalHeader.ImageBase; } bResult = TRUE; break; } } } __except ( EXCEPTION_EXECUTE_HANDLER ) { bResult = FALSE; } UnmapViewOfFile(pFileData); return bResult; } HANDLE GetServiceByName(IN PCTSTR pszServiceName, OUT OPTIONAL SC_HANDLE* pScManager) { SC_HANDLE hScManager, hScService; hScService = NULL; hScManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if ( pScManager != NULL ) *pScManager = hScManager; if ( hScManager != NULL ) { hScService = OpenService(hScManager, pszServiceName, SERVICE_ALL_ACCESS); if ( pScManager == NULL ) CloseServiceHandle(hScManager); } return hScService; } SC_HANDLE InstallDriver(IN PCTSTR pszServiceName, IN PCTSTR pszDriverFile) { SC_HANDLE hScManager, hScService; hScManager = NULL; hScService = GetServiceByName(pszServiceName, &hScManager); if ( hScService == NULL && hScManager != NULL ) { hScService = CreateService(hScManager, pszServiceName, pszServiceName, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, pszDriverFile, NULL, NULL, NULL, NULL, NULL ); // GetLastError(); } if ( hScManager != NULL ) CloseServiceHandle(hScManager); return hScService; } BOOL UninstallDriver(SC_HANDLE hScService) { SERVICE_STATUS Status; if ( ControlService(hScService, SERVICE_CONTROL_STOP, &Status) ) { DeleteService(hScService); CloseServiceHandle(hScService); return TRUE; } // GetLastError(); return FALSE; } BOOL ResetSSTEntry(PCSTR lpServiceName) { SC_HANDLE hScService; HANDLE hDevice; SST_ENTRY SstEntry; ULONG cbReturn; TCHAR szDriverPath[MAX_PATH]; PTSTR pszDriverName; BOOL bResult; SstEntry.cbSize = sizeof (SST_ENTRY); if ( !GetSSTEntry(lpServiceName, &SstEntry) ) return FALSE; GetModuleFileName(NULL, szDriverPath, MAX_PATH); pszDriverName = _tcsrchr(szDriverPath, _T('//')); _tcscpy(pszDriverName, _T("//RSSDT.sys")); hScService = GetServiceByName(_T("RSSDT"), NULL); if ( hScService == NULL ) { hScService = InstallDriver(_T("RSSDT"), szDriverPath); if ( hScService == NULL ) return FALSE; } bResult = FALSE; if ( StartService(hScService, 0, NULL) || GetLastError() == ERROR_ALREADY_EXISTS ) { hDevice = CreateFile(_T("////.//RSSDT"), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); GetLastError(); if ( hDevice != INVALID_HANDLE_VALUE ) { bResult = DeviceIoControl(hDevice, IOCTL_RSSDT_ENTRY_SET, &SstEntry, sizeof (SstEntry), &SstEntry, sizeof (SstEntry), &cbReturn, NULL); CloseHandle(hDevice); } } UninstallDriver(hScService); return bResult; } #if 1 int __cdecl main() { ResetSSTEntry("NtCreateKey"); ResetSSTEntry("NtCreatePagingFile"); ResetSSTEntry("NtEnumerateValueKey"); ResetSSTEntry("NtOpenKey"); ResetSSTEntry("NtQueryKey"); ResetSSTEntry("NtQueryValueKey"); ResetSSTEntry("NtSetSystemPowerState"); return 0; } #endif