首页
社区
课程
招聘
[原创]code:pspcidtable列进程
发表于: 2009-8-5 02:19 8770

[原创]code:pspcidtable列进程

2009-8-5 02:19
8770
//======================================获取pspcidtable地址CODE1=======================
//利用PsLookupXX函数搜索特征码0x35ff和0xe8获取
ULONG GetAddrFromProcessId()
{  
	UNICODE_STRING pslookup;
	PUCHAR addr;              //单字节指针
	PUCHAR p;                 //单字节指针
	ULONG q;                  //四字节
	RtlInitUnicodeString(&pslookup,L"PsLookupProcessByProcessId");
	addr=(PUCHAR)MmGetSystemRoutineAddress(&pslookup);
	KdPrint(("[PsLookupProcessByProcessId] addr:0x%x\n",addr));
	for(p=addr;p<addr+PAGE_SIZE;p++)
	{
		if((*(PUSHORT)p==0x35ff)&&(*(p+6)==0xe8))
		{  
			q=*(PULONG)(p+2);
			KdPrint(("[GetAddrFromProcessId] pspcidtable:0x%x\n",q));
			return q;
			break;
		}
	}
	return 0;
}
//======================================获取pspcidtable地址CODE2=======================

//利用KPCR取得
ULONG GetAddrFromKpcr()
{
	ULONG pspcidtable;
	//#define kpcr   0xffdff000
	//kpcr+0x37 是KdVersionBlock
    //KdVersionBlock+0x80是pspcidtable指针
	pspcidtable=*((PULONG)((*(PULONG)(kpcr+0x34)) + (ULONG)(0x80)));
	KdPrint(("[GetAddrFromKpcr] pspcidtable:0x%x\n",pspcidtable));
	return pspcidtable;
	
}
//====================================获取pspciatable地址CODE3=========================
//KdEnableDebugger->KdInitSystem->KdDebuggerDataBlock->KDDEBUGGER_DATA32->PspCidTable

//======================================================================================
//====================================遍历pspcidtable CODE1=========================
//利用导出的ExEnumHandleTable(ntoskrnl.exe导出函数),可以直接操作,不需要根据GMM自己定位地址

