找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 42748|回复: 28

[原创]Win10遍历句柄表+修改权限过Callback保护

 火.. [复制链接]

1

主题

56

回帖

1

精华

贵宾会员

积分
2075
发表于 2016-7-5 00:47:38 | 显示全部楼层 |阅读模式
本帖最后由 zjr230506 于 2016-7-5 00:49 编辑

本想发到看雪,但自己太菜,看雪“牛人”又太多,想想还是发到紫水晶吧。
感谢 TA 的 WIN64 教程带我走上驱动之路,想想除了个 VIP 账号就没教过学费,以后多在论坛发帖来回报一下吧。

正篇:
XP 和 Win7 上关于句柄表的文章不少,一点不懂的朋友请自行百度谷歌搜索,方法没变,依旧使用 ExpLookupHandleTableEntry 。

主要说说 Win10 的变化,相较于 Win7 这两个结构体有所改变: HANDLE_TABLE 和 HANDLE_TABLE_ENTRY ,另外多了一个 HANDLE_TABLE_FREE_LIST 。

根据 WinDBG 逆向出的结构定义如下:
  1. 1: kd> dt nt!_HANDLE_TABLE
  2. + 0x000 NextHandleNeedingPool : Uint4B
  3. + 0x004 ExtraInfoPages : Int4B
  4. + 0x008 TableCode : Uint8B
  5. + 0x010 QuotaProcess : Ptr64 _EPROCESS
  6. + 0x018 HandleTableList : _LIST_ENTRY
  7. + 0x028 UniqueProcessId : Uint4B
  8. + 0x02c Flags : Uint4B
  9. + 0x02c StrictFIFO : Pos 0, 1 Bit
  10. + 0x02c EnableHandleExceptions : Pos 1, 1 Bit
  11. + 0x02c Rundown : Pos 2, 1 Bit
  12. + 0x02c Duplicated : Pos 3, 1 Bit
  13. + 0x02c RaiseUMExceptionOnInvalidHandleClose : Pos 4, 1 Bit
  14. + 0x030 HandleContentionEvent : _EX_PUSH_LOCK
  15. + 0x038 HandleTableLock : _EX_PUSH_LOCK
  16. + 0x040 FreeLists : [1] _HANDLE_TABLE_FREE_LIST
  17. + 0x040 ActualEntry : [32] UChar
  18. + 0x060 DebugInfo : Ptr64 _HANDLE_TRACE_DEBUG_INFO

  19. typedef struct _HANDLE_TABLE
  20. {
  21.         ULONG32 NextHandleNeedingPool;
  22.         LONG32 ExtraInfoPages;
  23.         ULONG_PTR TableCode;
  24.         PEPROCESS QuotaProcess;
  25.         LIST_ENTRY HandleTableList;
  26.         ULONG32 UniqueProcessId;
  27.         union
  28.         {
  29.                 ULONG32 Flags;
  30.                 struct
  31.                 {
  32.                         BOOLEAN StrictFIFO : 1;
  33.                         BOOLEAN EnableHandleExceptions : 1;
  34.                         BOOLEAN Rundown : 1;
  35.                         BOOLEAN Duplicated : 1;
  36.                         BOOLEAN RaiseUMExceptionOnInvalidHandleClose : 1;
  37.                 };
  38.         };
  39.         ULONG_PTR HandleContentionEvent;
  40.         ULONG_PTR HandleTableLock;
  41.         union
  42.         {
  43.                 HANDLE_TABLE_FREE_LIST FreeLists[1];
  44.                 BOOLEAN ActualEntry[32];
  45.         };
  46.         PVOID DebugInfo;
  47. } HANDLE_TABLE, *PHANDLE_TABLE;
