在之前的文章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); }