3 0 0

绕过Head Inline Hook

大理寺少卿
643 3

本文共计2208个字,预计阅读时长8.3分钟。

#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->Parameters.DeviceIoControl.IoControlCode;
    ULONG inBufLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
    ULONG outBufLength =pIrpStack->Parameters.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);
}
上传的附件:

最新回复 ( 3 )
全部楼主