12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
三国霸业 战车-珍宝-觉醒-攻城掠地SF-全新玩法 免费玩新区 攻城掠地私服 进入游戏
手游私服盒子 各类免费游戏 0.1折送海量资源 各类手游私服 进入游戏
皇家MU2 《奇迹 2:传奇》韩国网禅公司《奇迹》正统续作。 3D锁视角Mmrpg 暗黑3+传奇+流放之路+奇迹 进入游戏
查看: 497|回复: 0

【原创】TP驱动保护分析系列二 代码定位内核函数

[复制链接]

505

主题

505

帖子

1020

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
1020
发表于 2021-7-26 01:44:43 | 显示全部楼层 |阅读模式
系列索引

【原创】TP驱动掩护分析系列一 定位TenProtect掩护
【原创】TP驱动掩护分析系列二 代码定位内核函数
【原创】TP驱动掩护分析系列三 SSDT定位内核函数
前言

前面在【原创】TP驱动掩护分析系列一 定位TenProtect掩护中分析并找到了TenProtect在内核层所做的手脚,但只通过windbg等工具找到可不够,接下来继承介绍代码定位内核函数的方法
代码定位内核函数

驱动函数直接定位

在驱动开发引入的里提供了MmGetSystemRoutineAddress函数,根据函数名可以直接获取到已导出的函数地点
该函数的官方文档直达:MmGetSystemRoutineAddress function (wdm.h) - Windows drivers | Microsoft Docs
这里再简朴介绍(翻译理解)一下:
函数原型

