多维时空 发表于 2017-6-1 13:32:38

获取SSDT,SSSDT原始函数地址

SSSDT的原始地址新的获取方法
时至今日发现我x64 下win32k.sys中W32pServiceTable是导出的... 一直没注意...


SSDT
当前函数地址 = KiSeviceTable + *(KiServiceTalbe + index * 4);
TableRVA = KiSeviceTable - 内核真实加载地址 ;
ImageBase = 0x140000000;(理想加载地址)
ImageKiSeviceTable = ImageBase + TableRVA;
LoadDLLBase = LoadLibrary("内核文件");


x64下 如果内核文件是以理想地址加载(0x140000000)的话那么在KiServiceTable里面的的地址就是理想函数地址
比如:NtReadFile 它在KiServiceTable下的0x18处(index = 4) 那么这个KiserviectTable+0x18位置处存储的就是NtReadFile地址,只不过它是理想地址
思路:我们首先得到基于PE镜像基址的KiServieTalbe的RVA
我们程序直接加载内核文件到进程(LoadLibrary或者映射文件),这个时候我们得到加载到进程的内核Base
这个Base + RVA 就是进程内存中的KiServieTable的地址
我们读这个地址的值(得到了基于理想地址的函数地址) 然后减去理想加载地址就得到了函数与内核加载地址的RVA
这个RVA在跟真实的内核加载地址相加就得到了原始的函数地址
这上面是SSDT--SSSDT一致 需要注意的是相对文件偏移和相对内存偏移
我这里使用符号获取SSSDT名
关于符号解析请看我上一篇文章
代码实现 查看SSSDT原始函数地址
一次显示100个 一共有837个

#include <windows.h>
#include <stdio.h>
#include <Dbghelp.h>
#include <psapi.h>

#pragma comment(lib, "Dbghelp.lib")
#pragma comment(lib, "Imagehlp.lib")

//去除警告
PLOADED_IMAGE
    IMAGEAPI
    ImageLoad(
    PCSTR DllName,
    PCSTR DllPath
    );

BOOL   
    IMAGEAPI   
    ImageUnload(
    PLOADED_IMAGE LoadedImage   
    );

BOOL MapAndLoad(
    PSTR          ImageName,
    PSTR          DllPath,
    PLOADED_IMAGE LoadedImage,
    BOOL          DotDll,
    BOOL          ReadOnly
);

BOOL UnMapAndLoad(
    PLOADED_IMAGE LoadedImage
);

//SSSDT函数地址
ULONGLONG   sssdt = {0};
ULONGLONG        g_w32pServiceTable = 0;
ULONGLONG                K = 0;
ULONG64               ulBaseDll = 0;
PLOADED_IMAGEploadImage = {0};
inti = 0;

typedef struct _SHADOWFUNC
{
CHAR FuncName;
ULONG64 FuncAddr;

}SHADOWFUNC, *PSHADOWFUNC;

SHADOWFUNCg_ShadowFunc = {0};

BOOL IsExist(ULONGLONG pSystemAdd)
{
        int                i = 0;
        BOOL        exist = FALSE;

        for(i = 0;i < 827; i++)
        {
                if(sssdt == pSystemAdd)
                {
                        exist = TRUE;
                }
        }
        return exist;
}

BOOL CALLBACK SymEnumSymbolsProc(
               PSYMBOL_INFOpSymInfo,
               ULONGSymbolSize,
               PVOID64UserContext
               )
{
                if(IsExist((ULONGLONG)pSymInfo->Address))
                {
                        printf("0x%llx\t%s\n",(ULONGLONG)pSymInfo->Address,pSymInfo->Name);                       
                }
return TRUE;
}

BOOL CALLBACK SymEnumSymbolsProcForTable(
               PSYMBOL_INFOpSymInfo,
               ULONGSymbolSize,
               PVOID64UserContext
               )
{       
        if(strcmp("W32pServiceTable",pSymInfo->Name)==0)
        {
                *(PULONG64)UserContext = pSymInfo->Address;
                printf("W32pServiceTable:%llx\n",pSymInfo->Address);
        }
return TRUE;
}