//================================================================================
//====================================自己遍历pspcidtable表=========================
//=============通过当前进程获取进程对象指针(PsGetCurrentProcess函数获取object指针转换成object_header里面记录对象类型)===============
typedef struct _OBJECT_HEADER
{
	union
	{
		struct
		{
			LONG PointerCount;
			LONG HandleCount;
		};
		LIST_ENTRY Entry;
	};
	POBJECT_TYPE Type;
	UCHAR NameInfoOffset;
	UCHAR HandleInfoOffset;
	UCHAR QuotaInfoOffset;
	UCHAR Flags;
	union
	{
		//POBJECT_CREATE_INFORMATION ObjectCreateInfo;
		PVOID QuotaBlockCharged;
	};
	PSECURITY_DESCRIPTOR SecurityDescriptor;
	QUAD Body;
} OBJECT_HEADER, *POBJECT_HEADER;
ULONG  GetProcessType()
{
	ULONG  type;
	ULONG  objecttoeprocess;
	objecttoeprocess=(ULONG)PsGetCurrentProcess();
	//object转换成object_header完全可以object-0x18
	objecttoeprocess=(ULONG)OBJECT_TO_OBJECT_HEADER(objecttoeprocess);
	type=*(PULONG)(objecttoeprocess+TYPE);
	KdPrint(("[GetProcessType] type:0x%x\n",type));
	return type;
}
//===================================采用单链表记录进程Eprocess地址================================================
void RecordProcess(ULONG address) //address  
{  
	PROCESSINFO *r;
	if(head==NULL)
	{
		head=(PROCESSINFO *)ExAllocatePoolWithTag(NonPagedPool,sizeof(PROCESSINFO),MEM_TAG);//分配头指针
		if(head==NULL)
		{
			KdPrint(("[RecoardProcess] Aloocate error\n"));
		}
		//分配内存,用完必须释放,否则内存泄漏
		head->addr=0x0;
	}
	if(head->addr==0x0)
	{
		head->addr=address;
		KdPrint(("[RecordProcess] head->addr:0x%x",head->addr));
		p=head;
	}
	else
	{
		r=(PROCESSINFO *)ExAllocatePoolWithTag(NonPagedPool,sizeof(PROCESSINFO),MEM_TAG);
		if(r==NULL)
		{
			KdPrint(("[RecoardProcess] Aloocate error\n"));
		}
		p->next=r;
		p=r;
		r->addr=address;
		KdPrint(("[RecoardProcess] r->addr:0x%x\n",r->addr));
		r->next=NULL;
	}
}
//==================================根据PID找对象指针=====================================================
void GetPointerToObject(ULONG table,ULONG pid)//函数返回的object即指向EPROCESS的指针
{   
	
    ULONG object,objectheader;
    ULONG NextFreeTableEntry;
    ULONG processtype,type;
    ULONG flags;
    processtype=GetProcessType();//调用函数获取进程类型
    if(MmIsAddressValid((PULONG)(table+pid*2)))
    {  
        if(MmIsAddressValid((PULONG)(table+ pid*2 +NEXTFREETABLEENTRY)))
        {
            
            NextFreeTableEntry=*(PULONG)(table + pid*2 + NEXTFREETABLEENTRY);
            if(NextFreeTableEntry==0)//正常的handle_table_entry中NextFreeTableEntry为0
            {
                object=*(PULONG)(table+pid*2);
                object=((object | 0x80000000)& 0xfffffff8);//转换为对象指针
                KdPrint(("[GetPointerToObject] object:0x%x\n",object));    //函数要记录的进程ERROCESS地址
                objectheader=(ULONG)OBJECT_TO_OBJECT_HEADER(object);//获取对象头指针
                KdPrint(("[GetPointerToObject] objectheader:0x%x\n",objectheader));
                if(MmIsAddressValid((PULONG)(objectheader+TYPE)))
                {  
                    type=*(PULONG)(objectheader+TYPE);
                    if(type==processtype)//表明是进程对象
                    {  
                        flags=*(PULONG)(object+FLAGS);//EPROCESS中Flags偏移量,指明了进程的死活
                        //KdPrint(("[GetPointerToObject]) flags:0x%x\n",flags)
                        if((flags&0xc)!=0xc)//死进程的flags最后一位为C
                        {
                            RecordProcess(object);
							num=num+1;  //进程数量
                        }      
                    }
                }
            }
        }
        
    }
    
}

