Win7x64系统过TP的一些尝试和目前遇到的问题
其实渣新学内核编程不过半个月时间,帖中难免有幼稚的想法和错误,遇到的问题我会用蓝色文字表述,还请各位前辈指正,感激不尽!
我把自己目前的进展和遇到的问题一起说说吧:
x64系统过TP大概分两步,首先要过双机调试,然后要过应用层调试。
1、过双机调试,这里也分两步
(1)首先要保证debug模式下启动游戏不蓝屏。
我也是第一次研究TP,对这之前的保护不了解,不过看网上所说这个启动蓝屏似乎是最近几个月新加的。
要过这个需要对内核调试引擎有一定的了解,不过还好我们是站在巨♂人♀的肩膀上,在看雪找到了篇帖子,比较详细的分析了系统启动时内核调试引擎初始化的几个标志。
TP只是检测了其中一个(待定),KdEnteredDebugger,它通过MDL映射来判断这个标志是不是True,如果是就蓝屏,解决方法我照抄了那篇帖子,直接在Hook一下IoAllocateMdl,
把判断的地址改到一个恒为False的地方这样就可以绕过了
[C++] 纯文本查看 复制代码 ?
不过这样做带来一个问题,蓝屏是不蓝屏了,TP的驱动模块也能加载,但只能启动登陆客户端Client.exe,在登陆后启动DNF.exe时TP会再进行一次检测,
这次就会造成虚拟机卡死,估计还是和调试模式的检测有关。
我用了个折中的解决办法,就是用户态调试的时候不进入Debug模式,这样就能启动DNF.exe了,不过实在是不方便
(2)使双机调试能下断点
关于双机调试中断点原理和异常的处理流程,我是看了《软件调试》这本书和http://www.xfocus.net/articles/200412/765.html这片帖子,有了些了解。
对于TP来说,他是不断调用KdDisableDebuger()这个函数来清零KdDebuggerEnabled,调试引擎就是在KeUpdateSystemTime()这个函数里不断检测这个标志来确定异常处理的流程
解决方法,一开始我是直接HooK KdDisableDebuger(),开头
[Asm] 纯文本查看 复制代码 ?
直接STATUS_SUCCESS然后返回,不让它做其他处理,但是毫无效果,还是下不了断点,不知道是怎么回事……
后来想了个办法,直接修改KeUpdateSystemTime()里面检测的地方,和上面一样,让它检测其它地址……
[C++] 纯文本查看 复制代码 ?
要改的地方有3处,我只贴了一处的代码。这样就能下各种断点了。
2、双机调试之后就是用户态调试了
x64系统上TP目前做的保护还不是特别多,这也是我选x64入手的原因之一
TP修改了DebugObject中ValIDAccessMask一项,这个就是调试权限,代码中我们恢复下就可以了。
windbg下输入以下命令就可以定位到ValidAccessMask,下硬件断点就能找到ValidAccessMask清零的地方。
至于如何在自己的代码中定位这个变量,我是通过SSDT表查找NtCreateDebugObject这个内核函数地址,里面定位DbgkDebugObjectType
再根据下面的结构体加几个偏移地址(+0x040 + 0x01c)来找到ValidAccessMask。应该有更好的定位方法……
我把自己目前的进展和遇到的问题一起说说吧:
x64系统过TP大概分两步,首先要过双机调试,然后要过应用层调试。
1、过双机调试,这里也分两步
(1)首先要保证debug模式下启动游戏不蓝屏。
我也是第一次研究TP,对这之前的保护不了解,不过看网上所说这个启动蓝屏似乎是最近几个月新加的。
要过这个需要对内核调试引擎有一定的了解,不过还好我们是站在巨♂人♀的肩膀上,在看雪找到了篇帖子,比较详细的分析了系统启动时内核调试引擎初始化的几个标志。
TP只是检测了其中一个(待定),KdEnteredDebugger,它通过MDL映射来判断这个标志是不是True,如果是就蓝屏,解决方法我照抄了那篇帖子,直接在Hook一下IoAllocateMdl,
把判断的地址改到一个恒为False的地方这样就可以绕过了
[C++] 纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 |
PMDL
newIoAllocateMdl(
__in_opt
PVOID
VirtualAddress,
__in
ULONG
Length,
__in
BOOLEAN
SecondaryBuffer,
__in
BOOLEAN
ChargeQuota,
__inout_opt
PIRP Irp OPTIONAL)
{
if
(VirtualAddress == KdEnteredDebugger)
{
//DbgPrint("[KdEnteredDebugger]
address: %p
", KdEnteredDebugger);
VirtualAddress
= ( PUCHAR )KdEnteredDebugger
+ 0x30; //据观察,+0x30
的位置恒为0
}
return
oldIoAllocateMdl(VirtualAddress, Length, SecondaryBuffer, ChargeQuota, Irp);
}
|
不过这样做带来一个问题,蓝屏是不蓝屏了,TP的驱动模块也能加载,但只能启动登陆客户端Client.exe,在登陆后启动DNF.exe时TP会再进行一次检测,
这次就会造成虚拟机卡死,估计还是和调试模式的检测有关。
我用了个折中的解决办法,就是用户态调试的时候不进入Debug模式,这样就能启动DNF.exe了,不过实在是不方便
(2)使双机调试能下断点
关于双机调试中断点原理和异常的处理流程,我是看了《软件调试》这本书和http://www.xfocus.net/articles/200412/765.html这片帖子,有了些了解。
对于TP来说,他是不断调用KdDisableDebuger()这个函数来清零KdDebuggerEnabled,调试引擎就是在KeUpdateSystemTime()这个函数里不断检测这个标志来确定异常处理的流程
解决方法,一开始我是直接HooK KdDisableDebuger(),开头
[Asm] 纯文本查看 复制代码 ?
1 2 |
xor
rax, rax
ret
|
后来想了个办法,直接修改KeUpdateSystemTime()里面检测的地方,和上面一样,让它检测其它地址……
[C++] 纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 |
//替换KeUpdateSystemTime函数中两个KdDebuggerEnabled变量地址为DummyKdDebuggerEnabled
KUSTPatchAddr1
= SearchAddressBySig(( PUCHAR )KeUpdateSystemTimeAddr
+ 0x100, 0x100, UPSig1, sizeof (UPSig1))
;
if
(KUSTPatchAddr1 != NULL)
{
KUSTPatchAddr1
+= sizeof (UPSig1);
//64位汇编,变量均为相对rip地址,下同
DisableWriteProtect64();
*( PULONG )KUSTPatchAddr1
= ( PUCHAR )pDummyKdDebuggerEnabled
- (( PUCHAR )KUSTPatchAddr1
- 2) - 6; //指令长度为6
EnableWriteProtect64();
}
|
要改的地方有3处,我只贴了一处的代码。这样就能下各种断点了。
2、双机调试之后就是用户态调试了
x64系统上TP目前做的保护还不是特别多,这也是我选x64入手的原因之一
TP修改了DebugObject中ValIDAccessMask一项,这个就是调试权限,代码中我们恢复下就可以了。
windbg下输入以下命令就可以定位到ValidAccessMask,下硬件断点就能找到ValidAccessMask清零的地方。
至于如何在自己的代码中定位这个变量,我是通过SSDT表查找NtCreateDebugObject这个内核函数地址,里面定位DbgkDebugObjectType
再根据下面的结构体加几个偏移地址(+0x040 + 0x01c)来找到ValidAccessMask。应该有更好的定位方法……
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: 全局钩子过TP
- 下一篇: SetThreadContext注入
copyright © 2008-2019 亿联网络 版权所有 备案号:粤ICP备14031511号-2