看流星社区

 找回密码
 注册账号
查看: 2157|回复: 0

某P保护之调戏权限清0的学习。

[复制链接]

该用户从未签到

发表于 2017-6-1 14:50:05 | 显示全部楼层 |阅读模式
废话不多说啦,直接开干。

我们先来看看ValidAccessMask的值。
通过NtCreateDebugObject来定位。
ufNtCreateDebugObject

地址为fffff800`04011f40

第一个地址就是_object_type的地址

我们想得到的ValidAccessMask存在TypeInfo中,偏移为0x40

由上图可以看出ValidAccessMask的默认值为0x1f000f,此值为0时OD将无法附加,测试一下看看,我们将ValidAccessMask修改为0。


进程已无法附加,可见ValidAccessMask的值的确对我们附加进程造成影响,参考资料得TP是循环的将ValidAccessMask清0,即得出解决方法:1)自己恢复原来的值2)找到TP清零的位置Nop掉3)对ValidAccessMask进行移位,这里用最简单的方法一。

写代码时候发现了许多问题。NtCreateDebugObject这个函数在SSDT中,而X64已经没有导出KeServiceDescriptorTable,这里参考了TA大的Win64驱动开发教程,代码拿来即可用,抱着学习的心态来,学习方法和原理,动手。

反汇编KiSystemCall64,这里是内核函数入口。
ufKiSystemCall64,代码很多,贴出关键部分

特征码是:4c8d15c
内核代码开始的地址保存在C0000082寄存器中,读取这个寄存器也很方便,可用__readmsr()函数读取(MSR中文是特别寄存器块),
WinDbg测试看看。

地址相同。


Code:
/************************************************************************
函数名称:GetKeServiceDescriptorTable64
函数功能:得到GetKeServiceDescriptorTable64地址
************************************************************************/
ULONGLONGGetKeServiceDescriptorTable64()
{
PUCHARStatrtSearchAddr=(PUCHAR)__readmsr(0xc0000082);
PUCHAREndSearchAddr=StatrtSearchAddr+0x500;
PUCHARi=NULL;
UCHARb1=0,b2=0,b3=0;
ULONGtemplong=0;
ULONGLONGaddr=0;

for(i=StatrtSearchAddr;i<EndSearchAddr;i++)
{
if(MmIsAddressValid(i)&amp;&amp;MmIsAddressValid(i+1)&amp;&amp;MmIsAddressValid(i+2))
{
b1=*i;
b2=*(i+1);
b3=*(i+2);

//fffff800`01ad07724c8d15c7202300lear10,[nt!KeServiceDescriptorTable(fffff800`01d02840)]
if(b1==0x4c&amp;&amp;b2==0x8d&amp;&amp;b3==0x15)
{
memcpy(&amp;templong,i+3,4);
addr=(ULONGLONG)templong+(ULONGLONG)i+7;
returnaddr;
}
}
}
return0;
}
[/code]

接下来就是获取SSDT函数的地址了,获取地址需要得到函数的Index,方法也简单,也可通过工具获得,还是为了学知识,简单了解一下了。

看框内代码几乎相同,唯一不同的就是第二行代码。(注:这里出了一些问题,在Win10上测试与Win7不同,后续继续研究。)
xxH即为Index,90h转为十进制为144。


Code:
/************************************************************************
函数名称:GetSSDTFunctionAddress
函数功能:获得SSDT表地址
参数:ID号
注意:计算方法ServiceTableBase[index]>>4+ServiceTableBase
************************************************************************/
ULONGLONGGetSSDTFunctionAddress(ULONGid)
{
LONGdwtmp=0;
PULONGServiceTableBase=NULL;
PSYSTEM_SERVICE_TABLEssdt=(PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
ServiceTableBase=(PULONG)ssdt->ServiceTableBase;
dwtmp=ServiceTableBase[id];
dwtmp=dwtmp>>4;
returndwtmp+(ULONGLONG)ServiceTableBase;
}
[/code]

至此NtCreateDebugObject地址也得到。
接下来我们要取得ValidAccessMask的地址,还是用特征码定位的方式

Code:
/************************************************************************
函数名称:PassValidAccessMask
函数功能:修改ValidAccessMask&#20540;为0x1F000F
思路:解决调试权限清零dt_OBJECT_TYPE_INITIALIZERfffffa80`03cdd380+40
eqfffffa8003cdd380+40+0x1c00000000为0后无法附加
************************************************************************/
VOIDPassValidAccessMask()
{
PUCHARStartSearchAddress=(PUCHAR)GetSSDTFunctionAddress(144);

pNtCreateDebugObject=(PVOID)GetSSDTFunctionAddress(144);
DbgPrint("pNtCreateDebugObject:%p\n",pNtCreateDebugObject);

pTargetAddr=(PVOID)(((ULONG64)pNtCreateDebugObject)+0x7c);
DbgPrint("pTargetAddr:%p\n",pTargetAddr);

PUCHAREndSearchAddress=StartSearchAddress+0x100;
PUCHARi=0;
UCHARb1=0,b2=0,b3=0;
LONGtemp=0;
LONGLONGaddr=0;
for(i=StartSearchAddress;i<EndSearchAddress;i++)
{
if(MmIsAddressValid(i)&amp;&amp;MmIsAddressValid(i+1)&amp;&amp;MmIsAddressValid(i+2))
{
b1=*i;
b2=*(i+1);
b3=*(i+2);
if(b1==0x48&amp;&amp;b2==0x8b&amp;&amp;b3==0x15)
{
memcpy_s(&amp;temp,4,i+3,4);
addr=(LONGLONG)temp+(LONGLONG)i+7;
DbgPrint("ValidAccessMask:%llx\n",*(ULONG*)((*(ULONGLONG*)addr)+0x40+0x1C));
*(ULONG*)((*(ULONGLONG*)addr)+0x40+0x1C)=0x1f000f;
}
}
}

}
[/code]

至此全部完成,开个定时器修改ValidAccessMask的&#20540;就行了,参考了论坛上一位大大的方法,谢谢啦,编译,最激动人心的时候要到了。



成功了尽然,抽根烟压压惊,剩下的路还很长,学习的还很多,继续努力得到第一篇精华。
新手发帖无任何技术含量,望大牛轻喷啊,最后附上源码,代码测试用的,有些凌乱,见谅。
PS:感谢TA大牛提供的Win64驱动编程基础教程与看雪上前辈们分享的文章。
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-4-24 08:06

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

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