//==================================遍历pspcidtable列举进程信息============================================
void ListProcess()
{
	ULONG pspcidtable;
	ULONG tablecode;
	ULONG table1,table2,table3,table4,table5;  //2层表正常情况下足够存放进程了,所以3层表就不考虑
	
    ULONG cid;
	ULONG NextHandleNeedingPool;
	
	pspcidtable=GetAddrFromKpcr();  //取pspcidtable地址
	KdPrint(("[ListProcess]pspcidtable:0x%x\n",pspcidtable));
	if(MmIsAddressValid((PULONG)pspcidtable))//地址是否有效
	{
		tablecode=*(PULONG)(*(PULONG)pspcidtable);//取tablecode地址
		NextHandleNeedingPool=*(PULONG)(*(PULONG)pspcidtable+0x038);//NextHandleNeedingPool值
		KdPrint(("[ListProcess] tablecode:0x%x\n",tablecode));
		KdPrint(("[ListProcess] NextHandleNeedingPool:0x%0x\n",NextHandleNeedingPool));  //PID最大值
		if((tablecode & 0x00000003)==0)//1层表存放的就是handle_table的基址
		{
			table1=tablecode;
			KdPrint(("[ListProcess] table1:0x%0x\n",table1));
			table2=0;
		}
		else if((tablecode & 0x00000003)==1)//2层表,一级表存放的是指向2级表的指针
		{   
			tablecode=tablecode&0xfffffffe;  //低二位清零
            table1=*(PULONG)tablecode;    //1个表存放0x800=2048大的PID,不够大  
			table2=*(PULONG)(tablecode+4);//2个表存放0x1000=4096大的PID,不够大
            table3=*(PULONG)(tablecode+8);//3个表存放0x1800=6144大的PID,不够大
			table4=*(PULONG)(tablecode+12);//4个表可以存放0x2000=8192大的PID,还不够大啊
            table5=*(PULONG)(tablecode+16);//5个表可以存放0x2800=10240的的PID,足够了吧
			KdPrint(("[ListProcess] table1:0x%x\n",table1));
            KdPrint(("[ListProcess] table2:0x%x\n",table2));
			KdPrint(("[ListProcess] table3:0x%x\n",table3));
			KdPrint(("[ListProcess] table4:0x%x\n",table4));
            KdPrint(("[ListProcess] table5:0x%x\n",table5));
		}
        //遍历
		
		for(cid=0;cid<NextHandleNeedingPool;cid=cid+4)//要加4
		{
			if((table1!=0)&&(cid<=0x800))//在第一个表中
			{
                GetPointerToObject(table1,cid);
			}
			if((table2!=0)&&(0x800<cid && cid<=0x1000))//在第二个表中
			{
				cid=(ULONG)(cid-0x800);
				//KdPrint(("[ListProcess] cid 0x%x\n",cid));
				GetPointerToObject(table2,cid);
                cid=(ULONG)(cid+0x800);
                //KdPrint(("[ListProcess] cid 0x%x\n",cid));
			}
			if((table3!=0)&&(0x1000<cid && cid<=0x1800))//在第三个表中
			{
				cid=(ULONG)(cid-0x1000);
				GetPointerToObject(table3,cid);
				cid=(ULONG)(cid+0x1000);
				
			}
			if((table4!=0)&&(0x1800<cid && cid<=0x2000))//在第四个表中
			{
				cid=(ULONG)(cid-0x1800);
				GetPointerToObject(table4,cid);
				cid=(ULONG)(cid+0x1800);
			}
			if((table5!=0)&&(0x2000<cid && cid<=0x2800))//在第五个表中
			{
				cid=(ULONG)(cid-0x2000);
				GetPointerToObject(table5,cid);
				cid=(ULONG)(cid+0x2000);
			}
		}
		
	}
	
}
//
//取进程全路径====================================================================
//原理Eprocess->sectionobject(0x138)->Segment(0x014)->ControlAera(0x000)->FilePointer(0x024)->(FileObject->FileName,FileObject->DeviceObject)
void GetProcessPath(ULONG eprocess,CHAR ProcessPath[256])
{
	ULONG object;
	PFILE_OBJECT FilePointer;
	UNICODE_STRING path;  //路径
	UNICODE_STRING name;  //盘符
	ANSI_STRING  string;
	path.Length=0;
    path.MaximumLength=256;
	path.Buffer=(PWCHAR)ExAllocatePoolWithTag(NonPagedPool,256,MEM_TAG);     //必须释放
	if(MmIsAddressValid((PULONG)(eprocess+0x138)))//Eprocess->sectionobject(0x138)
	{
		object=(*(PULONG)(eprocess+0x138));
        KdPrint(("[GetProcessFileName] sectionobject :0x%x\n",object));
		if(MmIsAddressValid((PULONG)((ULONG)object+0x014)))
		{
			object=*(PULONG)((ULONG)object+0x014);
			KdPrint(("[GetProcessFileName] Segment :0x%x\n",object));
			if(MmIsAddressValid((PULONG)((ULONG)object+0x0)))
			{
				object=*(PULONG)((ULONG_PTR)object+0x0);
				KdPrint(("[GetProcessFileName] ControlAera :0x%x\n",object));
				if(MmIsAddressValid((PULONG)((ULONG)object+0x024)))
				{
					object=*(PULONG)((ULONG)object+0x024);
					KdPrint(("[GetProcessFileName] FilePointer :0x%x\n",object));
				}
				else
					return ;
			}
			else
				return ;
		}
		else
			return ;
	}
	else
		return ;
    FilePointer=(PFILE_OBJECT)object;
    //KdPrint(("[GetProcessFileName] FilePointer :%wZ\n",&FilePointer->FileName));
	ObReferenceObjectByPointer((PVOID)FilePointer,0,NULL,KernelMode);//引用计数+1,操作对象
	RtlVolumeDeviceToDosName(FilePointer->DeviceObject,&name); //获取盘符名
	//KdPrint(("[GetProcessFileName] FilePointer :%wZ\n",&name));
    RtlCopyUnicodeString(&path,&name);//盘符连接
	RtlAppendUnicodeStringToString(&path,&FilePointer->FileName);//路径连接
	//KdPrint(("[GetProcessFileName] FilePointer :%wZ\n",&path));
	ObDereferenceObject(FilePointer);         //关闭对象引用
	//需要转换成ANSI_STRING,然后在转换成char输出给ring3
	RtlUnicodeStringToAnsiString(&string,&path,TRUE);    //释放内存
	if(string.Length >= 256 ) //保证以\0结尾
	{ 
		memcpy(ProcessPath, string.Buffer, 256); 
		*(ProcessPath + 255) = 0; 
	} 
	else 
	{ 
		memcpy(ProcessPath, string.Buffer, string.Length); 
		ProcessPath[string.Length] = 0; 
	}
	ExFreePool(path.Buffer); //释放
	RtlFreeAnsiString(&string);//释放
}
//====================================进程信息==========================================================
void  GetProcessInformation()//获取进程名,PID,路径
{
	ListProcess();       //调用函数
	KdPrint(("[DispatchIoctl] num:%d\n",num));//打印出进程数量
	for(p=head;MmIsAddressValid(p);p=p->next)     //写实现功能,获取进程PID,进程名,图标、全路径
	{   
		//KdPrint(("===============================================\n"));
		KdPrint(("[GetProcessInformation] EPROCESS:0x%x\n",p->addr));
		//EPROCESS获取进程名
		//XP下0x084偏移存放的进程PID
		//XP下0x174偏移存放的进程ProcessName
		p->pid=*(int *)(p->addr+CID);
		KdPrint(("[GetProcessInformation] PID:%d\n",p->pid));           //进程PID
		KdPrint(("===============================================\n"));
		memcpy(p->name,(PUCHAR)(p->addr+NAME),16);
		KdPrint(("[GetProcessInformation] ProcessName:%s\n",p->name));  //进程名   
		//获取全路径
		GetProcessPath(p->addr,p->Path);
		KdPrint(("[GetProcessInformation] ProcessPath:%s\n",p->Path)); //进程全路径
	}
}
//==================================释放链表函数=========================================================
void FreeList()
{
    //释放链表,释放内存
	PROCESSINFO *q;
    p=head;
	q=p->next;
	while(q!=NULL)
	{
		KdPrint(("[DispathIoctl] p->addr:0x%x\n",p->addr));
		ExFreePool(p);
		p=q;
		q=p->next;
		n=n+1;
	}
	KdPrint(("[DispathIoctl] p->addr:0x%x\n",p->addr));
	ExFreePool(p);
	head=NULL;        //不知道ExFreePool释放后head竟然不为NULL.p和head都是全局变量
	n=n+1;
	KdPrint(("[DispatchIoctl] n:%d\n",n));//打印出释放进程数量
	n=0;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 130
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我怎么一个也看不懂啊!?
2009-8-5 12:18
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
很少看到不用硬编码的驱动代码阿
2009-8-5 19:37
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
4
计算Cid部分写得太繁琐了…完全不用分那么多情况,而且你明知NextHandleNeedingPool是上限却仍然假设是5张表,混乱
2009-8-5 20:11
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
5
同意LS
2009-8-6 02:17
0
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
mark 顺路膜拜sd
2009-8-8 00:00
0
雪    币: 135
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
全部收藏学习了。。。
2009-8-20 23:26
0
游客
登录 | 注册 方可回帖
返回
//