首页
社区
课程
招聘
[求助]在R0下抹CSRSS中的句柄的问题
发表于: 2009-9-6 15:02 10102

[求助]在R0下抹CSRSS中的句柄的问题

2009-9-6 15:02
10102
由于在R3duplicate出CSRSS中句柄并close的方法不可逆,会引发诸多问题,于是我想自己在R0下定位句柄信息,并保存相关的地址和数据,先抹掉,再系统需要该信息时通过前面保存的信息还原之
        我的做法是先定位到CSRSS的EPROCESS结构,通过ObjectTable定位到TableCode,这个就是句柄表地址了,我用Windbg看了下,后3位为0,即该句柄表只有一层,但是问题是,通过遍历该句柄表,我发现里面的存放的对象没有PROCESS对象,我是通过对象头的Type == ProcessType来判断的,但是发现没有满足该条件的。。。。
        请问我的这种思路有问题吗??
        详细代码如下:
//该函数通过以当前进程作为例子来获取自身的对象类型的指针,类型也就是ProcessType
POBJECT_TYPE GetProcessType()
{
	PEPROCESS Process = PsGetCurrentProcess();
	POBJECT_HEADER ObjectHeader = (POBJECT_HEADER)((ULONG)Process - 0x18);     //得到对象头指针
	return ObjectHeader->Type;
}

PCSRSS_INFO HideProcessInCsrss(ULONG CsrssId, ULONG ProcessId)     //在Csrss中抹掉该进程的信息,并返回该信息用于还原
{
	PEPROCESS Csrss;
	NTSTATUS ntStatus = PsLookupProcessByProcessId((HANDLE)CsrssId, &Csrss);
	if(!NT_SUCCESS(ntStatus))
	{
		return NULL;
	}
	PHANDLE_TABLE ObjectTable = *(PHANDLE_TABLE*)((ULONG)Csrss + OFFSET_EPROCESS_OBJECTTABLE);
	ULONG TableCode = ObjectTable->TableCode;
	PHANDLE_TABLE_ENTRY Table_1,Table_2;
	ULONG Object;
	POBJECT_TYPE ProcessType;
	POBJECT_HEADER ObjectHeader;
	ProcessType = GetProcessType();
	if((TableCode & 0x03) == 0x00)
	{
		Table_1 = (PHANDLE_TABLE_ENTRY)TableCode;
		Table_2 = 0;
	}
	else if((TableCode & 0x03) == 0x01)
	{
		TableCode = TableCode & 0xfffffffc;       //去除低2位掩码
		Table_1 = *(PHANDLE_TABLE_ENTRY*)TableCode;
		Table_2 = *(PHANDLE_TABLE_ENTRY*)(TableCode + 1);          //1级表每8字节存放一个索引项,索引项为PHANDLE_TABLE_ENTRY(个人理解)
	}
	for (ULONG index = 0; index < 0x4e1c; index++)
	{
		if(index <= 0x800)
		{
			if(MmIsAddressValid((PHANDLE_TABLE_ENTRY)(Table_1 + index)))
			{
				Object = ((Table_1 + index)->Object) & 0xfffffff8;      //去掉掩码(因为是以4字节作为内存对齐)
			//	if( (Table_1 + index)->NextFreeTableEntry == 0 )
				{
					//为0则为正常
					ObjectHeader = (POBJECT_HEADER)(Object - 0x18);       //Object相对于ObjectHeader偏移0x18
					if(MmIsAddressValid((POBJECT_TYPE)&(ObjectHeader->Type)))
					{
						if(ObjectHeader->Type == ProcessType)
						{
							PEPROCESS Process = (PEPROCESS)Object;
							if( (*(PULONG)((ULONG)Process + OFFSET_EPROCESS_FLAGS) & 0x0c) != 0x0c )
							{
								if(MmIsAddressValid((PEPROCESS)Process))
								{
									if( ((ULONG)Process + OFFSET_EPROCESS_UNIQUEPROCESSID) == ProcessId )
									{
										PCSRSS_INFO pCsrssInfo = (PCSRSS_INFO)ExAllocatePool(PagedPool, sizeof(CSRSS_INFO));
										pCsrssInfo->Address = (PHANDLE_TABLE_ENTRY)(Table_1 + index);
										RtlCopyMemory(&(pCsrssInfo->hte), pCsrssInfo->Address, sizeof(HANDLE_TABLE_ENTRY));
										RtlZeroMemory(pCsrssInfo->Address, sizeof(HANDLE_TABLE_ENTRY));
										return pCsrssInfo;
									}
								}


							}
						}
					}

				}

			}
		}
		else
		{
			if(Table_2 != 0)
			{
				if(MmIsAddressValid((PHANDLE_TABLE_ENTRY)(Table_2 + index - 0x800)))
				{
					Object = ((Table_2 + index - 0x800)->Object) & 0xfffffff8;      //去掉掩码(因为是以4字节作为内存对齐)
					if( (Table_2 + index - 0x800)->NextFreeTableEntry == 0 )
					{
						//为0则为正常
						ObjectHeader = (POBJECT_HEADER)(Object - 0x18);       //Object相对于ObjectHeader偏移0x18
						if(MmIsAddressValid((POBJECT_TYPE)&(ObjectHeader->Type)))
						{
							if(ObjectHeader->Type == ProcessType)
							{
								PEPROCESS Process = (PEPROCESS)Object;
								if( (*(PULONG)((ULONG)Process + OFFSET_EPROCESS_FLAGS) & 0x0c) != 0x0c )
								{
									if(MmIsAddressValid((PEPROCESS)Process))
									{
										if( ((ULONG)Process + OFFSET_EPROCESS_UNIQUEPROCESSID) == ProcessId )
										{
											PCSRSS_INFO pCsrssInfo = (PCSRSS_INFO)ExAllocatePool(PagedPool, sizeof(CSRSS_INFO));
											pCsrssInfo->Address = (PHANDLE_TABLE_ENTRY)(Table_2 + index - 0x800);
											RtlCopyMemory(&(pCsrssInfo->hte), pCsrssInfo->Address, sizeof(HANDLE_TABLE_ENTRY));
											RtlZeroMemory(pCsrssInfo->Address, sizeof(HANDLE_TABLE_ENTRY));
											return pCsrssInfo;
										}
									}

								}
							}
						}
					}
				}
			}
		}

	}
	return NULL;
}


