获取SSDT,SSSDT原始函数地址

Posted zhuhuibeishadiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了获取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[827] = 0;
ULONGLONG	g_w32pServiceTable = 0;
ULONGLONG		K = 0;
ULONG64		 ulBaseDll = 0; 
PLOADED_IMAGE  ploadImage = 0; 
int  i = 0;

typedef struct _SHADOWFUNC  
  
  CHAR FuncName[100];  
  ULONG64 FuncAddr;  
  
SHADOWFUNC, *PSHADOWFUNC;  

SHADOWFUNC  g_ShadowFunc[827] = 0; 

BOOL IsExist(ULONGLONG pSystemAdd)

	int		i = 0;
	BOOL	exist = FALSE;

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


BOOL CALLBACK SymEnumSymbolsProc(  
                 PSYMBOL_INFO  pSymInfo,  
                 ULONG  SymbolSize,  
                 PVOID64  UserContext
                 )  
  
		if(IsExist((ULONGLONG)pSymInfo->Address))
		
			printf("0x%llx\\t%s\\n",(ULONGLONG)pSymInfo->Address,pSymInfo->Name);			
		
  return TRUE;  
  
 
BOOL CALLBACK SymEnumSymbolsProcForTable(  
                 PSYMBOL_INFO  pSymInfo,  
                 ULONG  SymbolSize,  
                 PVOID64  UserContext
                 )  
  	
	if(strcmp("W32pServiceTable",pSymInfo->Name)==0)
	
		*(PULONG64)UserContext = pSymInfo->Address;
		printf("W32pServiceTable:%llx\\n",pSymInfo->Address);
	
  return TRUE;  
  

BOOL CALLBACK SymEnumSymbolsProcTest(  
                 PSYMBOL_INFO  pSymInfo,  
                 ULONG  SymbolSize,  
                 PVOID64  UserContext
                 )  
  
	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[i].FuncAddr = (ULONG64)pSymInfo->Address;  
				lstrcpynA(g_ShadowFunc[i].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[0] = 0xFFFFF97FFF0DC4EC;
      sssdt[1] = 0xFFFFF97FFF0D5070;
	  sssdt[2] = 0xFFFFF97FFF077FA0;
	  sssdt[3] = 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[128*8];
	  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[n],(LPSTR)chName,MAX_PATH);
			  if(strcmp("win32k.sys",chName)==0)
			  
				  dwBaseAddr = (DWORD64)pDrvAddr[n];
				  //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[i].FuncAddr, g_ShadowFunc[i].FuncName); 
		  printf("%d\\t0x%llx\\t\\t%s\\n",i,g_ShadowFunc[i].FuncAddr - ulBaseDll + (ULONG64)dwBaseAddr,g_ShadowFunc[i].FuncName);
		  K++;
		  if(K==100)
		  
			  K = 0;
			  printf("\\nInput [Enter] Continue running...\\n\\n");
			  getchar();
		  
		
	   
	  ImageUnload(ploadImage);  
	  SymCleanup(hHandle);  
	  printf("\\nThe current system consists of %d functions\\n\\n",i);
	  printf("Input [Enter] 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_IMAGE  ploadImage = 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.dll   symsrv.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

测试图:


以上是关于获取SSDT,SSSDT原始函数地址的主要内容,如果未能解决你的问题,请参考以下文章

09SSDT概述

YJX_Driver_017_需要具备的理论知识

如何获得SSDT地址

Windows 逆向使用 CE 工具挖掘关键数据内存真实地址 ( 查找子弹数据的动态地址 | 查找子弹数据的静态地址 | 静态地址分析 | 完整流程 ) ★

windbg查找Kernel32.dll基址

基址简述