Posted on 2010-12-17 14:48
Tinpont 阅读(2504)
评论(3) 编辑 收藏 引用 所属分类:
驱动学习
最近期末答辩不知道写什么好,就写一个安全软件吧。软件使用驱动和C++编写,大概多数安全软件都是这样吧。
时间关系,就不说那么多了,直接入正题吧。
在此先感谢“伊丽_杀_白”、“堕落天才”、“antirootkit”等提供的优秀文章,我只是在他们基础之上修改了一下。
伊丽_杀_白 暴力搜索内存空间检测隐藏进程:
http://bbs.xdnice.com/thread-377796-1-1.html堕落天才 ring0检测隐藏进程:
http://bbs.pediy.com/showthread.php?t=44243antirootkit 枚举隐藏进程for ring0(搜索内存大法):
http://hi.baidu.com/antirootkit/blog/item/d2314b5c94772040fbf2c00b.html 原理:
大概流程图如下,当然我修改了部分。
下面看代码吧,没时间了,等下十点还要上课,有不明白的可以留言。我会解答的。
不过这种方法还是很容易躲过,详细就不公布出来了,看来还是要找另外一种方法了。
#include<ntddk.h>
//EPROCESS结构大小,我的系统是XP SP3,所以0x260,不过经过测试,这里设置成比实际EPROCESS小也是没问题的
#define EPROCESS_SIZE 0x260
#define PEB_OFFSET 0x1B0 //PEB偏移,下面就不注释了
#define FILE_NAME_OFFSET 0x174
#define PROCESS_LINK_OFFSET 0x088
#define PROCESS_ID_OFFSET 0x084
#define EXIT_TIME_OFFSET 0x078
#define OBJECT_HEADER_SIZE 0x018
#define OBJECT_TYPE_OFFSET 0x008
ULONG ulPebAddress; //PEB地址的前半部分
ULONG ulStartAddress, ulEndAddress; //起始,结束地址
ULONG ulObjectType; //进程对象类型
BOOLEAN IsaRealProcess(ULONG pEprocess); //该函数判断是否真的是进程
VOID WorkThread(IN PVOID pContext); //新开线程防止系统顿卡
VOID UpdateEndStartPebAddress(); //更新首尾地址和PEB地址
VOID EnumProcess(); //枚举进程
VOID ShowProcess(ULONG pEProcess); //显示进程信息
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
HANDLE hThread;
DriverObject -> DriverUnload = OnUnload;
UpdateEndStartPebAddress();
ulObjectType = *(PULONG)((ULONG)ulEndAddress - OBJECT_HEADER_SIZE + OBJECT_TYPE_OFFSET);
PsCreateSystemThread(&hThread,
(ACCESS_MASK)0,
NULL,
(HANDLE)0,
NULL,
WorkThread,
NULL );
return STATUS_SUCCESS;
}
//////////////////////////////////////////////
VOID WorkThread(IN PVOID pContext)
{
EnumProcess();
PsTerminateSystemThread(STATUS_SUCCESS);
}
////////////////////////////////////////////////////////
VOID UpdateEndStartPebAddress()
{
ULONG ulEProcessAddress = (ULONG)IoGetCurrentProcess();
ULONG pEProcess;
//IoGetCurrentProcess返回的是System进程EPROCESS结构地址,此处已经是搜索结束处。
ulStartAddress = ulEndAddress = ulEProcessAddress;
ulEProcessAddress = (ULONG)(((PLIST_ENTRY)(ulEProcessAddress + PROCESS_LINK_OFFSET))->Flink) - PROCESS_LINK_OFFSET;
ulPebAddress = *(PULONG)(ulEProcessAddress + PEB_OFFSET) & 0xFFFF0000;
while (ulEProcessAddress != ulEndAddress)
{ //遍历EPROCESS结构,找到最小地址处
ulEProcessAddress = (ULONG)(((PLIST_ENTRY)(ulEProcessAddress + PROCESS_LINK_OFFSET))->Flink) - PROCESS_LINK_OFFSET;
if (ulStartAddress > ulEProcessAddress)
ulStartAddress = ulEProcessAddress;
}
}
///////////////////////////////////////////////////////
VOID EnumProcess()
{
ULONG i;
ULONG nCount = 2;
ULONG Address;
ULONG ret;
KdPrint(("-------------------------------------------\r\n"));
KdPrint(("EProcess PID ImageFileName\r\n"));
KdPrint(("-------------------------------------------\r\n"));
//系统空闲进程的检测方法有点特殊,只作参考
ShowProcess(*(PULONG)(ulStartAddress + PROCESS_ID_OFFSET));
//system的PEB总是零 上面的方法是枚举不到的 不过我们用PsGetCurrentProcess就能得到了
ShowProcess(ulEndAddress);
for(i = ulStartAddress; i < ulEndAddress; i += 4) {//system进程的EPROCESS地址就是最大值了
if (MmIsAddressValid((PVOID)i)) {
Address = *(PULONG)i;
if (( Address & 0xFFFF0000) == ulPebAddress){//每个进程的PEB地址都是在差不多的地方,地址前半部分是相同的
if (IsaRealProcess(i)) {
ShowProcess(i - PEB_OFFSET);
i -= 4;
i += EPROCESS_SIZE;
nCount ++;
}
}
} else {
i -= 4;
i += 0x5000000;//5M
}
}
KdPrint(("-------------------------------------------\r\n"));
KdPrint(("===== Total Processes count:%3d =======\r\n", nCount));
KdPrint(("-------------------------------------------\r\n"));
}
/////////////////////////////////////////////////////////
VOID ShowProcess(ULONG pEProcess)
{
PLARGE_INTEGER ExitTime;
ULONG PID;
PUCHAR pFileName;
ExitTime = (PLARGE_INTEGER)(pEProcess + EXIT_TIME_OFFSET);
if(ExitTime->QuadPart != 0) //已经结束的进程的ExitTime为非零
return ;
PID = *(PULONG)(pEProcess + PROCESS_ID_OFFSET);
pFileName = (PUCHAR)(pEProcess + FILE_NAME_OFFSET);
KdPrint(("0x%08X %04d %s\r\n",pEProcess,PID,pFileName));
}
////////////////////////////////////////////////////////////////
BOOLEAN IsaRealProcess(ULONG pEprocess)
{
NTSTATUS STATUS;
PUNICODE_STRING pUnicode;
UNICODE_STRING Process;
ULONG pObjectType;
ULONG ObjectTypeAddress;
if (!MmIsAddressValid((PVOID)(pEprocess - PEB_OFFSET)))
return FALSE;
ObjectTypeAddress = pEprocess - PEB_OFFSET - OBJECT_HEADER_SIZE + OBJECT_TYPE_OFFSET ;
if (MmIsAddressValid((PVOID)ObjectTypeAddress)) {
pObjectType = *(PULONG)ObjectTypeAddress;
} else {
return FALSE;
}
if(ulObjectType == pObjectType) {//确定ObjectType是Process类型
return TRUE;
}
return FALSE;
}