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

废话不多说啦,直接开干。

我们先来看看ValidAccessMask的值。
通过NtCreateDebugObject来定位。
uf  NtCreateDebugObject
Click image for larger versionName:	1.pngViews:	15Size:	89 KBID:	102431
地址为fffff800`04011f40
Name:  2.pngViews: 2Size:  55 KB
第一个地址就是_object_type的地址
Click image for larger versionName:	3.pngViews:	7Size:	96 KBID:	102433
我们想得到的ValidAccessMask存在TypeInfo中,偏移为0x40
Click image for larger versionName:	4.pngViews:	9Size:	184 KBID:	102434
由上图可以看出ValidAccessMask的默认值为0x1f000f,此值为0时OD将无法附加,测试一下看看,我们将ValidAccessMask修改为0。
Click image for larger versionName:	5.pngViews:	12Size:	191 KBID:	102435
Click image for larger versionName:	6.pngViews:	18Size:	286 KBID:	102436
进程已无法附加,可见ValidAccessMask的值的确对我们附加进程造成影响,参考资料得TP是循环的将ValidAccessMask清0,即得出解决方法:1)自己恢复原来的值 2)找到TP清零的位置Nop掉 3)对ValidAccessMask进行移位,这里用最简单的方法一。

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

反汇编KiSystemCall64,这里是内核函数入口。
uf KiSystemCall64,代码很多,贴出关键部分
Click image for larger versionName:	7.pngViews:	10Size:	75 KBID:	102437
特征码是:4c8d15c
内核代码开始的地址保存在C0000082寄存器中,读取这个寄存器也很方便,可用__readmsr()函数读取(MSR中文是特别寄存器块),
WinDbg测试看看。
Name:  8.pngViews: 0Size:  70 KB
地址相同。

Code:
/************************************************************************
函数名称:GetKeServiceDescriptorTable64
函数功能:得到GetKeServiceDescriptorTable64地址
************************************************************************/
ULONGLONG GetKeServiceDescriptorTable64()
{
  PUCHAR StatrtSearchAddr = (PUCHAR)__readmsr(0xc0000082);
  PUCHAR EndSearchAddr = StatrtSearchAddr + 0x500;
  PUCHAR i = NULL;
  UCHAR b1 = 0, b2 = 0, b3 = 0;
  ULONG templong = 0;
  ULONGLONG addr = 0;

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

      //fffff800`01ad0772 4c8d15c7202300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`01d02840)]
      if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15)
      {
        memcpy(&templong,i + 3,4);
        addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
        return addr;
      }
    }
  }
  return 0;
}
接下来就是获取SSDT函数的地址了,获取地址需要得到函数的Index,方法也简单,也可通过工具获得,还是为了学知识,简单了解一下了。
Name:  9.pngViews: 1Size:  116 KB
看框内代码几乎相同,唯一不同的就是第二行代码。(注:这里出了一些问题,在Win10上测试与Win7不同,后续继续研究。)
xxH即为Index,90h转为十进制为144。
Click image for larger versionName:	10.pngViews:	5Size:	93 KBID:	102440
Code:
/************************************************************************
函数名称:GetSSDTFunctionAddress
函数功能:获得SSDT表地址
参   数 :ID号
注意:计算方法 ServiceTableBase[index] >> 4 + ServiceTableBase
************************************************************************/
ULONGLONG GetSSDTFunctionAddress(ULONG id)
{
  LONG dwtmp = 0;
  PULONG ServiceTableBase = NULL;
  PSYSTEM_SERVICE_TABLE ssdt = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
  ServiceTableBase = (PULONG)ssdt->ServiceTableBase;
  dwtmp = ServiceTableBase[id];
  dwtmp = dwtmp >> 4;
  return dwtmp + (ULONGLONG)ServiceTableBase;
}
至此NtCreateDebugObject地址也得到。
接下来我们要取得ValidAccessMask的地址,还是用特征码定位的方式
Code:
/************************************************************************
函数名称:PassValidAccessMask
函数功能:修改ValidAccessMask值为0x1F000F
思路:解决调试权限清零 dt  _OBJECT_TYPE_INITIALIZER fffffa80`03cdd380+40
eq fffffa8003cdd380+40+0x1c 00000000 为0后无法附加
************************************************************************/
VOID PassValidAccessMask()
{
  PUCHAR StartSearchAddress = (PUCHAR)GetSSDTFunctionAddress(144);

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

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

  PUCHAR EndSearchAddress = StartSearchAddress + 0x100;
  PUCHAR i = 0;
  UCHAR b1 = 0, b2 = 0, b3 = 0;
  LONG temp = 0;
  LONGLONG addr = 0;             
  for (i = StartSearchAddress; i < EndSearchAddress; i++)
  {
    if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
    {
      b1 = *i;
      b2 = *(i + 1);
      b3 = *(i + 2);
      if (b1 == 0x48 && b2 == 0x8b && b3 == 0x15)
      {
        memcpy_s(&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;
      }
    }
  }

}
至此全部完成,开个定时器修改ValidAccessMask的值就行了,参考了论坛上一位大大的方法,谢谢啦,编译,最激动人心的时候要到了。
Name:  QQ截图20160110192440.pngViews: 2Size:  74 KB
Click image for larger versionName:	QQ截图20160110192220.pngViews:	24Size:	628 KBID:	102454
Click image for larger versionName:	QQ截图20160110192332.pngViews:	19Size:	1291 KBID:	102456
成功了尽然,抽根烟压压惊,剩下的路还很长,学习的还很多,继续努力得到第一篇精华。
新手发帖无任何技术含量,望大牛轻喷啊,最后附上源码,代码测试用的,有些凌乱,见谅。
PS:感谢TA大牛提供的Win64驱动编程基础教程与看雪上前辈们分享的文章。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值