首页
社区
课程
招聘
[原创]Ps回调通知例程、Dpc定时器、内核线程使用方法.
发表于: 2013-3-31 00:09 5308

[原创]Ps回调通知例程、Dpc定时器、内核线程使用方法.

2013-3-31 00:09
5308
好久没发代码了,发个以前写的东西,代码是照葫芦画瓢来的,共同学习,共同进步,欢迎拍砖.
#ifndef _SAFENOTIFYROUTINE_H
#define _SAFENOTIFYROUTINE_H
/************************************************************************/
/************************************************************************/
#include <ntifs.h>
#include <wdm.h>
/************************************************************************/
/************************************************************************/
extern POBJECT_TYPE *PsProcessType;
typedef struct _DEVICE_TIMER 
{
	PVOID		thread_pointer;
	BOOLEAN         terminate_thread;    
	KEVENT          request_event;
	KTIMER          kTimer;
	KDPC            KiTimerExpireDpc;    
} DEVICE_TIMER, *PDEVICE_TIMER;
typedef class SafeNotifyRoutine* PSafeNotifyRoutine;
/************************************************************************/
/************************************************************************/
#endif

#ifndef SAFENOTIFYROUTINE_H
#define SAFENOTIFYROUTINE_H
/************************************************************************/
/************************************************************************/
#include "_SafeNotifyRoutine.h"
/************************************************************************/
/************************************************************************/
class SafeNotifyRoutine
{
public:
	BOOLEAN InitializeCallBackNotify();
	BOOLEAN CleanupCallBackNotify();
	BOOLEAN InitializeTimerNotify(ULONG Millisecond);
	BOOLEAN CleanupTimerNotify();
private:
	VOID _ZeroMemoryMember();
	static VOID LoadImageNotifyCallBack(PUNICODE_STRING FullImageName,HANDLE ProcessId,PIMAGE_INFO ImageInfo);
	static VOID CreateThreadNotifyCallBack(HANDLE ProcessId,HANDLE ThreadId,BOOLEAN Create);
	static VOID CreateProcessNotifyCallBack(HANDLE ParentId,HANDLE ProcessId,BOOLEAN Create);
	static VOID DpcTimerNotifyCallBack(struct _KDPC* Dpc,PVOID DeferredContext,PVOID SystemArgument1,PVOID SystemArgument2);
	static VOID ThreadNotifyCallBack(PVOID Context);
	BOOLEAN GetFullPathByProcessId(ULONG ProcessId, PUNICODE_STRING FullImageName);
	BOOLEAN LdrLoadDllByProcessId(ULONG ProcessId,char* szDllPath);
private:
	BOOLEAN IsLoadImage;
	BOOLEAN IsCreateProcess;
	BOOLEAN IsCreateThread;
	PEPROCESS _pEprocess;
public:
	DEVICE_TIMER _Timer;
};
#endif

