• 驱动开发:内核监控进程与线程创建


    监控进程的启动与退出可以使用 PsSetCreateProcessNotifyRoutineEx 来创建回调,当新进程产生时,回调函数会被率先执行,然后执行我们自己的MyCreateProcessNotifyEx函数,并在内部进行打印输出。

    #include <ntddk.h>
    
    NTKERNELAPI PCHAR PsGetProcessImageFileName(PEPROCESS Process);
    NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process);
    
    PCHAR GetProcessNameByProcessId(HANDLE ProcessId)
    {
    	NTSTATUS st = STATUS_UNSUCCESSFUL;
    	PEPROCESS ProcessObj = NULL;
    	PCHAR string = NULL;
    	st = PsLookupProcessByProcessId(ProcessId, &ProcessObj);
    	if (NT_SUCCESS(st))
    	{
    		string = PsGetProcessImageFileName(ProcessObj);
    		ObfDereferenceObject(ProcessObj);
    	}
    	return string;
    }
    
    VOID MyCreateProcessNotifyEx(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo)
    {
    	char ProcName[16] = { 0 };
    	if (CreateInfo != NULL)
    	{
    		strcpy(ProcName, PsGetProcessImageFileName(Process));
    		DbgPrint("父进程ID: %ld  --->父进程名: %s --->进程名: %s---->进程路径:%wZ", CreateInfo->ParentProcessId,
    			GetProcessNameByProcessId(CreateInfo->ParentProcessId),
    			PsGetProcessImageFileName(Process),CreateInfo->ImageFileName);
    	}
    	else
    	{
    		strcpy(ProcName, PsGetProcessImageFileName(Process));
    		DbgPrint("进程[ %s ] 离开了,程序被关闭了",ProcName);
    	}
    }
    
    VOID UnDriver(PDRIVER_OBJECT driver)
    {
    	PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)MyCreateProcessNotifyEx, TRUE);
    }
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
    {
    	NTSTATUS status;
    	status = PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)MyCreateProcessNotifyEx, FALSE);
    	Driver->DriverUnload = UnDriver;
    	return STATUS_SUCCESS;
    }
    

    在上方代码基础上进行一定的改进,思路:通过PsGetProcessImageFileName即将PID转换为进程名,然后通过_stricmp对比,如果发现是calc.exe进程则拒绝执行,禁止特定服务的运行,实现代码如下:

    #include <ntddk.h>
    
    NTKERNELAPI PCHAR PsGetProcessImageFileName(PEPROCESS Process);
    NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process);
    
    PCHAR GetProcessNameByProcessId(HANDLE ProcessId)
    {
    	NTSTATUS st = STATUS_UNSUCCESSFUL;
    	PEPROCESS ProcessObj = NULL;
    	PCHAR string = NULL;
    	st = PsLookupProcessByProcessId(ProcessId, &ProcessObj);
    	if (NT_SUCCESS(st))
    	{
    		string = PsGetProcessImageFileName(ProcessObj);
    		ObfDereferenceObject(ProcessObj);
    	}
    	return string;
    }
    
    VOID MyCreateProcessNotifyEx(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo)
    {
    	char ProcName[16] = { 0 };
    	if (CreateInfo != NULL)
    	{
    		strcpy(ProcName, PsGetProcessImageFileName(Process));
    		if (!_stricmp(ProcName, "calc.exe"))
    		{
    			CreateInfo->CreationStatus = STATUS_UNSUCCESSFUL;
    		}
    	}
    }
    
    VOID UnDriver(PDRIVER_OBJECT driver)
    {
    	PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)MyCreateProcessNotifyEx, TRUE);
    	DbgPrint(("驱动卸载成功"));
    }
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
    {
    	NTSTATUS status;
    	status = PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)MyCreateProcessNotifyEx, FALSE);
    	Driver->DriverUnload = UnDriver;
    	DbgPrint("驱动加载成功!");
    	return STATUS_SUCCESS;
    }
    

    将上方代码编译,当我们加载驱动程序以后,再次打开C:\Windows\System32\calc.exe 计算器进程则提示无法打开,我们的驱动已经成功的拦截了本次的请求。

    而检测线程操作与检测进程差不多,检测线程需要调用PsSetCreateThreadNotifyRoutine 创建回调函数,然后就可以检测线程的创建了,具体代码如下:

    #include <ntddk.h>
    
    NTKERNELAPI PCHAR PsGetProcessImageFileName(PEPROCESS Process);
    NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process);
    
    VOID MyCreateThreadNotify(HANDLE  ProcessId, HANDLE  ThreadId, BOOLEAN  Create)
    {
    	PEPROCESS eprocess = NULL;
    	PsLookupProcessByProcessId(ProcessId, &eprocess);                // 通过此函数拿到程序的EPROCESS结构
    	if (Create)
    		DbgPrint("线程TID: %1d --> 所属进程名: %s --> 进程PID: %1d \n", ThreadId, PsGetProcessImageFileName(eprocess), PsGetProcessId(eprocess));
    	else
    		DbgPrint("%s 线程已退出...", ThreadId);
    }
    VOID UnDriver(PDRIVER_OBJECT driver)
    {
    	PsRemoveCreateThreadNotifyRoutine(MyCreateThreadNotify);
    	DbgPrint(("驱动卸载成功"));
    }
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
    {
    	NTSTATUS status;
    	status = PsSetCreateThreadNotifyRoutine(MyCreateThreadNotify);
    	DbgPrint("PsSetCreateThreadNotifyRoutine: %x", status);
    	Driver->DriverUnload = UnDriver;
    	return STATUS_SUCCESS;
    }
    

  • 相关阅读:
    最大流基础
    转一篇写期望的日志
    poj3267The Cow Lexicon(dp)
    poj3026Borg Maze(bfs+MST)
    poj2226Muddy Fields(二分图的最小点覆盖)
    poj1035Spell checker(字符串模拟)
    poj1422Air Raid(最小路径覆盖)
    poj3020Antenna Placement(最小路径覆盖)
    [JSOI2009]火星藏宝图
    [SHOI2007]书柜的尺寸
  • 原文地址:https://www.cnblogs.com/LyShark/p/14735438.html
Copyright © 2020-2023  润新知