复制代码
  1. 1: kd> dt nt!_HANDLE_TABLE_ENTRY
  2. + 0x000 VolatileLowValue : Int8B
  3. + 0x000 LowValue : Int8B
  4. + 0x000 InfoTable : Ptr64 _HANDLE_TABLE_ENTRY_INFO
  5. + 0x008 HighValue : Int8B
  6. + 0x008 NextFreeHandleEntry : Ptr64 _HANDLE_TABLE_ENTRY
  7. + 0x008 LeafHandleValue : _EXHANDLE
  8. + 0x000 RefCountField : Int8B
  9. + 0x000 Unlocked : Pos 0, 1 Bit
  10. + 0x000 RefCnt : Pos 1, 16 Bits
  11. + 0x000 Attributes : Pos 17, 3 Bits
  12. + 0x000 ObjectPointerBits : Pos 20, 44 Bits
  13. + 0x008 GrantedAccessBits : Pos 0, 25 Bits
  14. + 0x008 NoRightsUpgrade : Pos 25, 1 Bit
  15. + 0x008 Spare1 : Pos 26, 6 Bits
  16. + 0x00c Spare2 : Uint4B

  17. typedef struct _HANDLE_TABLE_ENTRY
  18. {
  19.         union
  20.         {
  21.                 LONG_PTR VolatileLowValue;
  22.                 LONG_PTR LowValue;
  23.                 PVOID InfoTable;
  24.                 LONG_PTR RefCountField;
  25.                 struct
  26.                 {
  27.                         ULONG_PTR Unlocked : 1;
  28.                         ULONG_PTR RefCnt : 16;
  29.                         ULONG_PTR Attributes : 3;
  30.                         ULONG_PTR ObjectPointerBits : 44;
  31.                 };
  32.         };
  33.         union
  34.         {
  35.                 LONG_PTR HighValue;
  36.                 struct _HANDLE_TABLE_ENTRY *NextFreeHandleEntry;
  37.                 EXHANDLE LeafHandleValue;
  38.                 struct
  39.                 {
  40.                         ULONG32 GrantedAccessBits : 25;
  41.                         ULONG32 NoRightsUpgrade : 1;
  42.                         ULONG32 Spare1 : 6;
  43.                 };
  44.                 ULONG32 Spare2;
  45.         };
  46. } HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
复制代码
  1. 1: kd> dt nt!_HANDLE_TABLE_FREE_LIST
  2. + 0x000 FreeListLock     : _EX_PUSH_LOCK
  3. + 0x008 FirstFreeHandleEntry : Ptr64 _HANDLE_TABLE_ENTRY
  4. + 0x010 LastFreeHandleEntry : Ptr64 _HANDLE_TABLE_ENTRY
  5. + 0x018 HandleCount : Int4B
  6. + 0x01c HighWaterMark : Uint4B
  7. + 0x020 Reserved : [8] Uint4B

  8. typedef struct _HANDLE_TABLE_FREE_LIST
  9. {
  10.         ULONG_PTR FreeListLock;
  11.         PHANDLE_TABLE_ENTRY FirstFreeHandleEntry;
  12.         PHANDLE_TABLE_ENTRY lastFreeHandleEntry;
  13.         LONG32 HandleCount;
  14.         ULONG32 HighWaterMark;
  15.         ULONG32 Reserved[8];
  16. } HANDLE_TABLE_FREE_LIST, *PHANDLE_TABLE_FREE_LIST;
复制代码

只是一部分成员的偏移变化了,要注意的是表示对象地址的成员移到了 ObjectPointerBits 上,长度为 44 位的数据。
Win10上内核对象的地址算法:
  1. Object = Entry->ObjectPointerBits;
  2. Object <<= 4;
  3. Object |= 0xFFFF000000000000;
  4. Object += 0x30;
复制代码

另外对象权限也变到了 GrantedAccessBits 成员中,长度为 25 位的数据。

关于 ExpLookupHandleTableEntry 的实现上,相较 Win7 的版本仅仅优化了下代码逻辑,可以说没有变化。
直接抄 WRK 的代码,建议多看几遍代码,配合网上的其他帖子理解一下句柄表结构,我就不废话了(懒)。

本来想写一大堆,但感觉都是废话删掉了,结果就变成这么一篇偷懒贴,干脆直接上核心代码吧:
  1. NTSTATUS ViewHandle(ULONG32 ProcessId, POBJECT_INFO Buffer)
  2. {
  3.         PEPROCESS EProcess = NULL;
  4.         ULONG_PTR Handle = 0;
  5.         PHANDLE_TABLE_ENTRY Entry = NULL;
  6.         PVOID Object = NULL;
  7.         POBJECT_TYPE ObjectType = NULL;

  8.         if (!NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)ProcessId, &EProcess)))
  9.         {
  10.                 return STATUS_UNSUCCESSFUL;
  11.         }

  12.         for (Handle = 0;; Handle += HANDLE_VALUE_INC)
  13.         {
  14.                 Entry = ExpLookupHandleTableEntry(*(PHANDLE_TABLE*)((PUCHAR)EProcess + g_HandleTableOffset), *(PEXHANDLE)&Handle);
  15.                 if (Entry == NULL)
  16.                 {
  17.                         break;
  18.                 }

  19.                 *(ULONG_PTR*)&Object = Entry->ObjectPointerBits;
  20.                 *(ULONG_PTR*)&Object <<= 4;
  21.                 if (Object == NULL)
  22.                 {
  23.                         continue;
  24.                 }

  25.                 *(ULONG_PTR*)&Object |= 0xFFFF000000000000;
  26.                 *(ULONG_PTR*)&Object += 0x30;
  27.                 ObjectType = ObGetObjectType(Object);
  28.                 if (ObjectType == NULL)
  29.                 {
  30.                         continue;
  31.                 }

  32.                 wcscpy(Buffer->szTypeName, *(PCWSTR*)((PUCHAR)ObjectType + 0x18));
  33.                 Buffer->Handle = (HANDLE)Handle;
  34.                 Buffer->AccessMask = Entry->GrantedAccessBits;
  35.                 Buffer->Address = Object;

  36.                 Buffer++;
  37.         }

  38.         ObDereferenceObject(EProcess);

  39.         return STATUS_SUCCESS;
  40. }
