|
#include<ntddk.h> #include <windef.h> #include "processenum.h"
/*processenum文件的内容为
#ifndef MYSAFE_PSENUM_DRIVER_H__ #define MYSAFE_PSENUM_DRIVER_H__
#define PROCESS_ENUM_DEVICE 0x8000
// 获取进程列表 #define IOCTL_GETPROCESSPTR CTL_CODE(PROCESS_ENUM_DEVICE, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS) // METHOD_OUT_DIRECT
typedef struct Processinfo { unsigned long pEProcess; unsigned long PId; char Name[60]; } Processinfo;
#endif
*/
#define EPROCESS_SIZE 0x0 //EPROCESS结构大小
#define PEB_OFFSET 0x1 #define FILE_NAME_OFFSET 0x2 #define PROCESS_LINK_OFFSET 0x3 #define PROCESS_ID_OFFSET 0x4 #define EXIT_TIME_OFFSET 0x5
#define OBJECT_HEADER_SIZE 0x018 #define OBJECT_TYPE_OFFSET 0x008 //////////////////////////
#define PDE_INVALID 2 #define PTE_INVALID 1 #define VALID 0
Processinfo* pProcessPtr = NULL; int nProcessCount = 0;
ULONG pebAddress; //PEB地址的前半部分
PEPROCESS pSystem; //system进程
ULONG pObjectTypeProcess; //进程对象类型
ULONG VALIDpage(ULONG addr) ; //该函数直接复制自 Ring0下搜索内存枚举隐藏进程
BOOLEAN IsaRealProcess(ULONG i); //该函数复制自 Ring0下搜索内存枚举隐藏进程
VOID WorkThread(IN PVOID pContext); //ULONG GetPebAddress(); //得到PEB地址前半部分
VOID EnumProcess(); //枚举进程
VOID ShowProcess(ULONG pEProcess); //显示结果
DWORD GetPlantformDependentInfo(DWORD eprocessflag); #define SYSNAME "System" ULONG ProcessNameOffset = 0; //进程名偏移量
ULONG GetProcessNameOffset(); BOOLEAN GetProcess(PCHAR Name);
//void EnumProcess2();
WCHAR gDeviceName[]=L"\\Device\\safepsenum"; WCHAR gDosDeviceName[]=L"\\??\\safepsenum";
NTSTATUS SafePsEnumCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); NTSTATUS SafePsEnumClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
NTSTATUS MyDeviceControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
/////////////////////////////////////////////////////////
VOID OnUnload(IN PDRIVER_OBJECT DriverObject) { NTSTATUS status; UNICODE_STRING DosDeviceName; RtlInitUnicodeString(&DosDeviceName,gDosDeviceName); if(DriverObject->DeviceObject) IoDeleteDevice(DriverObject->DeviceObject); status = IoDeleteSymbolicLink(&DosDeviceName); if(status) DbgPrint("IoDeleteSymbolicLink Return %0x\n",status);
if (pProcessPtr) { ExFreePool(pProcessPtr); } }
/////////////////////////////////////////////////////////
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) { HANDLE hThread; UNICODE_STRING DeviceName; UNICODE_STRING DosDeviceName; PDEVICE_OBJECT pDeviceObject=NULL; NTSTATUS Status;
pSystem = PsGetCurrentProcess(); // pebAddress = GetPebAddress();
pebAddress = 0x7FFD0000; //取了一个通用的低位地址
ProcessNameOffset = GetProcessNameOffset();
pObjectTypeProcess = *(PULONG)((ULONG)pSystem - OBJECT_HEADER_SIZE +OBJECT_TYPE_OFFSET);
DbgPrint("type: %d \n", pObjectTypeProcess);
DriverObject -> DriverUnload = OnUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = SafePsEnumCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = SafePsEnumClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyDeviceControl;
RtlInitUnicodeString(&DeviceName,gDeviceName); RtlInitUnicodeString(&DosDeviceName,gDosDeviceName); IoCreateDevice(DriverObject,0,&DeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&pDeviceObject); pDeviceObject->Flags|=DO_BUFFERED_IO; Status = IoCreateSymbolicLink(&DosDeviceName,&DeviceName); if(Status) DbgPrint("IoCreateSymbolicLink Return %0x\n",Status);
nProcessCount = 0; // 测试固定获取最大为1024
pProcessPtr = ExAllocatePoolWithTag(NonPagedPool, 1024*sizeof(Processinfo), 'HpcM');
return STATUS_SUCCESS; }
/////////////////////////////////////////////////////////
NTSTATUS SafePsEnumCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp,IO_NO_INCREMENT); return STATUS_SUCCESS; }
/////////////////////////////////////////////////////////
NTSTATUS SafePsEnumClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp,IO_NO_INCREMENT); return STATUS_SUCCESS; }
/////////////////////////////////////////////////////////
/* ULONG GetPebAddress() { ULONG Address; PEPROCESS pEProcess;
//由于system进程的peb总是零 我们只有到其他进程去找了 pEProcess = (PEPROCESS)((ULONG)((PLIST_ENTRY)((ULONG)pSystem + PROCESS_LINK_OFFSET))->Flink - PROCESS_LINK_OFFSET); Address = *(PULONG)((ULONG)pEProcess + PEB_OFFSET);
return (Address & 0xFFFF0000); } */ ///////////////////////////////////////////////////////
VOID EnumProcess() { ULONG uSystemAddress = (ULONG)pSystem; ULONG i; ULONG Address; ULONG ret;
nProcessCount = 0;
for(i = 0x80000000; i < uSystemAddress; i += 4) {//system进程的EPROCESS地址就是最大值了
ret = VALIDpage(i);
if (ret == VALID) { Address = *(PULONG)i; if (( Address & 0xFFFF0000) == 0x7FFD0000) {//每个进程的PEB地址都是在差不多的地方,地址前半部分是相同的
if(IsaRealProcess(i)) { ShowProcess(i - GetPlantformDependentInfo(PEB_OFFSET));
i += GetPlantformDependentInfo(EPROCESS_SIZE); } } } else if(ret == PTE_INVALID) { i -=4; i += 0x1000;//4k
} else {
i-=4; i+= 0x400000;//4mb
} }
ShowProcess(uSystemAddress);//system的PEB总是零 上面的方法是枚举不到的 不过我们用PsGetCurrentProcess就能得到了
}
/////////////////////////////////////////////////////////
VOID ShowProcess(ULONG pEProcess) { PLARGE_INTEGER ExitTime; ULONG PID; PUCHAR pFileName;
ExitTime = (PLARGE_INTEGER)(pEProcess + GetPlantformDependentInfo(EXIT_TIME_OFFSET));
if(ExitTime->QuadPart != 0) //已经结束的进程的ExitTime为非零
return ;
PID = *(PULONG)(pEProcess + GetPlantformDependentInfo(PROCESS_ID_OFFSET)); pFileName = (PUCHAR)(pEProcess + GetPlantformDependentInfo(FILE_NAME_OFFSET));
pProcessPtr[nProcessCount].pEProcess = pEProcess; pProcessPtr[nProcessCount].PId = PID; strcpy(pProcessPtr[nProcessCount].Name, pFileName);
nProcessCount++; }
/////////////////////////////////////////////////////////////
ULONG VALIDpage(ULONG addr) { ULONG pte; ULONG pde;
pde = 0xc0300000 + (addr>>22)*4; if((*(PULONG)pde & 0x1) != 0){ //large page
if((*(PULONG)pde & 0x80) != 0){ return VALID; } pte = 0xc0000000 + (addr>>12)*4; if((*(PULONG)pte & 0x1) != 0){ return VALID; }else{ return PTE_INVALID; } } return PDE_INVALID; }
////////////////////////////////////////////////////////////////
BOOLEAN IsaRealProcess(ULONG i) { NTSTATUS STATUS; PUNICODE_STRING pUnicode; UNICODE_STRING Process; ULONG pObjectType; ULONG ObjectTypeAddress;
if (VALIDpage(i- GetPlantformDependentInfo(PEB_OFFSET)) != VALID){ return FALSE; }
ObjectTypeAddress = i - GetPlantformDependentInfo(PEB_OFFSET) - OBJECT_HEADER_SIZE + OBJECT_TYPE_OFFSET ;
if (VALIDpage(ObjectTypeAddress) == VALID){ pObjectType = *(PULONG)ObjectTypeAddress; }else{ return FALSE; }
if (pObjectTypeProcess == pObjectType){ //确定ObjectType是Process类型
return TRUE; } return FALSE; } ////////////////////////////////////////////////////////////////////
#define DWORD unsigned long
NTSTATUS MyDeviceControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) {
PIO_STACK_LOCATION io_stack; NTSTATUS status;
Irp->IoStatus.Information = 0; io_stack = IoGetCurrentIrpStackLocation(Irp);
if (io_stack->MajorFunction==IRP_MJ_DEVICE_CONTROL) { switch (io_stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_GETPROCESSPTR: { EnumProcess(); // EnumProcess2();
RtlCopyMemory((unsigned char*)Irp->UserBuffer, (unsigned char*)&nProcessCount, sizeof(DWORD)); RtlCopyMemory((unsigned char*)Irp->UserBuffer+sizeof(DWORD), (unsigned char*)pProcessPtr, nProcessCount*sizeof(Processinfo)); Irp->IoStatus.Information = nProcessCount*sizeof(Processinfo)+sizeof(DWORD); } } } Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; }
//----------------------------------------------------------------------
//
// GetProcessNameOffset
//
// In an effort to remain version-independent, rather than using a
// hard-coded into the KPEB (Kernel Process Environment Block), we
// scan the KPEB looking for the name, which should match that
// of the GUI process
//
//----------------------------------------------------------------------
ULONG GetProcessNameOffset() { PEPROCESS curproc; int i; DbgPrint(("GetProcessNameOffset\n")); curproc = PsGetCurrentProcess();
//
// Scan for 12KB, hopping the KPEB never grows that big!
//
for( i = 0; i < 3*PAGE_SIZE; i++ ) {
if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) {
DbgPrint("%d\n", i); return i; } } //
// Name not found - oh, well
//
DbgPrint("0\n"); return 0; }
//----------------------------------------------------------------------
//
// GetProcess
//
// Uses undocumented data structure offsets to obtain the name of the
// currently executing process.
//
//----------------------------------------------------------------------
BOOLEAN GetProcess( PCHAR Name ) { PEPROCESS curproc; char *nameptr; ULONG i;
//
// We only try and get the name if we located the name offset
//
if( ProcessNameOffset ) {
curproc = PsGetCurrentProcess(); nameptr = (PCHAR) curproc + ProcessNameOffset; strncpy( Name, nameptr, 16 ); return TRUE; } else { strcpy( Name, "???"); return FALSE; } }
//2000平台的我没环境所以没定义,请你自己找吧
DWORD GetPlantformDependentInfo(DWORD eprocessflag) { DWORD current_build; DWORD ans = 0;
PsGetVersion(NULL, NULL, ¤t_build, NULL);
switch(eprocessflag){ case EPROCESS_SIZE: if (current_build == 2195) //2000
{ // ans = 0xxx;
} if (current_build == 2600) //XP
{ ans = 0x25C;
} if (current_build == 3790) //2003
{ ans = 0x270; } break; case PEB_OFFSET: if (current_build == 2195) //2000
{
ans = 0xxxx; } if (current_build == 2600) //XP
{ ans = 0x1b0;
} if (current_build == 3790) //2003
{ ans = 0x1a0; } break; case FILE_NAME_OFFSET: if (current_build == 2195) //2000
{
ans = 0xxxx; } if (current_build == 2600) //XP
{ ans = 0x174;
} if (current_build == 3790) //2003
{ ans = 0x164; } break; case PROCESS_LINK_OFFSET: if (current_build == 2195) //2000
{
ans = 0xxxx; } if (current_build == 2600) //XP
{ ans = 0x088;
} if (current_build == 3790) //2003
{ ans = 0x098; } break; case PROCESS_ID_OFFSET: if (current_build == 2195) //2000
{
ans = 0xxxx; } if (current_build == 2600) //XP
{ ans = 0x084;
} if (current_build == 3790) //2003
{ ans = 0x094; } break; case EXIT_TIME_OFFSET: if (current_build == 2195) //2000
{
ans = 0xxxxx; } if (current_build == 2600) //XP
{ ans = 0x078;
} if (current_build == 3790) //2003
{ ans = 0x088; } break; default: break; } return ans; }
|