游戏安全实验室-游戏逆向-游戏辅助开发

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2433|回复: 9

绕过Head Inline Hook

[复制链接]
匿名  发表于 2023-6-3 21:47:11 |阅读模式
```
#include <NTDDK.H>
#include "passinline.h"
#include "irql.h"

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp);
NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp);
VOID UnloadDriver(IN PDRIVER_OBJECT DriverObject );

typedef struct _KAPC_STATE
{
        LIST_ENTRY ApcListHead[2];
        PVOID Process;
        BOOLEAN KernelApcInProgress;
        BOOLEAN KernelApcPending;
        BOOLEAN UserApcPending;
}KAPC_STATE, *PKAPC_STATE;

typedef enum _KAPC_ENVIRONMENT
{
    OriginalApcEnvironment,
    AttachedApcEnvironment,
    CurrentApcEnvironment,
    InsertApcEnvironment
}KAPC_ENVIRONMENT;

NTKERNELAPI
VOID
KeInitializeApc (
    IN PRKAPC Apc,
    IN PKTHREAD Thread,
    IN KAPC_ENVIRONMENT Environment,
    IN PKKERNEL_ROUTINE KernelRoutine,
    IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
    IN PKNORMAL_ROUTINE NormalRoutine OPTIONAL,
    IN KPROCESSOR_MODE ApcMode,
    IN PVOID NormalContext
    );

NTKERNELAPI
VOID
KeTerminateThread(
        KPRIORITY Increment);
       
typedef BOOLEAN (__stdcall *KEINSERTQUEUEAPC)
(
        PKAPC Apc,
    PVOID SystemArgument1,
    PVOID SystemArgument2,
    KPRIORITY Increment
);
KEINSERTQUEUEAPC MsInsertQueueApc;

typedef VOID (__fastcall *KIINSERTQUEUEAPC)
(
        PKAPC Apc,
    KPRIORITY Increment
);
KIINSERTQUEUEAPC KiInsertQueueApc;

ULONG KillProc;
ULONG KiAddr;
BYTE KiInsertQueueApc_orig_code[20] = { 0x00 };

//常量声明:XP下KTHREAD结构的一些偏移
const ULONG ThreadListEntryOffset=0x22c;
const ULONG ThreadListHeadOffset=0x190;

//作用:得到导出函数地址
ULONG GetFunctionAddr(IN PCWSTR FunctionName)
{
    UNICODE_STRING UniCodeFunctionName;
    RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
    return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   
}

//得到KiInsertQueueApc的地址
ULONG GetKiInsertQueueApc()
{
        UCHAR *cPtr, *pOpcode;
        ULONG Length, CallCount=1, ETAddr=0;
        ULONG AddressOf_KeInsertQueueApc,AddressOf_KiInsertQueueApc=0;
        //Get KeInsertQueueApc Address
        AddressOf_KeInsertQueueApc=GetFunctionAddr(L"KeInsertQueueApc");
        //Get KiInsertQueueApc Address
        for (cPtr = (PUCHAR)AddressOf_KeInsertQueueApc; cPtr < (PUCHAR)AddressOf_KeInsertQueueApc + PAGE_SIZE; cPtr += Length)
        {
                Length = SizeOfCode(cPtr, &pOpcode);
                if (!Length) return ETAddr;       
                if (*pOpcode == 0xE8)
                {
                        CallCount++;
                        if (CallCount==3) //XP: The Third e8 is KiInsertQueueApc
                        {
                                AddressOf_KiInsertQueueApc=(*(PULONG)(pOpcode+1)+(ULONG)cPtr + 5);
                                DbgPrint("KiInsertQueueApc Address = %X",AddressOf_KiInsertQueueApc);
                                break;
                        }
                }
        }       
        ETAddr=AddressOf_KiInsertQueueApc;
        return ETAddr;
}

VOID XPRestoreKiInsertQueueApc()
{
    PUCHAR addr;
        ULONG uladdr;
    KIRQL oldIrql;
        uladdr = GetKiInsertQueueApc();
        if (uladdr!=0)
        {
                addr = (PUCHAR)uladdr;
                //获得KiInsertQueueApc的前12字节
                GetOldCode(uladdr,12,KiInsertQueueApc_orig_code);
                //判断得到了字节没有
                if( KiInsertQueueApc_orig_code[0]==0x8B && KiInsertQueueApc_orig_code[1]==0xFF )
                {
                        //禁止系统写保护,提升IRQL到DPC,然后恢复KiInsertQueueApc的Inline Hook
                        WPOFF();
                        oldIrql = KeRaiseIrqlToDpcLevel();
                        //恢复KeInsertQueueApc的前12字节
                        RtlCopyMemory ( (BYTE*)addr, KiInsertQueueApc_orig_code, 12 );
                        KeLowerIrql(oldIrql);
                        WPON();
                        DbgPrint("XP RestoreKiInsertQueueApc Success!\n");
                }
                else
                {
                        DbgPrint("XP RestoreKiInsertQueueApc Failed: Can not get KiInsertQueueApc bytes\n");
                }
        }
        else
        {
                DbgPrint("XP RestoreKiInsertQueueApc Failed: Can not get KiInsertQueueApc Address\n");
        }
}

//作用:内核APC例程
VOID ApcCallBack(PKAPC Apc,PKNORMAL_ROUTINE *NormalRoutine,PVOID *NormalContext,PVOID *SystemArgument1,PVOID *SystemArgument2)
{
        NTSTATUS st;
        ExFreePool(Apc);
        st=PsTerminateSystemThread(STATUS_SUCCESS);
        if(!NT_SUCCESS(st)) KeTerminateThread(0);
}

//作用:结束线程
NTSTATUS TerminateThread(IN PETHREAD Thread)
{
        NTSTATUS st = STATUS_UNSUCCESSFUL;
        ULONG Size = 0;
        ULONG i = 0;
        PKAPC pApc = 0;
        ULONG EToffSET=0x248;
        if ( MmIsAddressValid((PVOID)Thread) == TRUE)
        {
                pApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
                //Fix Thread Type To SYSTEM THREAD
                *(PULONG)((ULONG)Thread+EToffSET)=0x10; //XP=0x248, 2K3=0x240, VISTA+2k8=0x260, Win7=0x280
                //If APC is OK
                if (pApc)
                {
                        KeInitializeApc(pApc, (PKTHREAD)Thread, OriginalApcEnvironment, ApcCallBack, 0, 0, KernelMode, 0);
                        //MsInsertQueueApc(pApc, NULL, NULL, 0);
                        //Test Use KiInsertQueueApc
                        pApc->SystemArgument1=NULL;
                        pApc->SystemArgument2=NULL;
                        pApc->Inserted = FALSE;
                        //KiInsertQueueApc=(KIINSERTQUEUEAPC)GetKiInsertQueueApc();
                        //KiInsertQueueApc(pApc,0);
                        KiInsertQueueApc(pApc,0);
                        DbgPrint("KiInsertQueueApc Over!");
                }
                st = STATUS_SUCCESS;
        }
        return st;       
}

PETHREAD GetNextProcessThread(IN PEPROCESS Process,IN PETHREAD Thread OPTIONAL)
{
    PETHREAD FoundThread = NULL;
    PLIST_ENTRY ListHead, Entry;
    PAGED_CODE();
    if (Thread)
    {
                Entry = (PLIST_ENTRY)((ULONG)(Thread) + ThreadListEntryOffset);//+0x22c ThreadListEntry  : _LIST_ENTRY
                Entry=Entry->Flink;
    }
    else
    {
        Entry = (PLIST_ENTRY)((ULONG)(Process) + ThreadListHeadOffset);//+0x190 ThreadListHead   : _LIST_ENTRY
        Entry = Entry->Flink;
    }
        ListHead = (PLIST_ENTRY)((ULONG)Process + ThreadListHeadOffset);
    while (ListHead != Entry)
    {
                FoundThread = (PETHREAD)((ULONG)Entry - ThreadListEntryOffset);
                if (ObReferenceObject(FoundThread)) break;
        FoundThread = NULL;
        Entry = Entry->Flink;
    }
    if (Thread) ObDereferenceObject(Thread);
    return FoundThread;
}

NTSTATUS TerminateProcess(PEPROCESS Process)
{
        NTSTATUS Status;
        PETHREAD Thread;       
        Status = STATUS_SUCCESS;
        KiAddr=GetKiInsertQueueApc();
        if(KiAddr!=0)
        {
                KiInsertQueueApc=ExAllocatePool( NonPagedPool, 20 );//分配20字节
                memset(KiInsertQueueApc,0x90,20);//NOP
                GetOldCode(KiAddr,12,(PBYTE)KiInsertQueueApc);
        }
        else
        {
                DbgPrint("Can not get KiInsertQueueApc!");
                return STATUS_UNSUCCESSFUL;
        }
        __try
        {
                for (Thread=GetNextProcessThread(Process,NULL); Thread!=NULL; Thread=GetNextProcessThread(Process,Thread))
                {
                        TerminateThread(Thread);
                        DbgPrint("Thread Terminated: %x",(ULONG)Thread);
                }
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
                Status = GetExceptionCode();
        }
        return Status;
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{

        UNICODE_STRING   uniDeviceName;
        UNICODE_STRING   uniSymLink;
        NTSTATUS         ntStatus;
        PDEVICE_OBJECT   deviceObject = NULL;
        RtlInitUnicodeString(&uniDeviceName, NT_DEVICE_NAME);
        RtlInitUnicodeString(&uniSymLink, DOS_DEVICE_NAME);
        DriverObject->MajorFunction[IRP_MJ_CREATE] =
                DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
        DriverObject->DriverUnload = UnloadDriver;
        ntStatus = IoCreateDevice(DriverObject, 0,&uniDeviceName,FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE,&deviceObject);
        if (!NT_SUCCESS(ntStatus)) return ntStatus;
    ntStatus = IoCreateSymbolicLink(&uniSymLink, &uniDeviceName);
        if (!NT_SUCCESS(ntStatus))
        {
                IoDeleteDevice(deviceObject);
                return ntStatus;
        }
        DbgPrint("driver loaded!\n");
    return STATUS_SUCCESS;
}

NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
{
        pIrp->IoStatus.Information = 0;
        pIrp->IoStatus.Status = STATUS_SUCCESS;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
}

NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT pDevObj,IN  PIRP pIrp)
{
        NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;//STATUS_UNSUCCESSFUL;//
        PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
        ULONG uIoControlCode = pIrpStack->arameters.DeviceIoControl.IoControlCode;
        ULONG inBufLength = pIrpStack->arameters.DeviceIoControl.InputBufferLength;
        ULONG outBufLength =pIrpStack->arameters.DeviceIoControl.OutputBufferLength;
        PVOID OutputBuffer = pIrp->UserBuffer;
        PVOID InputBuffer  = pIrp->AssociatedIrp.SystemBuffer;
        ULONG Ki;
        switch(uIoControlCode)
        {
                case IOCTL_BypassInline:
                {
                        /*MsInsertQueueApc=ExAllocatePool( NonPagedPool, 20 );//分配20字节
                        memset(MsInsertQueueApc,0x90,20);//NOP
                        GetOldCode(GetFunctionAddr(L"KeInsertQueueApc"),10,(PBYTE)MsInsertQueueApc);*/
                        /*GetOldCode(GetKiInsertQueueApc(),12,KiInsertQueueApc_orig_code);
                        for(Ki=0;Ki<12;Ki++)
                                DbgPrint("KiInsertQueueApc[%d]=%x",Ki,KiInsertQueueApc_orig_code[Ki]);*/
                        break;
                }
                case IOCTL_KillProcByEP:
                {
                        memcpy(&KillProc,InputBuffer,sizeof(ULONG));
                        //XPRestoreKiInsertQueueApc();
                        TerminateProcess((PEPROCESS)KillProc);
                        break;
                }
        }
        pIrp->IoStatus.Status = ntStatus;
        //pIrp->IoStatus.Information = outBufLength;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        return ntStatus;
}

VOID UnloadDriver( IN PDRIVER_OBJECT DriverObject )
{
        PDEVICE_OBJECT    deviceObject = DriverObject->DeviceObject;
        UNICODE_STRING    uniSymLink;
        RtlInitUnicodeString(&uniSymLink, DOS_DEVICE_NAME);
        if (MsInsertQueueApc) ExFreePool(MsInsertQueueApc);
        DbgPrint("driver unloaded.\n");
        IoDeleteSymbolicLink(&uniSymLink);
        IoDeleteDevice(deviceObject);
}
```

