SSDT Restore in ring0的部分代码

本文深入探讨了Windows内核模块的加载与解析过程,包括获取模块基本信息、映射图像文件、解析导出和导入表等内容,并提供了具体的实现代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NTSTATUS GetModuleBaseInformation(
IN PCHAR pModuleName,
OUT PSYSTEM_MODULE_INFORMATION psmi
)
{
PSYSTEM_MODULE_INFORMATION psmi2=0;
ULONG     i;
ULONG     uCount;
PCHAR     pName;
ULONG     dData;
PCHAR     BaseAddress=NULL;
NTSTATUS           rc;
ULONG      cbBuffer = 0x8000;
PVOID     pBuffer = NULL;

do
{
   pBuffer = ExAllocatePool (PagedPool, cbBuffer);
   if (pBuffer == NULL)
   {
    return rc;
   }
   rc = ZwQuerySystemInformation(
     SystemModuleInformation, pBuffer, cbBuffer, &dData);
   if (rc == STATUS_INFO_LENGTH_MISMATCH)
   {
    ExFreePool(pBuffer);
    cbBuffer *= 2;
   }
   else if (!NT_SUCCESS(rc))
   {
    ExFreePool(pBuffer);
    return rc;
   }
}
while (rc == STATUS_INFO_LENGTH_MISMATCH);

uCount = (ULONG) *( (PULONG) pBuffer);
psmi2 = (PSYSTEM_MODULE_INFORMATION)((ULONG)pBuffer+sizeof(ULONG));
for ( i = 0; i < uCount; i++ )
        {
        DbgPrint("%s/n", (psmi2->ImageName+psmi2->ModuleNameOffset));
       
        if(!_strnicmp(pModuleName, psmi2->ImageName+psmi2->ModuleNameOffset, strlen(pModuleName)))
        {
           *psmi = *psmi2;
           break;
        }
        psmi2 = (PSYSTEM_MODULE_INFORMATION)((ULONG)psmi2 + sizeof(SYSTEM_MODULE_INFORMATION));
        }
        ExFreePool(pBuffer);
return rc;
}

ULONG
NTAPI GetHeaders(
   PUCHAR ibase,
   PIMAGE_FILE_HEADER *pfh,
   PIMAGE_OPTIONAL_HEADER32 *poh,
   PIMAGE_SECTION_HEADER *psh
   )
{
NTSTATUS rc = STATUS_DEVICE_CONFIGURATION_ERROR;
  
__try {
   PIMAGE_DOS_HEADER mzhead=(PIMAGE_DOS_HEADER)ibase;
   if ( (mzhead->e_magic == IMAGE_DOS_SIGNATURE) &&  
    (ibaseDD[mzhead->e_lfanew] == IMAGE_NT_SIGNATURE) )
   {
    *pfh=(PIMAGE_FILE_HEADER)&ibase[mzhead->e_lfanew];
    if (((PIMAGE_NT_HEADERS)*pfh)->Signature==IMAGE_NT_SIGNATURE)
    {
     *pfh=(PIMAGE_FILE_HEADER)((PBYTE)*pfh+sizeof(IMAGE_NT_SIGNATURE));
     *poh=(PIMAGE_OPTIONAL_HEADER32)((PBYTE)*pfh+sizeof(IMAGE_FILE_HEADER));
     if ((*poh)->Magic==IMAGE_NT_OPTIONAL_HDR32_MAGIC)
     {
      *psh=(PIMAGE_SECTION_HEADER)((PBYTE)*poh+sizeof(IMAGE_OPTIONAL_HEADER32));
      rc = STATUS_SUCCESS;
     }
    }
   }
} __except(EXCEPTION_EXECUTE_HANDLER)
{
   return rc;  
}
return rc;
}

