Windows 回调监控 <二>

在之前的文章Windows 回调监控 <一> 总结了关于CreateProcessNotify,CreateProcessNotifyEx和LoadImageNotify一些用法,之后产生了一个思路,既然在进程创建的时候加载.exe文件会执行我们的回调函数,那么如果在我们回调函数之中对内存中的.exe文件的导入表增加一个项,这样进程会不会加载我们事先准备好的.dll文件,如果成功加载我们的dll话,就注入成功了。  

#pragma once

#include <ntifs.h>
#include <ntimage.h>
#include <WINDEF.H>

VOID WPOFF();
VOID WPON();
VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName,HANDLE  ProcessId,PIMAGE_INFO  ImageInfor);
extern CHAR*  PsGetProcessImageFileName(PEPROCESS EProcess);
VOID UnicodeToChar(PUNICODE_STRING uniSource, CHAR *szDest);

#include "LoadImage.h"


PIMAGE_IMPORT_DESCRIPTOR g_OldImportDesc;
KIRQL Irql;
PEPROCESS g_TargetProcess;
HANDLE    g_TargetProcessId;

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

    DbgPrint("驱动加载\r\n");
    DriverObject->DriverUnload = UnloadDriver;
    PsSetLoadImageNotifyRoutine((PLOAD_IMAGE_NOTIFY_ROUTINE)LoadImageNotifyRoutine);
    return STATUS_SUCCESS;
}

VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{
    PsRemoveLoadImageNotifyRoutine((PLOAD_IMAGE_NOTIFY_ROUTINE)LoadImageNotifyRoutine);
    DbgPrint("驱动卸载\r\n");
}



VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName,HANDLE  ProcessId,PIMAGE_INFO  ImageInfor)
{
    NTSTATUS Status;
    PVOID DriverEntryAddress = NULL;
    char szFullImageName[260]={0};
    PEPROCESS TatgetProcess = NULL;
    KAPC_STATE apcState;
    BOOLEAN       bAttached =FALSE;
    HANDLE    hProcess;
    Status  = PsLookupProcessByProcessId(ProcessId,&TatgetProcess);
    if (!NT_SUCCESS(Status))
    {
        return ;
    }
    if (strstr(PsGetProcessImageFileName(TatgetProcess),"cc.exe")) //当前进程是cc.exe
    {
        UnicodeToChar(FullImageName,szFullImageName);

        if (strstr(szFullImageName,"cc.exe"))  //加载的是cc.exe
        {
            g_TargetProcessId = ProcessId;
            Status = ObOpenObjectByPointer(TatgetProcess, 
                OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 
                NULL, 
                GENERIC_ALL, 
                *PsProcessType, 
                KernelMode, 
                &hProcess
                );
            if (!NT_SUCCESS(Status))
            {
                ObDereferenceObject(TatgetProcess);
                return; 
            }
            g_TargetProcess = TatgetProcess;
            __try
            {
                //KeStackAttachProcess(TatgetProcess,&apcState);
                if (MmIsAddressValid(ImageInfor->ImageBase))
                {
                    PIMAGE_DOS_HEADER pDos;
                    PIMAGE_NT_HEADERS pHeader = NULL;
                    PIMAGE_IMPORT_DESCRIPTOR  pImportDesc;
                    //ZwUnmapViewOfSection(hProcess,ImageInfor->ImageBase);
                    ULONG nImportDllCount;
                    PVOID ulImageBase = ImageInfor->ImageBase;
                    ULONG nNewImportSize;
                    ULONG nNewDllNameSize = 0x20;
                    PIMAGE_IMPORT_DESCRIPTOR lpNewImportDesc = NULL;
                    PVOID lpDllName = NULL;
                    IMAGE_IMPORT_DESCRIPTOR Add_ImportDesc;
                    PIMAGE_THUNK_DATA        lpNewThunkData = NULL;
                    ULONG nNewThunkDataSize = 0x20;
                    PIMAGE_IMPORT_BY_NAME lpImportApi = NULL;
                    ULONG nNewImportApiSize  = 0x20;
                    pDos =(PIMAGE_DOS_HEADER) ulImageBase;

                    pHeader = (PIMAGE_NT_HEADERS)((ULONG)ulImageBase+(ULONG)pDos->e_lfanew);
                    pImportDesc  = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG)pHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress \
                        + (ULONG)ulImageBase);
                    //导入表项个数
                    nImportDllCount = pHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);

                    g_OldImportDesc = pImportDesc;//原始的导入表

                    nNewImportSize = sizeof(IMAGE_IMPORT_DESCRIPTOR)*(nImportDllCount+1);//加上自己的

                    Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &lpNewImportDesc, 0, &nNewImportSize,
                        MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                    if (!NT_SUCCESS(Status))
                    {
                        ObDereferenceObject(TatgetProcess);
                        ObDereferenceObject(TatgetProcess);
                        return;
                    }
                    RtlZeroMemory(lpNewImportDesc,nNewImportSize);

                    Status = ZwAllocateVirtualMemory(hProcess, &lpDllName, 0, &nNewDllNameSize,
                        MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                    if (!NT_SUCCESS(Status))
                    {
                        ZwFreeVirtualMemory(hProcess,&lpNewImportDesc,0,MEM_RELEASE);
                        ObDereferenceObject(TatgetProcess);
                        ObDereferenceObject(TatgetProcess);
                        return;
                    }

                    RtlZeroMemory(lpDllName,nNewDllNameSize);

                    //ThunkData
                    Status = ZwAllocateVirtualMemory(hProcess, &lpNewThunkData, 0, &nNewThunkDataSize,
                        MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                    if (!NT_SUCCESS(Status))
                    {
                        ZwFreeVirtualMemory(hProcess,&lpNewImportDesc,0,MEM_RELEASE);
                        ZwFreeVirtualMemory(hProcess,&lpDllName,0,MEM_RELEASE);
                        ObDereferenceObject(TatgetProcess);
                        ObDereferenceObject(TatgetProcess);
                        return;
                    }
                    RtlZeroMemory(lpNewThunkData,nNewThunkDataSize);                    
                    //IMAGE_IMPORT_BY_NAME
                    Status = ZwAllocateVirtualMemory(hProcess, &lpImportApi, 0, &nNewImportApiSize,
                        MEM_COMMIT|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
                    if (!NT_SUCCESS(Status))
                    {
                        ZwFreeVirtualMemory(hProcess,&lpNewImportDesc,0,MEM_RELEASE);
                        ZwFreeVirtualMemory(hProcess,&lpDllName,0,MEM_RELEASE);
                        ZwFreeVirtualMemory(hProcess,&lpNewThunkData,0,MEM_RELEASE);
                        ObDereferenceObject(TatgetProcess);
                        ObDereferenceObject(TatgetProcess);
                        return;
                    }
                    RtlZeroMemory(lpImportApi,nNewImportApiSize);
                    //原始的导入表,留出一个表项
                    RtlCopyMemory(lpNewImportDesc+1,pImportDesc,sizeof(IMAGE_IMPORT_DESCRIPTOR)*nImportDllCount);
                    lpImportApi->Hint = 0;
                    RtlCopyMemory(lpImportApi->Name,"DllMain",0x20);
                    lpNewThunkData->u1.AddressOfData = (ULONG)lpImportApi-(ULONG)ulImageBase;                
                    Add_ImportDesc.OriginalFirstThunk = (ULONG)lpNewThunkData-(ULONG)ulImageBase;
                    Add_ImportDesc.TimeDateStamp = 0;
                    Add_ImportDesc.ForwarderChain = 0;
                    RtlCopyMemory(lpDllName,"test.dll",0x20);
                    Add_ImportDesc.Name = (ULONG)lpDllName-(ULONG)ulImageBase;
                    Add_ImportDesc.FirstThunk = Add_ImportDesc.OriginalFirstThunk;                    
                    RtlCopyMemory(lpNewImportDesc,&Add_ImportDesc,sizeof(IMAGE_IMPORT_DESCRIPTOR));
                    WPOFF(); //修改Descriptor
                    pHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
                    pHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = (ULONG_PTR)lpNewImportDesc - (ULONG_PTR)ulImageBase;
                    WPON();

                }
                //KeUnstackDetachProcess(&apcState);
            }__except(EXCEPTION_EXECUTE_HANDLER){
            }
            ObDereferenceObject(TatgetProcess);
        }
    }

    ObDereferenceObject(TatgetProcess);
}

VOID WPOFF()
{
    ULONG_PTR cr0 = 0;
    Irql = KeRaiseIrqlToDpcLevel();
    cr0 =__readcr0();
    cr0 &= 0xfffffffffffeffff;
    __writecr0(cr0);

}


VOID WPON()
{

    ULONG_PTR cr0=__readcr0();
    cr0 |= 0x10000;
    __writecr0(cr0);
    KeLowerIrql(Irql);
}

VOID UnicodeToChar(PUNICODE_STRING uniSource, CHAR *szDest)
{                                                  
    ANSI_STRING ansiTemp;                                
    RtlUnicodeStringToAnsiString(&ansiTemp,uniSource,TRUE);   

    strcpy(szDest,ansiTemp.Buffer);
    RtlFreeAnsiString(&ansiTemp);
}

 

点赞