代码写得很挫,如果不想看就麻烦看看我的思路,指点下我的思路是否有问题?谢谢各位了

[课程]Android-CTF解题方法汇总!

收藏
免费 0
支持
分享
最新回复 (18)
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
2
csrss是普通进程,它的句柄表里直接就是Object_Header,不用再减0x18,这一点跟PspCidTable是不一样的~~
2009-9-6 17:32
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
3
又见0x4e1c~~
2009-9-6 17:33
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
有得就有失   

这东西运行前 最好先祷告一下哦。。。
2009-9-6 19:29
0
雪    币: 212
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
前些天海风也提出了跟楼主很相似的思路,很强悍,顶一个。
2009-9-7 09:11
0
雪    币: 146
活跃值: (33)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
这个硬编码肯定有问题啦,我只是想先把思路成型后再处理这个细节处,教主太细心了。。。。
2009-9-7 09:28
0
雪    币: 146
活跃值: (33)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
7
就算是这样也不对劲额。。。我用WinDbg看了下,发现HandleTable中的居然没有一个对象是Process类型的。。。
2009-9-7 09:30
0
雪    币: 146
活跃值: (33)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
8
海风大侠出发点肯定和我不一样啦,我菜鸟的想法很天真的,呵呵
2009-9-7 09:30
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
9

怎么可能嘛?结合Process Explorer看一下~~
2009-9-7 10:23
0
雪    币: 251
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
一般的句柄表,最后关闭的句柄被放在空闲队列的头部
所以只要关闭后立即打开一个句柄就能把原来的位置占住(虽然不是很可靠,有同步问题)
因此 在用户态还原句柄也不是不可能
2009-9-7 11:10
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
11
用户态光有句柄也不行,你可以得到一个和原来一样的句柄,但对象不一定是那个对象。对csrss这个例子也可以象楼上说的在关闭你的进程句柄后再马上打开一个内核对象先把那个句柄占住,在需要恢复的时候关掉刚才占位的句柄,再立刻打开保存的那个进程,这样就恢复了~~在别的进程里关闭、打开可以用DuplicateHandle,不过确实存在同步问题
2009-9-7 12:07
0
雪    币: 146
活跃值: (33)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
12
已经在R0里解决了,发现还是那个ObjectHead当成ObjectBody的问题了。。。。
不过郁闷的是,确实抹了,但是IceSword还是能检测到进程。。。。进程链也断了,PspCidTable也抹了,CSRSS也抹了。。。还能检测到。。。他不会是连非进程类对象也检举吧,这样我的进程里的其他对象可能泄露我的踪迹,不知道这样理解对不???
2009-9-7 13:18
0
雪    币: 146
活跃值: (33)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
13
要是过程中发生了线程切换,而且切换后的线程刚好执行了打开一个句柄,那就。。。。。。
2009-9-7 13:20
0
雪    币: 146
活跃值: (33)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
14
其实我不知道这个0x4e1c到底有啥特殊含义,这个大小到底有啥特殊含义啊。。。
2009-9-7 13:24
0
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
15
icesword等有eprocess爆搜~光抹这个东西没啥用
2009-9-7 13:34
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
16
IceSword都被人研究得那么透了你竟然还不知道它是怎么枚举进程,就稀里糊涂地写什么隐藏…
2009-9-7 15:27
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
17
在正常情况下,0x4e1c作为PID上限足够了,但是这个数并没有什么合理的依据,也并不可靠,真正上限是PspCidTable->NextHandleNeedingPool
2009-9-7 15:38
0
雪    币: 146
活跃值: (33)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
18
研究得再透我没看到资料还是一样啦,初学都不知道哪里搞资料。。。。
2009-9-7 16:02
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
19
那你还是先把搜索引擎用好…推荐hi.baidu.com/isreverse,yykingking出品~
2009-9-7 18:20
0
游客
登录 | 注册 方可回帖
返回
//