// searches for the specified api in the import table and returns its rva
ULONG
NTAPI FindImport(
   PUCHAR hModule,
   PUCHAR Exporter,
   PUCHAR ApiName
   )
{
PIMAGE_FILE_HEADER   pfh;
PIMAGE_OPTIONAL_HEADER   poh;
PIMAGE_SECTION_HEADER   psh;
PIMAGE_IMPORT_DESCRIPTOR pid;
PIMAGE_THUNK_DATA   ptd;
PIMAGE_IMPORT_BY_NAME   pibn;
__try {
   GetHeaders(hModule,&pfh,&poh,&psh);
   if (poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) {
    pid=(PIMAGE_IMPORT_DESCRIPTOR)RVATOVA(hModule,poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    __asm int 3
    while (pid->FirstThunk && (pid->FirstThunk<poh->SizeOfImage)) {
     if (!_stricmp((PCHAR)RVATOVA(hModule,pid->Name),Exporter)) {
      for (ptd=(PIMAGE_THUNK_DATA)RVATOVA(hModule,pid->FirstThunk);ptd->u1.Function;ptd++) {
       pibn=RVATOVA(hModule,ptd->u1.Function);
       if (!strcmp(pibn->Name,ApiName))
        return (ULONG)&ptd->u1.Function-(ULONG)hModule;
      }
     }
     pid++;
    }
   }
} __except(EXCEPTION_EXECUTE_HANDLER) {
}
return 0;
}

ULONG
NTAPI FindExport(
   PUCHAR hModule,
   PUCHAR ApiName
   )
{
PIMAGE_FILE_HEADER pfh;
PIMAGE_OPTIONAL_HEADER poh;
PIMAGE_SECTION_HEADER psh;
PIMAGE_EXPORT_DIRECTORY ped;
BOOL    bDumbLinker;
BOOL    bFindByOrdinal;
DWORD    i = 0;
DWORD    dwOrdinals = 0;
PDWORD    pName;
WORD    nOrdinal;
DWORD    dwFuncRva = 0;
DWORD    dwReturnRva = 0;
__try {
   bFindByOrdinal = ((DWORD)ApiName == (WORD)ApiName);
   GetHeaders(hModule,&pfh,&poh,&psh);
   if (poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) {
    ped = (PIMAGE_EXPORT_DIRECTORY)RVATOVA(hModule,poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    pName = (PDWORD)RVATOVA(hModule,ped->AddressOfNames);
    for (i=0;i<ped->NumberOfFunctions;i++,pName++) {
     bDumbLinker=FALSE;
     // hack to avoid access violation when addressing bad pointers:
     // some dumb linkers set NumberOfFunctions to the largest ordinal
     // and NumberOfNames to the real functions number.
     if (i*2+(DWORD)RVATOVA(hModule,ped->AddressOfNameOrdinals)==    
      (DWORD)RVATOVA(hModule,ped->Name)) {
      bDumbLinker=TRUE;
      break;
     }
     __try {
      nOrdinal = ((PWORD)RVATOVA(hModule,ped->AddressOfNameOrdinals))[i];
      dwFuncRva = ((PDWORD)(RVATOVA(hModule,ped->AddressOfFunctions)))[nOrdinal];
     } __except(EXCEPTION_EXECUTE_HANDLER) {
      bDumbLinker = TRUE;     
     }
     // don't want to mess up my stack
     if (bDumbLinker) break;
     nOrdinal += (WORD)ped->Base;
     if (!bFindByOrdinal && pName && i<ped->NumberOfNames) {     
      if (!strcmp(ApiName,(PCHAR)RVATOVA(hModule,*pName))) {
       dwReturnRva = dwFuncRva;
       break;
      }
     } else
      if (bFindByOrdinal && (nOrdinal==(WORD)ApiName)) {
       dwReturnRva = dwFuncRva;
       break;
      }    
    }   
   }
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
return dwReturnRva;
}

NTSTATUS LoadImage(
   IN PUCHAR ModuleName,
   OUT PMODULE_INFORMATION pmi
   )
{
NTSTATUS    rc = STATUS_DEVICE_CONFIGURATION_ERROR;
WCHAR     wSystemRoot[MAX_PATH+1];
UNICODE_STRING    uSystemRoot;
SYSTEM_MODULE_INFORMATION smi;
WCHAR     wFilePath[MAX_PATH+1];
PCHAR     PathName;
PCHAR     ImageName;
ANSI_STRING    AnsiPath;
UNICODE_STRING    UnicodePath;
PVOID     ptr2;

__try {
   rc = GetModuleBaseInformation(ModuleName, &smi);
   if (NT_SUCCESS(rc))
   {
    pmi->dwImageBase = smi.Base;
    RtlInitUnicodeString(&uSystemRoot, wSystemRoot);
    rc = GetSystemRoot(&uSystemRoot);  
    if (NT_SUCCESS(rc))
    {
     PathName = smi.ImageName + smi.ModuleNameOffset;
     ImageName = smi.ImageName;
     if (((PWORD)ImageName)[0]=='?//')
     {
      RtlInitAnsiString(&AnsiPath, ImageName);
      rc = RtlAnsiStringToUnicodeString(&UnicodePath, &AnsiPath, TRUE);
      if (NT_SUCCESS(rc))
      {
       _snwprintf((PWCHAR)&wFilePath, sizeof(wFilePath), L"%s",UnicodePath.Buffer);
       RtlFreeUnicodeString(&UnicodePath);
       rc = MapImage((PWCHAR)&wFilePath, pmi);
       if (NT_SUCCESS(rc)) {
        return rc;
       }
      }
     } else
     {
      rc = STATUS_DEVICE_CONFIGURATION_ERROR;
     }
     if (!NT_SUCCESS(rc))
     {
      RtlInitAnsiString(&AnsiPath, PathName);
      rc = RtlAnsiStringToUnicodeString(&UnicodePath, &AnsiPath, TRUE);
      if (NT_SUCCESS(rc))
      {
       _snwprintf((PWCHAR)&wFilePath, sizeof(wFilePath), L"%ssystem32//drivers//%s", (PWCHAR)&wSystemRoot, UnicodePath.Buffer);
       RtlFreeUnicodeString(&UnicodePath);
       rc = MapImage((PWCHAR)&wFilePath, pmi);
       if (NT_SUCCESS(rc)) {
        return rc;
       }
      }
     } if (!NT_SUCCESS(rc))
     {
      RtlInitAnsiString(&AnsiPath, PathName);
      rc = RtlAnsiStringToUnicodeString(&UnicodePath, &AnsiPath, TRUE);
      if (NT_SUCCESS(rc))
      {
       _snwprintf((PWCHAR)&wFilePath, sizeof(wFilePath), L"%ssystem32//%s", (PWCHAR)&wSystemRoot, UnicodePath.Buffer);
       RtlFreeUnicodeString(&UnicodePath);
       rc = MapImage((PWCHAR)&wFilePath, pmi);
       if (NT_SUCCESS(rc)) {
        return rc;
       }
      }
     }
    }
   }   
} __except(EXCEPTION_EXECUTE_HANDLER) {
   pmi->hModule=0;
}
if (!pmi->hModule)
   rc = STATUS_DEVICE_CONFIGURATION_ERROR;
return rc;
}

NTSTATUS MapImage(
   IN PWCHAR pwFileName,
   OUT PMODULE_INFORMATION pmi
   )
{
NTSTATUS    rc = STATUS_DEVICE_CONFIGURATION_ERROR;
UNICODE_STRING    uFileName;
OBJECT_ATTRIBUTES   oa;
IO_STATUS_BLOCK    iosb;
HANDLE     FileHandle;
FILE_STANDARD_INFORMATION fsi;
LARGE_INTEGER    ByteOffset;
PVOID     FilePool = 0;
PIMAGE_FILE_HEADER   pfh;
PIMAGE_OPTIONAL_HEADER   poh;
PIMAGE_SECTION_HEADER   psh;
ULONG     i;

__try {
   RtlInitUnicodeString(&uFileName, pwFileName);
   InitializeObjectAttributes(&oa,&uFileName,OBJ_CASE_INSENSITIVE,NULL,NULL);
   RtlZeroMemory(&iosb, sizeof(iosb));
   rc = ZwOpenFile(&FileHandle,
    GENERIC_READ | SYNCHRONIZE,
    &oa,
    &iosb,
    FILE_SHARE_READ,
    FILE_SYNCHRONOUS_IO_NONALERT
    );
   if (NT_SUCCESS(rc))
   {
    rc = ZwQueryInformationFile(FileHandle,&iosb,&fsi,sizeof(FILE_STANDARD_INFORMATION),FileStandardInformation);
    if (NT_SUCCESS(rc))
    {
     FilePool = ExAllocatePool(PagedPool,fsi.EndOfFile.LowPart);
     if (FilePool)
     {
      RtlZeroMemory(FilePool,fsi.EndOfFile.LowPart);
      ByteOffset.QuadPart = 0;
      rc = ZwReadFile(FileHandle,
        NULL,
        NULL,
        NULL,
        &iosb,
        FilePool,
        fsi.EndOfFile.LowPart,
        &ByteOffset,
        NULL);
      if (NT_SUCCESS(rc))
      {
       rc = GetHeaders(FilePool,&pfh,&poh,&psh);
       if (NT_SUCCESS(rc))
       {
        pmi->hModule=ExAllocatePool(PagedPool,poh->SizeOfImage);
        if (pmi->hModule)
        {
         RtlZeroMemory(pmi->hModule,poh->SizeOfImage);
         // copy header to the virtual image buffer
         memcpy(pmi->hModule,FilePool,poh->SizeOfHeaders);
         // copy sections
         for (i=0;i<pfh->NumberOfSections;i++,psh++)
          memcpy(pmi->hModule+psh->VirtualAddress,
           (PVOID)((ULONG)FilePool+(ULONG)psh->PointerToRawData),
           psh->SizeOfRawData);  
        }
       }
      }
      ExFreePool(FilePool);
     }
    }
    ZwClose(FileHandle);
   }  
} __except(EXCEPTION_EXECUTE_HANDLER) {
}
return rc;
}

NTSTATUS UnMapImage(
   OUT PMODULE_INFORMATION pmi
   )
{
NTSTATUS rc = STATUS_DEVICE_CONFIGURATION_ERROR;

__try {
   ExFreePool(pmi->hModule);
   RtlZeroMemory(pmi,sizeof(MODULE_INFORMATION));
} __except(EXCEPTION_EXECUTE_HANDLER) {
}
return rc;
}

ULONG SearchKiServiceTable(
   PUCHAR hModule,
   ULONG dwKSDT
   )
{
PIMAGE_FILE_HEADER   pfh;
PIMAGE_OPTIONAL_HEADER   poh;
PIMAGE_SECTION_HEADER   psh;
PIMAGE_BASE_RELOCATION   pbr;
PIMAGE_FIXUP_ENTRY   pfe;   
    DWORD     dwFixups=0;
    DWORD     i;
    DWORD     dwPointerRva;
    DWORD     dwPointsToRva;
    DWORD     dwKiServiceTable;
BOOL     bFirstChunk;

GetHeaders((char*)(PBYTE)hModule,&pfh,&poh,&psh);

// loop thru relocs to speed up the search
if ((poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) &&
        (!((pfh->Characteristics)&IMAGE_FILE_RELOCS_STRIPPED)))
        {
        pbr = (PIMAGE_BASE_RELOCATION)RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,hModule);
   bFirstChunk = TRUE;
        // 1st IMAGE_BASE_RELOCATION.VirtualAddress of ntoskrnl is 0
   while (bFirstChunk || pbr->VirtualAddress) {
               bFirstChunk=FALSE;
    pfe=(PIMAGE_FIXUP_ENTRY)((DWORD)pbr+sizeof(IMAGE_BASE_RELOCATION));
   
    for (i=0;i<(pbr->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))>>1;i++,pfe++) {
                   if (pfe->type==IMAGE_REL_BASED_HIGHLOW) {
                        dwFixups++;
                        dwPointerRva=pbr->VirtualAddress+pfe->offset;
                        // DONT_RESOLVE_DLL_REFERENCES flag means relocs aren't fixed
                        dwPointsToRva=*(PDWORD)((DWORD)hModule+dwPointerRva)-(DWORD)poh->ImageBase;
      // does this reloc point to KeServiceDescriptorTable.Base?
                        if (dwPointsToRva==dwKSDT) {
                            // check for mov [mem32],imm32. we are trying to find
                            // "mov ds:_KeServiceDescriptorTable.Base, offset _KiServiceTable"
                            // from the KiInitSystem.
                            if (*(PWORD)((DWORD)hModule+dwPointerRva-2)==0x05c7) {
                                 // should check for a reloc presence on KiServiceTable here
                                 // but forget it
                                 dwKiServiceTable=*(PDWORD)((DWORD)hModule+dwPointerRva+4)-poh->ImageBase;
                                 return dwKiServiceTable;
                            }
                        }
                   } else if (pfe->type!=IMAGE_REL_BASED_ABSOLUTE)
                           // should never get here
                           DbgPrint("/trelo type %d found at .%X/n",pfe->type,pbr->VirtualAddress+pfe->offset);
               }
               *(PDWORD)&pbr+=pbr->SizeOfBlock;
        }
}   
if (!dwFixups)
        // should never happen - nt, 2k, xp kernels have relocation data
        DbgPrint("No fixups!/n");
    return 0;
}

NTSTATUS FindKiSystemService(
   PDWORD _KiServiceTable
   )
{
SYSTEM_MODULE_INFORMATION smi;
MODULE_INFORMATION   mi;
NTSTATUS    rc = STATUS_DEVICE_CONFIGURATION_ERROR;
ULONG     RVAKiSystemService = 0;
ULONG     RVATableShadow = 0;

__try {
   *_KiServiceTable = 0;
   rc = LoadImage("ntoskrnl.exe", &mi);
   if (NT_SUCCESS(rc)) {
    RVAKiSystemService = FindExport(mi.hModule,"KeServiceDescriptorTable");
        if (RVAKiSystemService != 0) {
         *_KiServiceTable = SearchKiServiceTable(mi.hModule,RVAKiSystemService);
           }
           RVATableShadow = FindExport(mi.hModule,"KeAddSystemServiceTable");
        if (RVATableShadow != 0) {
         *_KiServiceTable = (ULONG)GetKeServiceDescriptorTableShadow((PUCHAR)mi.hModule + RVATableShadow);
        }
            
    UnMapImage(&mi);
   }
} __except(EXCEPTION_EXECUTE_HANDLER) {
}
return rc;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值