BOOL CALLBACK SymEnumSymbolsProcTest(
               PSYMBOL_INFOpSymInfo,
               ULONGSymbolSize,
               PVOID64UserContext
               )
{
        PULONGLONG temp = 0;
       
        if(UserContext == 0)//获取w32p
        {
                if(strcmp("W32pServiceTable",pSymInfo->Name)==0)
                {
                        //printf("W32pServiceTable:%llx\n\n",pSymInfo->Address);
                        g_w32pServiceTable = pSymInfo->Address;
                }
        }else
        {
                temp = (PULONGLONG)UserContext;

                for (i = 0; i < 827; i++)
                {
                       if ((ULONG64)*(temp + i) == (ULONG64)pSymInfo->Address)
                       {
                                g_ShadowFunc.FuncAddr = (ULONG64)pSymInfo->Address;
                                lstrcpynA(g_ShadowFunc.FuncName, pSymInfo->Name, 100);   
                                //printf("i:%d---Address:%llx,Name:%s\n",i,(ULONG64)pSymInfo->Address,&pSymInfo->Name);
                       }
                }
               
        }
return TRUE;
}

//这个用来测试用的
void OrigFunction()
{
          HANDLE               hHandle = 0;
          
          

          hHandle = GetCurrentProcess();
          printf("Are enumerated symbolic...\n\n");
          SymInitialize(hHandle, NULL, TRUE);
          ploadImage = ImageLoad("win32k.sys", NULL);
          sssdt = 0xFFFFF97FFF0DC4EC;
      sssdt = 0xFFFFF97FFF0D5070;
          sssdt = 0xFFFFF97FFF077FA0;
          sssdt = 0xFFFFF97FFF085510;
          ulBaseDll = SymLoadModule64(hHandle,\
                                                                  ploadImage->hFile,\
                                                                  "win32k.sys",\
                                                                  "win32k.pdb",\
                                                                  0,\
                                                                  ploadImage->SizeOfImage);
          printf("SSSDTFunctionAddr\tSSSDTFunctionName\n");
          printf("------------------\t------------------\n");
          SymEnumSymbols(hHandle,\
                                       ulBaseDll,\
                                       NULL,\
                                       SymEnumSymbolsProc,\
                                     NULL);
          printf("\nEnumerations end of symbols...\n");
          ImageUnload(ploadImage);
          SymCleanup(hHandle);
          getchar();
}