绕过Head Inline Hook.7z

22.14 KB, 下载次数: 3

回复

使用道具

匿名  发表于 2023-7-12 19:18:17
用vs2022的注册不成功该怎么办…?
回复

使用道具

匿名  发表于 2023-7-20 22:42:39
66666
回复

使用道具

匿名  发表于 2023-9-1 21:49:54
学习啦
回复

使用道具

0

主题

7

回帖

26

积分

新手上路

积分
26
发表于 2024-6-9 22:05:08 | 显示全部楼层
1111FFFFFFFFFFF
回复

使用道具 举报

0

主题

7

回帖

26

积分

新手上路

积分
26
发表于 2024-6-9 22:05:53 | 显示全部楼层
2344444444
回复

使用道具 举报

0

主题

7

回帖

26

积分

新手上路

积分
26
发表于 2024-6-9 22:06:09 | 显示全部楼层
GFDGREGERH
回复

使用道具 举报

0

主题

3

回帖

53

积分

注册会员

积分
53
发表于 2024-6-12 20:19:08 | 显示全部楼层
感谢分享~~~~~~
回复

使用道具 举报

1

主题

19

回帖

53

积分

注册会员

积分
53
发表于 2024-6-21 11:46:37 | 显示全部楼层
有点意思但不多
回复

使用道具 举报

0

主题

23

回帖

52

积分

注册会员

积分
52
发表于 2024-7-23 23:57:25 | 显示全部楼层
有没有大佬写个教程分享一下?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|游戏安全实验室

GMT+8, 2024-11-21 15:35 , Processed in 0.058585 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表