|
作者:Tesla.Angela
说到商业级进程保护,没有最奇葩的需求,只有更奇葩的需求。
有一个用户提出的要求是,进程被结束无所谓,但不能被“某保护”获取进程路径。
要求支持的系统是:32位XP、WIN7、WIN8、WIN8.1;64位的WIN7(可以破PG)。
于是解决方案就是:Hook ObReferenceObjectByHandle/ObReferenceObjectByHandleWithTag。它们的原型是:
NTSTATUS ObReferenceObjectByHandle
(
_In_ HANDLE Handle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_TYPE ObjectType,
_In_ KPROCESSOR_MODE AccessMode,
_Out_ PVOID *Object,
_Out_opt_ POBJECT_HANDLE_INFORMATION HandleInformation
);
NTSTATUS ObReferenceObjectByHandleWithTag
(
_In_ HANDLE Handle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_TYPE ObjectType,
_In_ KPROCESSOR_MODE AccessMode,
_In_ ULONG Tag,
_Out_ PVOID *Object,
_Out_opt_ POBJECT_HANDLE_INFORMATION HandleInformation
);
ObReferenceObjectByHandle/ObReferenceObjectByHandleWithTag是一对非常讨巧的API,所有需要句柄的进程/线程操作中,都需要用到它们。因为它们执行的是“句柄->对象”的转换操作。如果在这里下绊,就会让各种句柄“被”失效。而正巧那个用户所搞的“某保护”,就是用ZwQueryInformationProcess获取进程路径的。之所以要HOOK两个函数,是因为WIN8以及之后的系统(在诸如ZwQueryInformationProcess等函数里)不再使用ObReferenceObjectByHandle执行“句柄->对象”的转换操作,而改用ObReferenceObjectByHandleWithTag。最终策略就是:对于WIN8之前的系统,挂钩ObReferenceObjectByHandle;从WIN8开始,挂钩ObReferenceObjectByHandleWithTag。值得一提的是对PVOID *Object这个参数的处理,个人为了稳定,直接对这个对象执行“反查询操作”。最后把函数返回失败。但其实可以耍点阴招,就是在执行完“反查询操作”后,把*Object的值赋为PsGetCurrentProcess(),然后用ObReferenceObject增加一次引用计数。于是最后操作者操作的就是自身的进程。如果是查询路径,得到的就是自身的路径,如果是结束进程,结束的就是自己的进程。
|
|