CARRIE 发表于 2017-6-1 17:25:37

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,HANDLEProcessId,PIMAGE_INFOImageInfor);
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,HANDLEProcessId,PIMAGE_INFOImageInfor)
{
    NTSTATUS Status;
    PVOID DriverEntryAddress = NULL;
    char szFullImageName={0};
    PEPROCESS TatgetProcess = NULL;
    KAPC_STATE apcState;
    BOOLEAN       bAttached =FALSE;
    HANDLE    hProcess;
    Status= PsLookupProcessByProcessId(ProcessId,&amp;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,
                &amp;hProcess
                );
            if (!NT_SUCCESS(Status))
            {
                ObDereferenceObject(TatgetProcess);
                return;
            }
            g_TargetProcess = TatgetProcess;
            __try
            {
                //KeStackAttachProcess(TatgetProcess,&amp;apcState);
                if (MmIsAddressValid(ImageInfor->ImageBase))
                {
                  PIMAGE_DOS_HEADER pDos;
                  PIMAGE_NT_HEADERS pHeader = NULL;
                  PIMAGE_IMPORT_DESCRIPTORpImportDesc;
                  //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.VirtualAddress \
                        + (ULONG)ulImageBase);
                  //导入表项个数
                  nImportDllCount = pHeader->OptionalHeader.DataDirectory.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);

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

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

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

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

                  RtlZeroMemory(lpDllName,nNewDllNameSize);

                  //ThunkData
                  Status = ZwAllocateVirtualMemory(hProcess, &amp;lpNewThunkData, 0, &amp;nNewThunkDataSize,
                        MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                  if (!NT_SUCCESS(Status))
                  {
                        ZwFreeVirtualMemory(hProcess,&amp;lpNewImportDesc,0,MEM_RELEASE);
                        ZwFreeVirtualMemory(hProcess,&amp;lpDllName,0,MEM_RELEASE);
                        ObDereferenceObject(TatgetProcess);
                        ObDereferenceObject(TatgetProcess);
                        return;
                  }
                  RtlZeroMemory(lpNewThunkData,nNewThunkDataSize);                  
                  //IMAGE_IMPORT_BY_NAME
                  Status = ZwAllocateVirtualMemory(hProcess, &amp;lpImportApi, 0, &amp;nNewImportApiSize,
                        MEM_COMMIT|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
                  if (!NT_SUCCESS(Status))
                  {
                        ZwFreeVirtualMemory(hProcess,&amp;lpNewImportDesc,0,MEM_RELEASE);
                        ZwFreeVirtualMemory(hProcess,&amp;lpDllName,0,MEM_RELEASE);
                        ZwFreeVirtualMemory(hProcess,&amp;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,&amp;Add_ImportDesc,sizeof(IMAGE_IMPORT_DESCRIPTOR));
                  WPOFF(); //修改Descriptor
                  pHeader->OptionalHeader.DataDirectory.Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
                  pHeader->OptionalHeader.DataDirectory.VirtualAddress = (ULONG_PTR)lpNewImportDesc - (ULONG_PTR)ulImageBase;
                  WPON();

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

    ObDereferenceObject(TatgetProcess);
}

VOID WPOFF()
{
    ULONG_PTR cr0 = 0;
    Irql = KeRaiseIrqlToDpcLevel();
    cr0 =__readcr0();
    cr0 &amp;= 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(&amp;ansiTemp,uniSource,TRUE);   

    strcpy(szDest,ansiTemp.Buffer);
    RtlFreeAnsiString(&amp;ansiTemp);
}
页: [1]
查看完整版本: Windows 回调监控