admin 发表于 2009-12-12 23:49:53

恢复 SSDT

// 只贴 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;

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 >> 12) == 3 )
   {
      PULONG RefAddr = (PULONG)(ImageBase + RefBlock + (pRelItem & 0x0FFF));
   
      // 验证内存是否有效
      if ( !IsBadReadPtr(RefAddr, 1) && RefAddr == 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; // 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;

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.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));
    if ( strcmp(pName, "KeServiceDescriptorTable") == 0 )
    {
   ULONG _KiServiceTable, _KeServiceDescriptorTable; // 类型都是 va
   
   _KiServiceTable = 0;
   _KeServiceDescriptorTable = pNtH->OptionalHeader.ImageBase + pFunAddr];
   
   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 - 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;
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
页: [1]
查看完整版本: 恢复 SSDT