复制代码

效果是这样的,对照WIN64AST:
p1.png


这点破东西貌似不够看,再加个然并卵的玩意。

修改进程句柄权限过 Callback 保护:
  1. if (wcscmp(*(PCWSTR*)((PUCHAR)ObjectType + 0x18), L"Process") == 0)
  2. {
  3.         if (*(PULONG32)((PUCHAR)Object + 0x2E8) == PassiveId)
  4.         {
  5.                 Entry->GrantedAccessBits = 0x1FFFFF;
  6.                 Status = STATUS_SUCCESS;
  7.         }
  8. }
复制代码

拿 TP 举例,通常情况下,在 Ring3 调用 OpenProcess 传递 PROCESS_ALL_ACCESS 参数,该句柄对应的进程对象权限是 0x1FFFFF ,但对 TP 保护的游戏进行同样做法后会发现权限变成了 0x1FFD85,它的 Callback 中抹掉了进程对象的这些权限:
  1. #define PROCESS_CREATE_THREAD    (0x0002)
  2. #define PROCESS_VM_OPERATION     (0x0008)
  3. #define PROCESS_VM_READ          (0x0010)
  4. #define PROCESS_VM_WRITE         (0x0020)
  5. #define PROCESS_DUP_HANDLE       (0x0040)
  6. #define PROCESS_SET_INFORMATION  (0x0200)
复制代码

直接在 TP 的 Callback 中写 ret 游戏会封号,而且 TP 卸载时会蓝屏,内部通信肯定是有的,尝试过逆向,一堆 jmp 把我弄晕了,干脆就换种办法。

如上代码,我的做法是,遍历句柄表,判断对象类型为 "PROCESS" ,然后根据 EPROCESS 对象获得对应进程进程的 PID ,如果是被保护的进程就把权限写成 0x1FFFFF ,测试过 DXF 有效。

效果是这样的,恢复权限之前和之后分别为:
q1.png
q2.png

听说这是一种比较二逼的解决方法,没办法谁让我菜呢。如果有更好的办法还望不吝赐教。


最后奉上完整打包好的解决方案, VS2015 + WDK10 直接编译,附件包含:
HandleView User Ring3
HandleView Ring0
RestoreAccess Ring3
RestoreObjectAccess Ring0

Code.zip (54.56 KB, 下载次数: 19322)

溜了溜了{:soso__14291351291962500186_4:}

评分

参与人数 1水晶币 +100 收起 理由
Tesla.Angela + 100 很给力!

查看全部评分

0

主题

59

回帖

0

精华

铜牌会员

积分
303
发表于 2016-7-5 10:02:36 | 显示全部楼层
不错,赞一个

1

主题

77

回帖

0

精华

金牌会员

积分
1137
发表于 2016-7-5 16:40:12 | 显示全部楼层
看看看看看看看看看看

0

主题

4

回帖

0

精华

初来乍到

积分
61
发表于 2016-7-9 19:28:40 | 显示全部楼层
不错不错.我来看看

1

主题

29

回帖

0

精华

铜牌会员

积分
94
发表于 2016-7-18 16:33:54 | 显示全部楼层
shishikankan

1

主题

72

回帖

0

精华

铜牌会员

积分
260
发表于 2016-7-19 11:02:09 | 显示全部楼层
不错,学到了个思路

5

主题

103

回帖

0

精华

铜牌会员

积分
252
发表于 2016-7-19 16:22:29 | 显示全部楼层
Good Job!

0

主题

24

回帖

0

精华

铜牌会员

积分
165
发表于 2016-7-19 22:00:50 | 显示全部楼层
不错,赞一个

2

主题

165

回帖

0

精华

金牌会员

积分
944
发表于 2016-7-20 08:59:30 | 显示全部楼层
本帖最后由 284406022 于 2016-7-20 09:01 编辑

只想问个问题:楼主是怎么双机调试win10的?我用VirtualKD-2.8,但是开启windbg后进入不了win10系统了,用了VirtualKD最新版本也是这样,目前只有VirtualKD双机调试win7 x64和win7 x86是成功的,win8.1也是不行,求个双机调试win10的方法

0

