我是靠谱客的博主 笨笨饼干,最近开发中收集的这篇文章主要介绍KdDisableDebugger()反调试,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

NTSTATUS KdDisableDebugger();
剥离内核调试器成功,返回 STATUS_SUCCESS
如果并没有内核调试器,返回STATUS_DEBUGGER_INACTIVE
如果内核调试器处于阻塞状态返回STATUS_ACCESS_DENIED
KdDisableDebugger函数会判断一个全局变量,当系统不是在调试下启动时,该值为1,在调试下启动时该值被置0,且该值只在操作系统启动时被初始化了一次(推测),当该值为0时,KdDisableDebugger会调用相关函数使内核调试器与操作系统分离,该全局变量仅作为一个标识
反调试

#include <ntddk.h>
#pragma warning(disable:4100)
#define DELAY_ONE_MICROSECOND 	(-10)
#define DELAY_ONE_MILLISECOND	(DELAY_ONE_MICROSECOND*1000)
BOOLEAN g_bExit = FALSE;
PVOID pThreadObj = NULL;
VOID MySleep(LONG msec);
VOID CheckDebug(PVOID pContext);
NTSTATUS CreateThread();
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{

    KdPrint(("驱动正在被关闭n"));
    g_bExit = TRUE;
    if (pThreadObj!=NULL)
    {
        //等待对象
        KeWaitForSingleObject(pThreadObj,
            Executive,
            KernelMode,
            FALSE,
            NULL);
        //因为使用了 ObRefrenceObjceByHandle.所以引用对象+1了.现在需要引用对象-1
        ObDereferenceObject(pThreadObj);
    }
    // 卸载驱动
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path)
{
    DbgPrint("驱动正在被启动n");
    NTSTATUS ntStatus = 0;
    ntStatus = CreateThread();
    //指定卸载函数
    pDriver->DriverUnload = DriverUnload;
    return ntStatus;
}
//==================================================================
//函数名: MySleep
//功能:睡眠函数,类似于三环的sleep()  
//输入参数1:msec,睡眠的时间,单位秒
//返回值:null
//==================================================================
VOID MySleep(LONG msec)
{
    LARGE_INTEGER my_interval;
    my_interval.QuadPart = DELAY_ONE_MILLISECOND;
    my_interval.QuadPart *= msec;
    KeDelayExecutionThread(KernelMode, 0, &my_interval);
}
VOID CheckDebug(PVOID pContext)
{
    while (1)
    {
        DbgPrint("执行KdDisableDebugger()...n");
        KdDisableDebugger();
        MySleep(2000);
        if (g_bExit == TRUE)
            break;
    }
    PsTerminateSystemThread(STATUS_SUCCESS);
}
NTSTATUS CreateThread()
{
    //创建线程
    HANDLE hThread;
    NTSTATUS ntStatus;
    ntStatus = PsCreateSystemThread(&hThread,
        THREAD_ALL_ACCESS,
        NULL,
        (HANDLE)0,
        NULL,
        CheckDebug,    //你创建函数的回调地址
        NULL);          //给你创建函数传递的参数值
    //等待线程创建完毕.
    if (!NT_SUCCESS(ntStatus))
        return ntStatus;
    //判断IRQL 降低权限
    if (KeGetCurrentIrql() != PASSIVE_LEVEL)
        ntStatus = KfRaiseIrql(PASSIVE_LEVEL);

    ntStatus = ObReferenceObjectByHandle(hThread,
        THREAD_ALL_ACCESS,
        NULL,
        KernelMode,
        &pThreadObj,
        NULL);
    if (!NT_SUCCESS(ntStatus))
        return ntStatus;
    //关闭线程句柄
    ZwClose(hThread);
    return ntStatus;
}

反反调试
将此全局变量重新置为1
用到的相关结构体

#ifdef _WIN64
typedef struct _LDR_DATA
{
	LIST_ENTRY listEntry;
	ULONG64 __Undefined1;
	ULONG64 __Undefined2;
	ULONG64 __Undefined3;
	ULONG64 NonPagedDebugInfo;
	ULONG64 DllBase;
	ULONG64 EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING path;
	UNICODE_STRING name;
	ULONG   Flags;
}LDR_DATA, * PLDR_DATA;
#else
typedef struct _LDR_DATA
{
	LIST_ENTRY listEntry;
	ULONG unknown1;
	ULONG unknown2;
	ULONG unknown3;
	ULONG unknown4;
	ULONG unknown5;
	ULONG unknown6;
	ULONG unknown7;
	UNICODE_STRING path;
	UNICODE_STRING name;
	ULONG   Flags;
}LDR_DATA, * PLDR_DATA;
#endif

用到的相关函数

/*
* --------------------------------函数声明
*/
UINT64 SearchFeature(UINT64 nAddr, char* pFeature, int nLeng, UINT64 size);
UINT64 GetDriverAddressByFeature(LPCWSTR DriverName, PDRIVER_OBJECT  pDriverObject, char* pFeature, int nLeng);
/*
* --------------------------------函数声明
*/

详情

//==================================================================
//函数名: GetDriverAddressByFeature
//功能:搜索指定内核模块的特征码,并获取该特征码的位置
//输入参数1:DriverName,要搜索的驱动模块名
//输入参数2:pDriverObject,自己的驱动对象
//输入参数3:pFeature,特征码
//输入参数4:nLeng,特征码的长度
//返回值:UINT64,特征码的地址
//==================================================================
UINT64 GetDriverAddressByFeature(LPCWSTR DriverName, PDRIVER_OBJECT  pDriverObject, char* pFeature, int nLeng)
{
	PLDR_DATA CurrentDllInfo = (PLDR_DATA)pDriverObject->DriverSection; 
	PLDR_DATA DllInfoTemp = CurrentDllInfo;
	UNICODE_STRING uniDriverName;
	UINT64 dllBase = 0;
	UINT64 dllSize = 0;
	RtlInitUnicodeString(&uniDriverName, DriverName);
	do
	{
		DllInfoTemp = (PLDR_DATA)(DllInfoTemp->listEntry.Flink);   //先查询下一个
		//wcscmp()会蓝屏,尽量使用内核提供的字符串函数
		if (RtlCompareUnicodeString(&uniDriverName,&DllInfoTemp->name,TRUE)==0)
		{
			DbgPrint("Driver Module Name=%wsn", DllInfoTemp->name.Buffer);
			DbgPrint("Driver Module Dllbase=%pn", DllInfoTemp->DllBase);
			dllBase = DllInfoTemp->DllBase;
			dllSize = DllInfoTemp->SizeOfImage;
		}
	} while (CurrentDllInfo != DllInfoTemp);    //遍历到当前驱动LDR_DATA_TABLE_ENTRY地址时,说明查询结束
	//没找到目标驱动模块
	if (dllBase == 0)
		return FALSE;
	return SearchFeature(dllBase, pFeature, nLeng, dllSize);
}
//==================================================================
//函数名: SearchFeature
//描述:内部函数
//==================================================================
UINT64 SearchFeature(UINT64 nAddr, char* pFeature, int nLeng, UINT64 size)
{
	char szStatus[256] = "";
	INT64 i = size;

	while (i--)
	{
		RtlMoveMemory(szStatus, (char*)nAddr, nLeng);

		if (RtlCompareMemory(pFeature, szStatus, nLeng) == nLeng)
		{
			return nAddr;
		}
		nAddr++;
	}

	return 0;
}

最后

以上就是笨笨饼干为你收集整理的KdDisableDebugger()反调试的全部内容,希望文章能够帮你解决KdDisableDebugger()反调试所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部