获取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原始函数地址的主要内容,如果未能解决你的问题,请参考以下文章
Windows 逆向使用 CE 工具挖掘关键数据内存真实地址 ( 查找子弹数据的动态地址 | 查找子弹数据的静态地址 | 静态地址分析 | 完整流程 ) ★