清除句柄表保护进程

上节课老师讲错了属性是最后两位,0xfffffffc,并且从句柄表中取出来的值也要-1才能用通过逆向PsLookupProcessByProcessId可以知道

//关键代码
 v4 = (struct _KPROCESS **)ExMapHandleToPointer(ProcessId);
 //->
     v2 = (volatile signed __int32 *)ExpLookupHandleTableEntry(NewIrql);
    if ( v2 )
    {
      while ( 1 )
      {
        v3 = *v2;
        if ( (*v2 & 1) != 0 )
        {
        //_InterlockedCompareExchange这个函数就是比较1,3参数一样就把值给参数1
          if ( _InterlockedCompareExchange(v2, v3 - 1, v3) == v3 )
            return v2;
        }
 

之后讲了利用系统使用ExpLookupHandleTableEntry判断是否超过最大句柄返回0,就不会蓝屏(老师说这里会返回0)

if ( (a2 & 0xFFFFFFFC) >= this[13] )
    return 0;

但是事实上当你把PID修改为0时,系统调用时并不会返回,他会按部就班的去寻找这个PID的句柄。没有蓝屏只是因为这个PID的进程没有退出或者根本就没有时,软件的退出才不会蓝屏,所以如果你把PID修改为4(system的PID)时也不会蓝屏。但是你要是按照条件去做这个判断时比如说填个0XFFFF FFFF时还是会蓝屏的

VOID ClearHandleTableByPid(ULONG pid) {
	UNICODE_STRING funcName = { 0 };
	RtlInitUnicodeString(&funcName, L"PsLookupProcessByProcessId");
	PUCHAR targetAddr = MmGetSystemRoutineAddress(&funcName);
	if (!targetAddr) {
		DbgPrint("MmGetSystemRoutineAddress\n");
		return;
	}

	PULONG PspCidTable = 0;
	USHORT keyWord = 0x3d8b;
	for (size_t i = 0; i < 100; i++) {
		if (!(*(PUSHORT)targetAddr - keyWord)) {
			PspCidTable = *(PULONG)(targetAddr + 2);
			DbgPrint("PspCidTable:%p\n", PspCidTable);
		}
		targetAddr++;
	}

	pid /= 4;
	ULONG handleTableDir = pid / HANDLE_TABLE_SIZE;
	ULONG handleEntry = pid % HANDLE_TABLE_SIZE;
	handleTableDir = (*(PULONG)(*PspCidTable) & 0xfffffffc) + sizeof(PVOID) * handleTableDir;
	handleEntry = *(PULONG)handleTableDir + handleEntry * 8;

	HANDLE handle = (ULONG)(*(PHANDLE)handleEntry) & 0xfffffffc;
	memset(handleEntry, 0, 8);

	DbgPrint("handle:%p\n", handle);
	DWORD offset = GetProcessIdOffset();
	*(PULONG)((PUCHAR)handle + offset) = 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这段代码定义了一个事件标志组句柄 EventGroupHandler,它的类型是 EventGroupHandle_t。事件标志组是一种用于进程间通信的机制,在FreeRTOS中被广泛使用。本段代码还定义了一些事件位,包括 EVENTBIT_0、EVENTBIT_1、EVENTBIT_2 和 EVENTBIT_ALL。这些事件位可以被用来示不同的事件状态。 在使用事件标志组时,你可以通过调用 xEventGroupCreate() 函数来创建一个事件标志组,然后使用 xEventGroupSetBits() 函数来设置事件位,使用 xEventGroupClearBits() 函数来清除事件位,使用 xEventGroupWaitBits() 函数来等待事件位的状态变化。例如,下面的代码可以将 EVENTBIT_1 和 EVENTBIT_2 设置为事件标志组中的事件位: ```c EventGroupHandler = xEventGroupCreate(); // 创建事件标志组 xEventGroupSetBits(EventGroupHandler, EVENTBIT_1 | EVENTBIT_2); // 设置事件位 ``` 在等待事件位状态变化的时候,可以使用 xEventGroupWaitBits() 函数等待事件位被设置或清除,并且可以指定等待的事件位和等待的方式(例如等待所有事件位都被设置、等待任何一个事件位被设置等等)。例如,下面的代码可以等待 EVENTBIT_1 和 EVENTBIT_2 都被设置: ```c EventBits_t bits = xEventGroupWaitBits(EventGroupHandler, EVENTBIT_1 | EVENTBIT_2, pdTRUE, pdFALSE, portMAX_DELAY); if ((bits & (EVENTBIT_1 | EVENTBIT_2)) == (EVENTBIT_1 | EVENTBIT_2)) { // EVENTBIT_1 和 EVENTBIT_2 都被设置了 } ``` 需要注意的是,在使用事件标志组时,需要确保所有任务都使用相同的事件标志组句柄
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值