PVOID MmGetSystemRoutineAddress(  PUNICODE_STRING SystemRoutineName);函数名MmGetSystemRoutineAddress函数功能驱动程序可以使用这个Routine来确定一个Routine在特定版本的Windows上是否可用。它只能用于内核或HAL导出的例程,不能用于任何驱动程序定义的Routine参数名SystemRoutineName参数名阐明想要获取的系统Routine的名称参数类型PUNICODE_STRING参数类型阐明字符串,定义如下typedef struct _UNICODE_STRING {    USHORT Length;    USHORT MaximumLength;#ifdef MIDL_PASS    [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;#else // MIDL_PASS    _Field_size_bytes_part_opt_(MaximumLength, Length) PWCH   Buffer;#endif // MIDL_PASS} UNICODE_STRING;typedef UNICODE_STRING *PUNICODE_STRING;函数的使用

        UNICODE_STRING s;                                //声明字符串        CHAR* string = L"RoutineName";        //要赋值的字符串 注意前面字符串前要加上L L告示编译器使用两个字节的 unicode 字符集。        RtlInitUnicodeString(&s, string);                //初始化unicode字符串        MmGetSystemRoutineAddress(&s);        //使用函数支持直接定位的函数

前面提到了MmGetSystemRoutineAddress只能用于内核或HAL导出的例程,也就是只能获取到内核中的导出函数
怎样知道内核导出了哪些函数?

找到C:\WINDOWS\system32\ntkrnlpa.exe的内核文件
PS:根据操纵系统版本的不同,对应的内核文件也大概不同,如在虚拟机XP系统下内核文件为ntkrnlpa.exe,而在实机WIN10下对应的内核文件为ntoskrnl.exe
除此之外,还有两种内核文件:ntkrnlmp.exe 和ntkrpamp.exe
这四种内核文件的区别如下:
ntoskrnl - 单处置惩罚器,不支持PAE
ntkrnlpa - 单处置惩罚器,支持PAE
ntkrnlmp - 多处置惩罚器,不支持PAE
ntkrpamp - 多处置惩罚器,支持PAE
PAE全称Physical Address Extension,即物理地点拓展,是x86处置惩罚器的一个功能,让中心处置惩罚器在32位操纵系统下访问超过4GB的物理内存
使用IDA Pro打开对应的内核文件,得到:

点击右上角的Exports,检察导出(不仅包含导出的函数,也包含了导出的变量等):

定位代码样例

下面以NtOpenProcess函数为例,通过MmGetSystemRoutineAddress定位函数地点
代码

#include "ntddk.h"VOID DriverUnload(IN PDRIVER_OBJECT DriverObject){        DbgPrint("卸载完成!\n");}NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath){        UNICODE_STRING s;        CHAR* string = L"NtOpenProcess";        RtlInitUnicodeString(&s, string);        PVOID address=MmGetSystemRoutineAddress(&s);        DbgPrint("address:%p\n", address);        DriverObject->DriverUnload = DriverUnload;        return STATUS_SUCCESS;}运行效果


验证效果

得到的地点为:805CC486
使用windbg检察对应地点的反汇编:
u 805CC486
可以验证得到的就是NtOpenProcess的地点
特征码定位

当想要定位的内核函数没有导出,但其在可获得地点附近时,则可使用特征码定位法
所谓的特征码定位法,就是选一个地点作为搜刮的起始地点,然后开始逐一比对 匹配的特征码(字节码)
PsTerminateProcess

下面以PsTerminateProcess函数为例,介绍特征码定位法
确定起始地点

要使用特征码定位PsTerminateProcess函数,首先要确定一个起始地点开始搜刮该函数
于是使用IDA Pro检察PsTerminateProcess附近的函数:

可以发现PsTerminateProcess函数的上面一个函数PsTerminateSystemThread正好是导出函数:

于是便可直接使用PsTerminateSystemThread作为起始地点
确定特征码

确定了起始位置后,便要确定特征码了
所谓特征码:关键就是要突出特征,即最好能够保持unique(独一无二),并且稳固(固定不变)
使用Windbg检察PsTerminateProcess对应的反汇编
u PsTerminateProcess得到:

即:
nt!PsTerminateProcess:805d35c2 8bff            mov     edi,edi805d35c4 55              push    ebp805d35c5 8bec            mov     ebp,esp805d35c7 5d              pop     ebp805d35c8 e9b5feffff      jmp     nt!PspTerminateProcess (805d3482)805d35cd cc              int     3805d35ce cc              int     3805d35cf cc              int     3这里选取的特征码为:8b ff 55 8b ec 5d e9
轻微阐明一下为什么不选取jmp     nt!PspTerminateProcess指令后面的b5feffff
jmp XXXX 对应的 硬编码为 e9 offset,e9代表jmp,后面的offset为偏移地点
实际要跳转的地点(XXXX) =  当前地点 + offset +当前指令长度
代入这里: 要跳转的地点(805d3482) =  805d35c8(当前地点) + fffffeb5(offset 小端存储) + 5(当前指令长度)
即 805d3482 = 805d35c8 + fffffeb5+ 5
也就是 805d3482-805d35c8-5 = fffffeb5
这里的fffffeb5是一个有符号负数,可以直接用系统自带的计算器来验证
(关于有符号数、无符号数可回顾:逆向基础笔记二 数据宽度和逻辑运算)

而偏移量是不固定的,即不满足特征码的稳固性要素,故不将后面字节码作为特征码
代码

确定了起始位置和特征码后,就可以写代码实现特征码定位了,代码如下:
#include "ntddk.h"/*        获取指定地点的数值        base:要获取的地点        offset:偏移量        size:获取的巨细*/PVOID GetAddrValue(PVOID* base, INT offset, INT size) {        PVOID Addr = *base;        PVOID templong = 0;        //复制内存,将指定位置的内存的值读取出来        RtlCopyMemory(&templong, (PUCHAR)Addr + offset, size);        return templong;}VOID DriverUnload(IN PDRIVER_OBJECT DriverObject){        DbgPrint("卸载完成!\n");}NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath){    //通过MmGetSystemRoutineAddress直接获取PsTerminateSystemThread地点        UNICODE_STRING s;        CHAR* string = L"PsTerminateSystemThread";        RtlInitUnicodeString(&s, string);        PVOID address = MmGetSystemRoutineAddress(&s);        DbgPrint("PsTerminateSystemThread Address:%p\n", address);    //将PsTerminateSystemThread作为起始地点        ULONG beginAdress =(ULONG) address;    //搜刮范围限制为0x1000        ULONG endAdress = beginAdress + 0x1000;    //刚开始匹配地点为0,表现尚未匹配到        PVOID matchAdress = 0;    //开始循环比较 搜刮特征码        for (ULONG i=beginAdress;i< endAdress;i+=1)        {                PVOID value = GetAddrValue(&i, 0, 4);                PVOID value2 = GetAddrValue(&i, 0, 3);                //特征码为8b ff 55 8b ec 5d e9 小端存储                if (value == 0x8b55ff8b && value2 == 0xe95dec) {            //匹配特征码后 赋值,终止循环                        matchAdress = i;                        break;                }        }        DbgPrint("PsTerminateProcess Address:%p\n", address);        DriverObject->DriverUnload = DriverUnload;        return STATUS_SUCCESS;}运行效果


验证效果

得到的地点为:805D3594
使用windbg检察对应地点的反汇编:
u 805D3594
可以验证得到的就是PsTerminateProcess的地点
总结

本篇介绍了代码定位内核函数的两种方法:MmGetSystemRoutineAddress直接定位和特征码定位

  • MmGetSystemRoutineAddress只能定位到导出的内核函数,比较局限,但胜在方便稳固
  • 特征码定位要注意特征码选取需要满足unique(独一无二)和稳固(固定不变)
限于篇幅,本章就先到这里,后续会再继承介绍SSDT定位法和符号表PDB解析法
PS:还有一种PE文件导出表扫描法在PE文件笔记十四 导出表中已阐明过,就不再赘述了
在介绍完这些定位方法后,就会针对TenProtect实例进行分析定位并绕过,敬请等待( &#8226;&#768; ω &#8226;&#769; )&#10023;
附件

最后附上本篇中用到的用具和最后编译出的驱动文件
包罗:

  • 驱动加载工具:InstDrv 1.3 汉化版
  • 调试信息检察工具:DbgView
  • 特征码定位编译出的驱动文件:GetKernelAddress.sys
PS:特征码定位中用到了MmGetSystemRoutineAddress,故不但独提供驱动函数直接定位的驱动文件
DbgView可直接到微软官方下载:DebugView - Windows Sysinternals | Microsoft Docs
加载工具和驱动文件下载:点我下载
务必注意,驱动运行环境为Windows XP!!!WIN7和WIN7以上版本的操纵系统不支持
学习交换为主,请勿用于其他非法途径
驱动加载工具和成品.zip
11.42 KB, 下载次数: 20, 下载积分: 吾爱币 -1 CB

论坛备份,土豪专用

来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-11-24 10:48 , Processed in 0.078125 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表