1. 编译
Pspeek.cpp
#include <ntddk.h>
#define DANIEL_LIST_PROCESS 0x8001
PDRIVER_OBJECT daniel_DriverObject;
PDEVICE_OBJECT daniel_DeviceObject;
NTSTATUS daniel_DispatchCreate(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION stackLocation;
PIO_SECURITY_CONTEXT securityContext;
stackLocation = IoGetCurrentIrpStackLocation(Irp);
securityContext = stackLocation->Parameters.Create.SecurityContext;
DbgPrint("###############\n");
DbgPrint("Daniel PsPeek daniel_DispatchCreate\n");
DbgPrint("###############\n");
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS KphDispatchDeviceControl(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
{
NTSTATUS status;
PIO_STACK_LOCATION stackLocation;
PVOID originalInput;
ULONG inputLength;
ULONG ioControlCode;
KPROCESSOR_MODE accessMode;
UCHAR capturedInput[16 * sizeof(ULONG_PTR)];
PVOID capturedInputPointer;
stackLocation = IoGetCurrentIrpStackLocation(Irp);
originalInput = stackLocation->Parameters.DeviceIoControl.Type3InputBuffer;
inputLength = stackLocation->Parameters.DeviceIoControl.InputBufferLength;
ioControlCode = stackLocation->Parameters.DeviceIoControl.IoControlCode;
accessMode = Irp->RequestorMode;
// Probe and capture the input buffer.
if (accessMode != KernelMode)
{
__try
{
ProbeForRead(originalInput, inputLength, sizeof(UCHAR));
memcpy(capturedInput, originalInput, inputLength);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
goto ControlEnd;
}
}
else
{
memcpy(capturedInput, originalInput, inputLength);
}
capturedInputPointer = capturedInput; // avoid casting below
switch (ioControlCode)
{
case DANIEL_LIST_PROCESS:
{
status = STATUS_SUCCESS;
}
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
ControlEnd:
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
VOID daniel_DriverUnload(
__in PDRIVER_OBJECT DriverObject
)
{
PAGED_CODE();
IoDeleteDevice(daniel_DeviceObject);
}
extern "C" NTSTATUS DriverEntry(
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
UNICODE_STRING deviceName;
PDEVICE_OBJECT deviceObject;
PAGED_CODE();
DbgPrint("###############\n");
DbgPrint("Daniel PsPeek DriverEntry\n");
DbgPrint("Current Pid: %d\n", PsGetCurrentProcessId());
DbgPrint("###############\n");
daniel_DriverObject = DriverObject;
// Create the device.
RtlInitUnicodeString(&deviceName, L"\\Device\\DanielPsPeekDriver");
status = IoCreateDevice(
DriverObject,
0,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObject
);
if (!NT_SUCCESS(status))
return status;
daniel_DeviceObject = deviceObject;
// Set up I/O.
DriverObject->MajorFunction[IRP_MJ_CREATE] = daniel_DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KphDispatchDeviceControl;
DriverObject->DriverUnload = daniel_DriverUnload;
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return status;
}
sources
TARGETNAME=Pspeek
TARGETPATH=obj
TARGETTYPE=DRIVER
SOURCES=Pspeek.cpp
mk.bat
set setenv_script=D:\WinDDK\7600.16385.1\bin\setenv.bat
set ddk_path=D:\WinDDK\7600.16385.1\
set config=chk
set platform=x86
set os=WXP
%setenv_script% %ddk_path% %config% %platform% %os% && H: && cd %cd% && build
2. 加载
ld.bat
sc stop Pspeek
sc delete Pspeek
copy /y "F:\pspeek.sys" "C:\WINDOWS\system32\pspeek.sys"
sc create Pspeek binPath= "C:\WINDOWS\system32\pspeek.sys" type= kernel start= auto error= ignore DisplayName= "Daniel Process Peek Driver"
sc start Pspeek
在Windows 7下,需要使用"管理员权限"才能执行上述脚本。
3. 枚举进程列表
void GatherProcessListByEPROCESS()
{
HANDLE pid = PsGetCurrentProcessId();
DbgPrint("Current Pid: %d\n", pid);
PEPROCESS eprocess;
PsLookupProcessByProcessId(pid, &eprocess);
DbgPrint("_EPROCESS: 0x%08x\n", eprocess);
_LIST_ENTRY active_process_node = {0,0};
memcpy(&active_process_node, (CHAR*)eprocess + 0x88, 8);
DbgPrint("Active Process List Node: [0x%08x, 0x%08x]\n", active_process_node.Blink, active_process_node.Flink);
DbgPrint("VirtualSize: 0x%08x \n", *(ULONG*)((CHAR*)eprocess + 0xb0));
}
上面代码与WinDbg的验证一致,因此Windows下获取内核相关的数据与Linux并无太大差别。
void PProcess(char* eprocess)
{
DbgPrint("%16s: 0x%08x\n", "_EPROCESS", eprocess);
DbgPrint("%16s: %s\n", "ImageName", eprocess + 0x174);
DbgPrint("\n");
}
void GatherProcessListByEPROCESS()
{
HANDLE pid = PsGetCurrentProcessId();
DbgPrint("Current Pid: %d\n", pid);
PEPROCESS eprocess;
PsLookupProcessByProcessId(pid, &eprocess);
_LIST_ENTRY active_process_node = {0,0};
memcpy(&active_process_node, (CHAR*)eprocess + 0x88, 8);
_LIST_ENTRY* head = active_process_node.Flink;
PProcess((char*)eprocess);
for (_LIST_ENTRY* cur=head;
cur->Flink != head;
cur = cur->Flink)
{
PProcess((char*)cur - 0x88);
}
}