void GetOrigSSSDTAddr()
{
          HANDLE               hHandle = 0;
          PVOID                     pDrvAddr;
          DWORD                     dwcbNeeded=0,n=0;
          DWORD64               dwBaseAddr = 0;
          CHAR         *chName=(CHAR*)malloc(260);

          SetConsoleTitleA("GetSSSDTOriginalFunctionAddrForWin7x64R3");

          if (EnumDeviceDrivers(pDrvAddr,sizeof(pDrvAddr),&dwcbNeeded))
          {
                  for (n=0 ; n<(dwcbNeeded/8) ; n++)
                  {
                          GetDeviceDriverBaseNameA(pDrvAddr,(LPSTR)chName,MAX_PATH);
                          if(strcmp("win32k.sys",chName)==0)
                          {
                                  dwBaseAddr = (DWORD64)pDrvAddr;
                                  //printf("%s 0x%llx\n\n",chName,(DWORD64)dwBaseAddr);
                                  free(chName);
                                  break;
                          }
                  }
          }


          hHandle = GetCurrentProcess();
          printf("Are enumerated symbolic...\n\n");
          SymInitialize(hHandle, NULL, TRUE);
          ploadImage = ImageLoad("win32k.sys", NULL);
          ulBaseDll = SymLoadModule64(hHandle,\
                                                                  ploadImage->hFile,\
                                                                  "win32k.sys",\
                                                                  "win32k.pdb",\
                                                                  0,\
                                                                  ploadImage->SizeOfImage);
          SymEnumSymbols(hHandle,\
                                       ulBaseDll,\
                                       NULL,\
                                       SymEnumSymbolsProcTest,\
                                     NULL);
          if(g_w32pServiceTable!=0)
          {
                  printf("Index\tSSSDTFunctionAddr\t\tSSSDTFunctionName\n");
                  printf("----\t------------------\t\t------------------\n");
                  //printf("g_w32pServiceTable:%llx ------ulBaseDll:%llx-------MappedAddr:%llx\n",g_w32pServiceTable,ulBaseDll,ploadImage->MappedAddress);
                  //getchar();
                  g_w32pServiceTable = g_w32pServiceTable - (ULONG64)ulBaseDll + (ULONG64)ploadImage->MappedAddress;
                  g_w32pServiceTable = g_w32pServiceTable - (ULONG64)0xc00;//ida中是以相对内存偏移对齐(1000)--内存映射是以相对稳健偏移对齐(400)1000-400=0xc00
                  SymEnumSymbols(hHandle,ulBaseDll,NULL,SymEnumSymbolsProcTest,(PVOID64)g_w32pServiceTable);
          }

          for (i = 0; i < 827; i++)
          {
                  //printf("%d\t0x%llx\t\t%s\n", i, g_ShadowFunc.FuncAddr, g_ShadowFunc.FuncName);
                  printf("%d\t0x%llx\t\t%s\n",i,g_ShadowFunc.FuncAddr - ulBaseDll + (ULONG64)dwBaseAddr,g_ShadowFunc.FuncName);
                  K++;
                  if(K==100)
                  {
                          K = 0;
                          printf("\nInput Continue running...\n\n");
                          getchar();
                  }
               
          }
          ImageUnload(ploadImage);
          SymCleanup(hHandle);
          printf("\nThe current system consists of %d functions\n\n",i);
          printf("Input Exit...\n");
          getchar();
}
//运行会很慢,
//需要的符号文件
//dbghelp.pdb
//imagehlp.pdb
//kernel32.pdb
//kernelbase.pdb
//msvcr110d.amd64.pdb
//msvcrt.pdb
//ntdll.pdb
//win32k.pdb
//首次运行成功后,在同目录下sym文件中可以找到相应的pdb文件,复制到同目录即可.

//这个是传入地址给出名称
void GetImageW32pSeviceTable(PULONG64 pW32SeviceTableAddr)
{
          HANDLE               hHandle = 0;
          ULONG64               ulBaseDll = 0;
          PLOADED_IMAGEploadImage = {0};

          hHandle = GetCurrentProcess();
          printf("Are enumerated symbolic...\n\n");
          SymInitialize(hHandle, NULL, TRUE);
          ploadImage = ImageLoad("win32k.sys", NULL);
          ulBaseDll = SymLoadModule64(hHandle,\
                                                                  ploadImage->hFile,\
                                                                  "win32k.sys",\
                                                                  "win32k.pdb",\
                                                                  0,\
                                                                  ploadImage->SizeOfImage);
          SymEnumSymbols(hHandle,\
                                       ulBaseDll,\
                                       NULL,\
                                       SymEnumSymbolsProcForTable,\
                                       pW32SeviceTableAddr);
          printf("\nEnumerations end of symbols...\n");
          ImageUnload(ploadImage);
          SymCleanup(hHandle);
}


void main()
{
          GetOrigSSSDTAddr();
          return;
}

我在测试中并没有将
dbghelp.dllsymsrv.dll 放到exe目录

如果不能正常输出,可以到windbg目录下复制过来
如果还不没有效果,检测了自己网络没有问题后
添加环境变量
变量名:_NT_SYMBOL_PATH
变量值:SRV*{$Path}*http://msdl.microsoft.com/download/symbols/
将“{$Path}”替换为要存储pdb符号表文件的路径,比如:C:\PDB,在线的符号下载。

参考:http://www.cnblogs.com/lanrenxinxin/p/4513464.html
测试图:
页: [1]
查看完整版本: 获取SSDT,SSSDT原始函数地址