[求助]关于win10 x64下获取ssdt原始函数地址的问题(已解决)
最近在学习win64下的驱动编程, 想自己写一款ARK软件在坛主的<<WIN64驱动编程基础教程>> 中的关于SSDT UnHook获取SSDT原始函数地址的算法:
代码是这么实现的基本就是教程里的代码,我稍微改动了一些:
获取NtosBase的函数:
VOID CUtils::GetNtosBase(ULONGLONG& NtosBase, CHAR* NtosName)
{
char FileName = { 0 }, *FullName;
NtosBase = GetNtosBaseAndPath(FileName);
FullName = cs("C:\\Windows\\system32\\", FileName);
strcpy(NtosName, FullName);
printf("NTOSKRNL base: %llx\n", NtosBase);
printf("NTOSKRNL name: %s\n", NtosName);
}
获取NtosImageBase的函数
VOID CUtils::GetNtosImageBase(ULONGLONG&NtosImageBase, char* NtosName)
{
PIMAGE_NT_HEADERS64 pinths64;
PIMAGE_DOS_HEADER pdih;
char *NtosFileData = NULL;
NtosFileData = LoadDllContext(NtosName);
pdih = (PIMAGE_DOS_HEADER)NtosFileData;
pinths64 = (PIMAGE_NT_HEADERS64)(NtosFileData + pdih->e_lfanew);
NtosImageBase = pinths64->OptionalHeader.ImageBase;
printf("ImageBase: %llx\n", NtosImageBase);
free(NtosFileData);
}
最终获取原始函数地址的函数:
ULONGLONG CSSDTHookView::GetFunctionOriginalAddress(DWORD index)
{
//"C:\\Windows\\system32\\ntkrnlmp.exe"
if (NtosInProcess == 0)
NtosInProcess = (ULONGLONG)LoadLibraryExA(NtosName, 0, DONT_RESOLVE_DLL_REFERENCES);
if (KiServiceTable == 0)
{
DWORD dwRet = 0;
KiServiceTableAddr_INFO info;
DriverCtrl::GetInstance()->IoControl(0x807, 0, 0, &info, sizeof(KiServiceTableAddr_INFO), &dwRet);
if (dwRet <= 0)
{
MessageBox(L"获取KiServerTable地址失败", L"错误");
return 0;
}
KiServiceTable = info.addr;
}
ULONGLONG RVA = KiServiceTable - NtosBase;
ULONGLONG test = (NtosInProcess + RVA + 8 * (ULONGLONG)index);
ULONGLONG temp =*(PULONGLONG) (NtosInProcess + RVA + 8 * (ULONGLONG)index);
//IMAGE_OPTIONAL_HEADER64.ImageBase=0x140000000(这个值基本是固定的)
ULONGLONG RVA_index = temp - NtosImageBase;
return RVA_index + NtosBase;
}
我调试看了,其中的KiServiceTable的地址是没问题的, 这是一次我调试断点变量的值
NtosInProcess 7ff6f7ff0000
NtosBase fffff800e881e000
KiServiceTablefffff800e8b6d000
NtosImageBase 140000000
好像也都没什么问题,但是计算结果还有很大误差,我本机没有开任何可能hook ssdt(修该)函数地址的软件
下面是我的程序获取到的截图
这是我的系统版本信息
这个问题困扰我好几天了, 各种百度谷歌没有找到好的解决办法, 希望路过的大牛不吝赐教,指点一下, 先谢谢了!
从WIN10某版本开始获取原始地址的方法变化了。具体公式是:**** Hidden Message *****由于已转PHP开发,具体细节我记不清了。你应该用IDA看看。 简单说一下,win10x64th2及之前的版本,原始地址的保存方式是八字节的,每个地址是需要重定向的绝对地址,但从win10x64rs1开始,原始地址保存方式是四字节的,每个地址是不需要重定向的相对地址。
简单说公式就是
original_address=image_base+address_read_from_file
其中original_address和image_base是八字节整形,address_read_from_file是四字节整形
之前的公式是:
original_address=image_base+(address_read_from_file-file_image_base)
这四个变量都是八字节整形,括号内计算的是重定向 Tesla.Angela 发表于 2018-2-28 21:30
从WIN10某版本开始获取原始地址的方法变化了。具体公式是:**** 本内容被作者隐藏 ****由于已转PHP开发,具 ...
嗯, 你说的新公式我试了下是可以的,谢谢 tangptr@126.com 发表于 2018-2-28 23:39
简单说一下,win10x64th2及之前的版本,原始地址的保存方式是八字节的,每个地址是需要重定向的绝对地址, ...
嗯, 很佩服像你这样驾轻就熟的大牛,我用ida 查看 ntosknrl.exe ,找了半天也没找到KiServerTable它初始化函数地址的地方【类似下面这张图片展示的地方】
http://chuantu.biz/t6/240/1519876432x-1404764426.jpg
哎。。。, 这次算是从你这里直接拿了条鱼回家吧,万分感谢。
【分享】win10 x64通过读取ntoskrnl.exe文件获取ssdt函数原始
本帖最后由 T3Shell 于 2018-3-1 12:28 编辑感谢Tesla.Angela、tangptr 两位大大的解答
坛主在《WIN64驱动编程基础教程>》 中提到的关于SSDT UnHook获取SSDT原始函数地址的算法是这样的:
计算ssdt原始地址的关键算法是这样写的【代码大部分都是坛主和网友写的】
ULONGLONG CSSDTHookView::GetFunctionOriginalAddress(DWORD index)
{
//"C:\\Windows\\system32\\ntkrnlmp.exe"
if (NtosInProcess == 0)
NtosInProcess = (ULONGLONG)LoadLibraryExA(NtosName, 0, DONT_RESOLVE_DLL_REFERENCES);
if (KiServiceTable == 0)
{
DWORD dwRet = 0;
KiServiceTableAddr_INFO info;
DriverCtrl::GetInstance()->IoControl(0x807, 0, 0, &info, sizeof(KiServiceTableAddr_INFO), &dwRet);
if (dwRet <= 0)
{
MessageBox(L"获取KiServerTable地址失败", L"错误");
return 0;
}
KiServiceTable = info.addr;
}
ULONGLONG RVA = KiServiceTable - NtosBase;
ULONGLONG test = (NtosInProcess + RVA + 8 * (ULONGLONG)index);
ULONGLONG temp =*(PULONGLONG) (NtosInProcess + RVA + 8 * (ULONGLONG)index);
//IMAGE_OPTIONAL_HEADER64.ImageBase=0x140000000(这个值基本是固定的)
ULONGLONG RVA_index = temp - NtosImageBase;
return RVA_index + NtosBase;
}
但是最近我在测试最新的win10 x64(1709)版本的时候发现获取的地址不对,在论坛提问
原提问帖子地址: [求助]关于win10 x64下获取ssdt原始函数地址的问题
tangptrz 大大是这么说的:
简单说一下,win10x64th2及之前的版本,原始地址的保存方式是八字节的,每个地址是需要重定向的绝对地址,但从win10x64rs1开始,原始地址保存方式是四字节的,每个地址是不需要重定向的相对地址。
简单说公式就是
original_address=image_base+address_read_from_file
其中original_address和image_base是八字节整形,address_read_from_file是四字节整形
之前的公式是:
original_address=image_base+(address_read_from_file-file_image_base)
这四个变量都是八字节整形,括号内计算的是重定向
Tesla.Angela 则给出了新的计算公式
VA = KiServiceTable - NtosBase + ReloadedNtosBase;
OriAddr = getdword(VA+Index*4) + NtosBase;
我最终修正后的算法是这样的:
ULONGLONG CSSDTHookView::GetFunctionOriginalAddress(DWORD index)
{
//"C:\\Windows\\system32\\ntkrnlmp.exe"
if (NtosInProcess == 0)
NtosInProcess = (ULONGLONG)LoadLibraryExA(NtosName, 0, DONT_RESOLVE_DLL_REFERENCES);
if (KiServiceTable == 0)
{
DWORD dwRet = 0;
KiServiceTableAddr_INFO info;
DriverCtrl::GetInstance()->IoControl(0x807, 0, 0, &info, sizeof(KiServiceTableAddr_INFO), &dwRet);
if (dwRet <= 0)
{
MessageBox(L"获取KiServerTable地址失败", L"错误");
return 0;
}
KiServiceTable = info.addr;
}
ULONGLONG RVA = KiServiceTable - NtosBase;
ULONGLONG temp =*(PULONG) (NtosInProcess + RVA + 4 * (ULONGLONG)index);
//IMAGE_OPTIONAL_HEADER64.ImageBase=0x140000000(这个值基本是固定的)
ULONGLONG RVA_index = temp - NtosImageBase;
return temp + NtosBase;
}
图:
最后非常感谢论坛积极热心的朋友们的耐心解答, 希望以后能和大家一起学习交流进步
祝大家狗年大吉大利,哈哈哈
两条公式分别生效于不同的系统,需要区分版本号。
此外,同样的内容没必要分成两个主题帖。 我来看看吧 希望楼主发个完整的代码获取SSDT地址的 小白可以学习 T3Shell 发表于 2018-3-1 11:55
嗯, 很佩服像你这样驾轻就熟的大牛,我用ida 查看 ntosknrl.exe ,找了半天也没找到KiServerTable它初 ...
IDA有个功能叫jump by name的,直接输入KiServiceTable就行(对窗口凭空敲键盘)。如果没有就写_KiServiceTable 看下 学习下,谢谢开源 学习学习 win10 x64下获取ssdt 学习一下。 谢谢楼主 看下!!! 学习一下。。。 谢谢分析,看看 看看什么变化。 66666666666666666666 谢谢分享 看看隐藏的高级内容 谢谢 学习一下方法 看看公式 从哪个版本开始变的? 来看看回复 谢谢层主 66666666666 小白可以学习
我来看看吧 巩固一下
页:
[1]
2