/************************************************************************/
/************************************************************************/
#include "SafeNotifyRoutine.h"
/************************************************************************/
/************************************************************************/
PSafeNotifyRoutine g_pThis = NULL;
/************************************************************************/
/************************************************************************/
BOOLEAN SafeNotifyRoutine::InitializeCallBackNotify()
{
    this->_ZeroMemoryMember();
    if(!NT_SUCCESS(PsSetLoadImageNotifyRoutine(SafeNotifyRoutine::LoadImageNotifyCallBack)))
        return FALSE;
    else
        this->IsLoadImage = TRUE;
    if(!NT_SUCCESS(PsSetCreateThreadNotifyRoutine(SafeNotifyRoutine::CreateThreadNotifyCallBack)))
        return FALSE;
    else
        this->IsCreateThread = TRUE;
    if(!NT_SUCCESS(PsSetCreateProcessNotifyRoutine(SafeNotifyRoutine::CreateProcessNotifyCallBack,FALSE)))
        return FALSE;
    else
        this->IsCreateProcess = TRUE;
    g_pThis = this;
    return TRUE;
}
/************************************************************************/
/************************************************************************/
BOOLEAN SafeNotifyRoutine::InitializeTimerNotify(ULONG Millisecond)
{
    __try
    {
        LARGE_INTEGER duetime = {0};
        HANDLE ThreadHandle;
        KeInitializeEvent(&this->_Timer.request_event,NotificationEvent,FALSE);
        KeInitializeTimerEx(&this->_Timer.kTimer, NotificationTimer);
        KeInitializeDpc(&this->_Timer.KiTimerExpireDpc,SafeNotifyRoutine::DpcTimerNotifyCallBack,NULL);
        KeSetTimerEx(&this->_Timer.kTimer, duetime,Millisecond,&this->_Timer.KiTimerExpireDpc);
        this->_Timer.terminate_thread = FALSE;
        if(!NT_SUCCESS(PsCreateSystemThread(&ThreadHandle,0,NULL,NULL,NULL,SafeNotifyRoutine::ThreadNotifyCallBack,NULL)))
        {
            KdPrint(("PsCreateSystemThread Fail.\n"));
            return FALSE;
        }
        if(!NT_SUCCESS(ObReferenceObjectByHandle(ThreadHandle,THREAD_ALL_ACCESS,NULL,KernelMode,&this->_Timer.thread_pointer,NULL)))
        {
            KdPrint(("ObReferenceObjectByHandle Fail.\n"));
            ZwClose(ThreadHandle);
            this->_Timer.terminate_thread = TRUE;
            KeSetEvent(&this->_Timer.request_event,(KPRIORITY)0,FALSE);
            return FALSE;
        }
        else
        {
            ZwClose(ThreadHandle);
        }
        return TRUE;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        KdPrint(("InitializeTimerNotify Except Fail.\n"));
        return FALSE;
    }
}
/************************************************************************/
/************************************************************************/
BOOLEAN SafeNotifyRoutine::CleanupTimerNotify()
{
    __try
    {
        KeCancelTimer(&g_pThis->_Timer.kTimer);
        g_pThis->_Timer.terminate_thread = TRUE;
        KeSetEvent(&g_pThis->_Timer.request_event,(KPRIORITY)0,FALSE);
        KeWaitForSingleObject(g_pThis->_Timer.thread_pointer,Executive,KernelMode,FALSE,NULL);
        ObDereferenceObject(g_pThis->_Timer.thread_pointer);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        KdPrint(("CleanupTimerNotify Except Fail.\n"));
        return FALSE;
    }
    return TRUE;
}
/************************************************************************/
/************************************************************************/
BOOLEAN SafeNotifyRoutine::CleanupCallBackNotify()
{
    if(this->IsLoadImage)
        PsRemoveLoadImageNotifyRoutine(SafeNotifyRoutine::LoadImageNotifyCallBack);
    if(this->IsCreateThread)
        PsRemoveCreateThreadNotifyRoutine(SafeNotifyRoutine::CreateThreadNotifyCallBack);
    if(this->IsCreateProcess)
        PsSetCreateProcessNotifyRoutine(SafeNotifyRoutine::CreateProcessNotifyCallBack,TRUE);
    this->_ZeroMemoryMember();
    return TRUE;
}
/************************************************************************/
/************************************************************************/
VOID SafeNotifyRoutine::_ZeroMemoryMember()
{
    this->IsLoadImage = FALSE;
    this->IsCreateThread = FALSE;
    this->IsCreateProcess = FALSE;
}
/************************************************************************/
/************************************************************************/
VOID SafeNotifyRoutine::LoadImageNotifyCallBack(PUNICODE_STRING FullImageName,HANDLE ProcessId,PIMAGE_INFO ImageInfo)
{
    if(KeGetCurrentIrql()!=PASSIVE_LEVEL)
        return;
    DbgPrint("ImageName:%wZ ProcessId:%d\n",FullImageName,(ULONG)ProcessId);
	g_pThis->LdrLoadDllByProcessId((ULONG)ProcessId,NULL);
}
/************************************************************************/
/************************************************************************/
VOID SafeNotifyRoutine::CreateThreadNotifyCallBack(HANDLE ProcessId,HANDLE ThreadId,BOOLEAN Create)
{
    if(KeGetCurrentIrql()==PASSIVE_LEVEL&&Create)
    {
        DbgPrint("ProcessId:%d ThreadId:%d\n",(ULONG)ProcessId,(ULONG)ThreadId);
    }
}
/************************************************************************/
/************************************************************************/
VOID SafeNotifyRoutine::CreateProcessNotifyCallBack(HANDLE ParentId,HANDLE ProcessId,BOOLEAN Create)
{
    if(KeGetCurrentIrql()==PASSIVE_LEVEL&&Create)
    {
        UNICODE_STRING FullImageName = {512,1024,(PWCH)ExAllocatePoolWithTag(PagedPool,1024,'Safe')};
        g_pThis->GetFullPathByProcessId((ULONG)ProcessId,&FullImageName);
        DbgPrint("ParentId:%d ProcessId:%d FullImageName:%wZ\n",(ULONG)ParentId,(ULONG)ProcessId,FullImageName);
        ExFreePoolWithTag((PVOID)FullImageName.Buffer,'Safe');
    }
}
/************************************************************************/
/************************************************************************/
VOID SafeNotifyRoutine::DpcTimerNotifyCallBack(struct _KDPC* Dpc,PVOID DeferredContext,PVOID SystemArgument1,PVOID SystemArgument2)
{
    KdPrint(("haha dpc function work\n"));
    KeSetEvent(&g_pThis->_Timer.request_event,(KPRIORITY)0,FALSE);
}
/************************************************************************/
/************************************************************************/
VOID SafeNotifyRoutine::ThreadNotifyCallBack(PVOID Context)
{
    KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
    for(;;)
    {
        do
        {
            KdPrint(("thread work ok !!\n"));
            goto failselabel;
        }
        while(TRUE);
failselabel:
        KeWaitForSingleObject(&g_pThis->_Timer.request_event,Executive,KernelMode,FALSE,NULL);
        KeResetEvent(&g_pThis->_Timer.request_event);
        if(g_pThis->_Timer.terminate_thread)
            PsTerminateSystemThread(STATUS_SUCCESS);
    }
}
/************************************************************************/
/************************************************************************/
BOOLEAN SafeNotifyRoutine::GetFullPathByProcessId(ULONG ProcessId, PUNICODE_STRING FullImageName)
{
    HANDLE ProcessHandle = NULL;
    ULONG NumberOfBytes = 8;
    if(!NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)ProcessId,&this->_pEprocess)))
    {
        KdPrint(("PsLookupProcessByProcessId Fail\n"));
        return FALSE;
    }
    if(!NT_SUCCESS(ObOpenObjectByPointer(this->_pEprocess,OBJ_KERNEL_HANDLE ,0,GENERIC_READ,*PsProcessType,0,&ProcessHandle)))
    {
        KdPrint(("ObOpenObjectByPointer Fail\n"));
        return FALSE;
    }
    if(!NT_SUCCESS(NtQueryInformationProcess(ProcessHandle,ProcessImageFileName,0,0,&NumberOfBytes)))
    {
        KdPrint(("NtQueryInformationProcess Fail\n"));
        return FALSE;
    }
    if(FullImageName->MaximumLength<NumberOfBytes-sizeof(UNICODE_STRING))
    {
        KdPrint(("FullImageName->MaximumLength Buffer Length Too Small\n"));
        return FALSE;
    }
    PUNICODE_STRING TmpImageName= (PUNICODE_STRING)ExAllocatePoolWithTag(PagedPool,NumberOfBytes,'Safe');
    if(TmpImageName==NULL)
    {
        KdPrint(("ExAllocatePoolWithTag Fail\n"));
        return FALSE;
    }
    if(NT_SUCCESS(NtQueryInformationProcess(ProcessHandle,ProcessImageFileName,TmpImageName,NumberOfBytes,&NumberOfBytes)))
    {
        KdPrint(("FullImageName %wZ\n",TmpImageName->Buffer));
        wcsncpy(FullImageName->Buffer,TmpImageName->Buffer,TmpImageName->Length);
    }
    ExFreePoolWithTag((PVOID)TmpImageName,'Safe');
    return (NT_SUCCESS(ZwClose(ProcessHandle)));
}
/************************************************************************/
/************************************************************************/
BOOLEAN SafeNotifyRoutine::LdrLoadDllByProcessId(ULONG ProcessId,char* szDllPath)
{
	HANDLE ProcessHandle = NULL;
	PVOID pMemSpace = NULL;
	if(!NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)ProcessId,&this->_pEprocess)))
	{
		KdPrint(("PsLookupProcessByProcessId Fail\n"));
		return FALSE;
	}
	ULONG size = 2000;
	if(!NT_SUCCESS(ObOpenObjectByPointer(this->_pEprocess,OBJ_KERNEL_HANDLE,NULL,PROCESS_ALL_ACCESS,NULL,KernelMode,&ProcessHandle)))
	{
		KdPrint(("ObOpenObjectByPointer Fail\n"));
		return FALSE;
	}
	if(!NT_SUCCESS(NtAllocateVirtualMemory(ProcessHandle,&pMemSpace,0,&size,MEM_COMMIT,PAGE_EXECUTE_READWRITE)))
	{
		KdPrint(("NtAllocateVirtualMemory Fail\n"));
		return FALSE;
	}
	if(ProcessHandle!=NULL)
		ObfDereferenceObject(ProcessHandle);
	DbgPrint("MEM SPACE ADDR:%x\n",(ULONG)pMemSpace);
}

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

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
失败后, 先前打开的句柄 不释放了吗。。。
2013-3-31 00:36
0
雪    币: 114
活跃值: (180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
韬哥早啊
2013-3-31 00:40
0
雪    币: 216
活跃值: (144)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
4
少年,继续努力!!
2013-4-2 00:14
0
游客
登录 | 注册 方可回帖
返回
//