T3Shell 发表于 2018-2-28 14:35:47

[求助]关于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(修该)函数地址的软件
下面是我的程序获取到的截图


这是我的系统版本信息






这个问题困扰我好几天了, 各种百度谷歌没有找到好的解决办法, 希望路过的大牛不吝赐教,指点一下, 先谢谢了!

Tesla.Angela 发表于 2018-2-28 21:30:59

从WIN10某版本开始获取原始地址的方法变化了。具体公式是:**** Hidden Message *****由于已转PHP开发,具体细节我记不清了。你应该用IDA看看。

tangptr@126.com 发表于 2018-2-28 23:39:15

简单说一下,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)
这四个变量都是八字节整形,括号内计算的是重定向

T3Shell 发表于 2018-3-1 11:49:47

Tesla.Angela 发表于 2018-2-28 21:30
从WIN10某版本开始获取原始地址的方法变化了。具体公式是:**** 本内容被作者隐藏 ****由于已转PHP开发,具 ...

嗯, 你说的新公式我试了下是可以的,谢谢

T3Shell 发表于 2018-3-1 11:55:26

tangptr@126.com 发表于 2018-2-28 23:39
简单说一下,win10x64th2及之前的版本,原始地址的保存方式是八字节的,每个地址是需要重定向的绝对地址, ...

嗯, 很佩服像你这样驾轻就熟的大牛,我用ida 查看 ntosknrl.exe ,找了半天也没找到KiServerTable它初始化函数地址的地方【类似下面这张图片展示的地方】
http://chuantu.biz/t6/240/1519876432x-1404764426.jpg

哎。。。, 这次算是从你这里直接拿了条鱼回家吧,万分感谢。


T3Shell 发表于 2018-3-1 12:22:07

【分享】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;
}


图:


最后非常感谢论坛积极热心的朋友们的耐心解答, 希望以后能和大家一起学习交流进步

祝大家狗年大吉大利,哈哈哈

Tesla.Angela 发表于 2018-3-1 13:23:26

两条公式分别生效于不同的系统,需要区分版本号。

此外,同样的内容没必要分成两个主题帖。

x8680800 发表于 2018-3-1 16:48:15

我来看看吧

x8680800 发表于 2018-3-1 16:51:36

希望楼主发个完整的代码获取SSDT地址的 小白可以学习

tangptr@126.com 发表于 2018-3-1 22:08:57

T3Shell 发表于 2018-3-1 11:55
嗯, 很佩服像你这样驾轻就熟的大牛,我用ida 查看 ntosknrl.exe ,找了半天也没找到KiServerTable它初 ...

IDA有个功能叫jump by name的,直接输入KiServiceTable就行(对窗口凭空敲键盘)。如果没有就写_KiServiceTable

CleanLove 发表于 2018-3-1 22:35:38

看下 学习下,谢谢开源

flasco 发表于 2018-3-5 19:46:04

学习学习

309100 发表于 2018-3-10 15:30:47

win10 x64下获取ssdt

sqdwr 发表于 2018-4-22 11:45:18

学习一下。

YOUBADBAD 发表于 2018-5-1 19:16:30

谢谢楼主

li53133 发表于 2019-5-20 19:35:26

看下!!!

dsqyg 发表于 2019-6-6 13:25:15

学习一下。。。

sc12345 发表于 2019-8-13 09:59:47

谢谢分析,看看

aqtata 发表于 2019-11-7 09:24:50

看看什么变化。

269141225 发表于 2019-11-14 17:42:26

66666666666666666666

longjianfei 发表于 2019-11-18 05:07:30

谢谢分享

委员长 发表于 2019-11-20 20:08:57

看看隐藏的高级内容

yxxxxxxx 发表于 2019-11-27 09:12:53

谢谢

602621480 发表于 2019-12-7 19:11:45

学习一下方法

cloud1983 发表于 2019-12-12 14:23:54

看看公式

zoandcom 发表于 2019-12-16 14:38:54

从哪个版本开始变的?

JX小丶 发表于 2020-1-31 19:48:47

来看看回复

flappy 发表于 2020-4-18 20:17:46

谢谢层主

96613686 发表于 2020-5-5 22:09:59

66666666666

ol8080 发表于 2021-3-7 13:22:14

小白可以学习

ol8080 发表于 2021-3-10 13:07:02

我来看看吧

kanren 发表于 2021-11-4 14:25:03

巩固一下
页: [1] 2
查看完整版本: [求助]关于win10 x64下获取ssdt原始函数地址的问题(已解决)