主题

25

回帖

0

精华

银牌会员

积分
330
发表于 2016-7-20 19:53:44 | 显示全部楼层
感谢分享 我直接用xuetr恢复会被制裁

857

主题

2632

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36129
发表于 2016-7-21 07:29:30 | 显示全部楼层
这个帖子我竟然没看到。。。真是不好意思,立马加精加币!

0

主题

65

回帖

0

精华

金牌会员

积分
1011
发表于 2016-7-21 08:43:13 | 显示全部楼层
不错,赞一个,感谢楼主分享。

0

主题

67

回帖

0

精华

铂金会员

积分
2141
发表于 2016-7-21 10:00:54 | 显示全部楼层
看起很不错的,赞一个

1

主题

56

回帖

1

精华

贵宾会员

积分
2075
 楼主| 发表于 2016-7-21 14:12:49 | 显示全部楼层
284406022 发表于 2016-7-20 08:59
只想问个问题:楼主是怎么双机调试win10的?我用VirtualKD-2.8,但是开启windbg后进入不了win10系统了,用了Vir ...

我没有用VirtrualKD,Guest直接添加的调试启动项,设置COM1虚拟串口,然后Windbg远程调试。

2

主题

165

回帖

0

精华

金牌会员

积分
944
发表于 2016-7-22 08:17:31 | 显示全部楼层
zjr230506 发表于 2016-7-21 14:12
我没有用VirtrualKD,Guest直接添加的调试启动项,设置COM1虚拟串口,然后Windbg远程调试。 ...

Guset账户手动添加windbg远程调试启动项参数? admin帐号手动添加可以吗?

1

主题

56

回帖

1

精华

贵宾会员

积分
2075
 楼主| 发表于 2016-7-22 09:14:25 | 显示全部楼层
284406022 发表于 2016-7-22 08:17
Guset账户手动添加windbg远程调试启动项参数? admin帐号手动添加可以吗?

这都哪跟哪啊...怎么还扯到账户了呢?
虚拟机用bcdedit命令添加一个启动项,开启调试,指定调试端口和波特率,然后给这个虚拟机添加一个命名管道,宿主机启动Windbg也指定同样的端口和波特率就可以了。
具体百度双机调试,Win10跟Win7一样的方法。

0

主题

33

回帖

0

精华

金牌会员

积分
739
发表于 2016-7-23 20:13:29 | 显示全部楼层
貌似很厉害,虽然有一半没看太懂,这意思可以在ring3下反tp?
拿去研究研究,感觉这方法比vt好容易多了,反回调函数想想就激动

0

主题

40

回帖

0

精华

铜牌会员

积分
96
发表于 2016-7-29 03:32:19 | 显示全部楼层
支持一下。。。。。。。。。。。。。。。。

0

主题

7

回帖

0

精华

铜牌会员

积分
61
发表于 2016-7-29 09:39:06 | 显示全部楼层
不错,赞一个.

0

主题

36

回帖

0

精华

铜牌会员

积分
64
发表于 2016-7-30 15:28:59 | 显示全部楼层
厉害 学习一哈

2

主题

12

回帖

0

精华

铜牌会员

积分
217
发表于 2016-8-2 21:52:14 | 显示全部楼层
厉害,刚入门的我发现还不太懂,继续努力中

0

主题

40

回帖

0

精华

铜牌会员

积分
96
发表于 2016-8-4 20:32:15 | 显示全部楼层
2E8怎么来的

0

主题

28

回帖

0

精华

铜牌会员

积分
284
发表于 2016-9-26 16:52:24 | 显示全部楼层
谢谢分享,好思路

2

主题

45

回帖

0

精华

铜牌会员

积分
214
发表于 2018-11-7 13:41:47 | 显示全部楼层
本帖最后由 hapi 于 2018-12-2 08:14 编辑

遍历的时候蓝屏了,TK中;My OS:16299

2

主题

80

回帖

0

精华

铜牌会员

积分
92
发表于 2018-12-22 00:30:07 | 显示全部楼层
这个很牛.

0

主题

3

回帖

0

精华

初来乍到

积分
13
发表于 2020-4-25 16:17:51 | 显示全部楼层
学习一下谢谢了

0

主题

20

回帖

0

精华

初来乍到

积分
19
发表于 2020-5-1 18:32:26 | 显示全部楼层
学习了,谢谢

0

主题

52

回帖

0

精华

铜牌会员

积分
77
发表于 2020-7-4 17:28:59 | 显示全部楼层
哇,楼主能在游戏开着的时候双机调试

1

主题

24

回帖

0

精华

铜牌会员

积分
66
发表于 2020-8-21 09:29:23 | 显示全部楼层
下载看看,感谢分享!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

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