驱动中给进程注入DLL,模拟GlobaHook,不完整,某些情况下报错

利用 PsSetLoadImageNotifyRoutine 设置回调,等有镜像被加载的时候,根据进程PID获取基址,然后和镜像基址对比,
如果相同,则加载的是进程EXE的镜像,这个时候通过修改镜像头中的导入表 来注入DLL。
修改导入表部分的代码,是修改的MS的detours库来的。
经过测试大部分进程注入都没问题,碰到一些比较特殊的进程运行的时候会报错,请教高手。。。
一下是核心代码:

//获取进程基址
PVOID GetProcessBaseAddress(IN HANDLE PID)
{
    NTSTATUS status;
    HANDLE hProcess = NULL;
    CLIENT_ID clientid;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PPROCESS_BASIC_INFORMATION pProcessBaseInfo;
    ULONG returnedLength;
    PMY_PEB Peb;
    PVOID ImageBase = NULL;

    if(KeGetCurrentIrql() >= DISPATCH_LEVEL)
    { 
        return ImageBase;
    }

    InitializeObjectAttributes(&ObjectAttributes, 0, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, 0, 0);
    clientid.UniqueProcess = PID;
    clientid.UniqueThread = 0;
    //通过PID获得进程句柄
    status = ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &ObjectAttributes, &clientid);
    if(!NT_SUCCESS(status))
    {
        DbgPrint("[GetProcessBaseAddress] ZwOpenProcess 调用失败\n");
        return ImageBase;
    }

    pProcessBaseInfo = (PPROCESS_BASIC_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESS_BASIC_INFORMATION), 'sam1');
    if (pProcessBaseInfo == NULL)
    {
        DbgPrint("[GetProcessBaseAddress]ExAllocatePoolWithTag 分配内存失败\n");
        ZwClose(hProcess);
        return ImageBase;        
    }
    RtlZeroMemory(pProcessBaseInfo, sizeof(PROCESS_BASIC_INFORMATION));

    //获得文件镜像名
    status = ZwQueryInformationProcess(hProcess, ProcessBasicInformation, pProcessBaseInfo, sizeof(PROCESS_BASIC_INFORMATION), &returnedLength);
    if(NT_SUCCESS(status)) 
    {
        Peb = (PMY_PEB)pProcessBaseInfo->PebBaseAddress;
        ImageBase = Peb->Reserved3[1];
    }
    else
    {
        DbgPrint("[GetProcessBaseAddress]2.ZwQueryInformationProcess 调用失败\n");
    }

    ZwClose(hProcess);
    ExFreePool(pProcessBaseInfo);
    return ImageBase;
}
//-----------------------------------------------------------------------------------------------------


//---------------------------------------
ULONG PadToDword(ULONG dw)
{
    return (dw + 3) & ~3u;
}

ULONG PadToDwordPtr(ULONG dw)
{
    return (dw + 7) & ~7u;
}

BOOLEAN StringCchCopyA(CHAR *pszDest, size_t cchDest, const CHAR *pszSrc)
{
    BOOLEAN hr = TRUE;

    if (cchDest == 0)
    {
        hr = FALSE;
    }
    else
    {
        while (cchDest && (*pszSrc != '\0'))
        {
            *pszDest++ = *pszSrc++;
            cchDest--;
        }

        if (cchDest == 0)
        {
            // we are going to truncate pszDest
            pszDest--;
            hr = FALSE;
        }

        *pszDest= '\0';
    }

    return hr;
}

//修改导入表注入DLL
BOOLEAN XXXXXDLL(IN HANDLE ProcessId,  IN PVOID pImageBase, PCHAR lpDlls[], ULONG nDlls)
{
    NTSTATUS ntStatus;

    PEPROCESS EProcess;
    KAPC_STATE ApcState;
    HANDLE hProcessHandle;
    CHAR curProcessName[16] = {0};

    PIMAGE_DOS_HEADER pDos;                            //DOS头
    PIMAGE_NT_HEADERS pHeader;                        //NT头
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc;    //原始导入表
    PDETOUR_CLR_HEADER pClr;

    ULONG nBound = 0;
    ULONG dwFileSize = 0;
    ULONG dwSec = 0;

    PVOID pbNewIid = NULL;
    PVOID pbNew = NULL;
    ULONG cbNew = 0;
    ULONG obRem = 0;
    ULONG obTab = 0;
    ULONG obDll = 0;
    ULONG obStr = 0;
    ULONG cbTmp = 0;
    ULONG obBase = 0;
    ULONG i=0, n=0;

    ULONG OldProtect = 0;
    PVOID lpTemp1 = NULL;
    ULONG dwTemp1 = 0;

    if(ProcessId == 0 || pImageBase == NULL)
    {
        return FALSE;
    }

    pDos =(PIMAGE_DOS_HEADER) pImageBase;
    pHeader = (PIMAGE_NT_HEADERS)((ULONG)pImageBase + (ULONG)pDos->e_lfanew);
    pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG)pImageBase + pHeader->IMPORT_DIRECTORY.VirtualAddress);

    if(pHeader->IMPORT_DIRECTORY.VirtualAddress == 0)
    {
        return FALSE;
    }

    if(PsLookupProcessByProcessId( (PVOID)ProcessId, (PEPROCESS *)&EProcess) != STATUS_SUCCESS) 
    {
        DbgPrint("[XXXXXDLL] PsLookupProcessByProcessId failed\n");
        return FALSE;
    }

    __try
    {
        KeStackAttachProcess(EProcess, &ApcState);

        ntStatus = ObOpenObjectByPointer(EProcess, OBJ_KERNEL_HANDLE, NULL, 0x008,  NULL, KernelMode, &hProcessHandle);
        if(!NT_SUCCESS(ntStatus)) 
        {
            DbgPrint("[XXXXXDLL] ObOpenObjectByPointer failed error [%08X]\n", ntStatus);
            __leave;
        }

        lpTemp1 = (PVOID)(&pHeader->BOUND_DIRECTORY.VirtualAddress);
        dwTemp1 = 4;
        ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, PAGE_EXECUTE_READWRITE, &OldProtect);
        pHeader->BOUND_DIRECTORY.VirtualAddress = 0;
        ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, OldProtect, NULL);

        lpTemp1 = (PVOID)(&pHeader->BOUND_DIRECTORY.Size);
        dwTemp1 = 4;
        ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, PAGE_EXECUTE_READWRITE, &OldProtect);
        pHeader->BOUND_DIRECTORY.Size = 0;
        ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, OldProtect, NULL);


        dwSec = (ULONG)pDos->e_lfanew + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + pHeader->FileHeader.SizeOfOptionalHeader;
        for (i=0; i<pHeader->FileHeader.NumberOfSections; i++) 
        {
            PIMAGE_SECTION_HEADER pSectionHeader;
            pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONG)pImageBase + dwSec + (sizeof(IMAGE_SECTION_HEADER) * i));

            // 如果该文件不具有IAT_DIRECTORY,我们创建一个.
            if (pHeader->IAT_DIRECTORY.VirtualAddress == 0 &&
                pHeader->IMPORT_DIRECTORY.VirtualAddress >= pSectionHeader->VirtualAddress &&
                pHeader->IMPORT_DIRECTORY.VirtualAddress < pSectionHeader->VirtualAddress +pSectionHeader->SizeOfRawData
                ) 
            {
                lpTemp1 = (PVOID)(&pHeader->IAT_DIRECTORY.VirtualAddress);
                dwTemp1 = 4;
                ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, PAGE_EXECUTE_READWRITE, &OldProtect);
                pHeader->IAT_DIRECTORY.VirtualAddress = pSectionHeader->VirtualAddress;
                ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, OldProtect, NULL);

                lpTemp1 = (PVOID)(&pHeader->IAT_DIRECTORY.Size);
                dwTemp1 = 4;
                ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, PAGE_EXECUTE_READWRITE, &OldProtect);
                pHeader->IAT_DIRECTORY.Size = pSectionHeader->SizeOfRawData;
                ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, OldProtect, NULL);
            }

            // Find the end of the file...
            if (dwFileSize < pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData)
            {
                dwFileSize = pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData;
            }
        }

        obRem = sizeof(IMAGE_IMPORT_DESCRIPTOR) * nDlls;
        obTab = PadToDwordPtr(obRem + pHeader->IMPORT_DIRECTORY.Size);
        obDll = obTab + sizeof(DWORD_PTR) * 4 * nDlls;
        obStr = obDll;
        cbNew = obStr;

        for(n=0; n<nDlls; n++) 
        {
            cbNew += PadToDword((DWORD)strlen(lpDlls[n]) + 1);
        }

        // 分配本地内存,先在本地内存中构造好输入表
        pbNew = ExAllocatePoolWithTag(NonPagedPool, cbNew, 'sam1');
        if (pbNew == NULL) 
        {
            DbgPrint("[XXXXXDLL] ExAllocatePoolWithTag cbNew faile\n");
            __leave;
        }
        RtlZeroMemory(pbNew, cbNew);

        // 在进程中分配和本地内存同样大小的虚拟内存
        cbTmp = cbNew;
        ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &pbNewIid, 0, &cbTmp, MEM_COMMIT|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
        if(!NT_SUCCESS(ntStatus))
        { 
            DbgPrint("[XXXXXDLL] ZwAllocateVirtualMemory pbNewIid failed error [%08X]\n", ntStatus);
            __leave;
        }
        RtlZeroMemory(pbNewIid, cbNew);

        // pbNewIid 是我们在远程线程分配的新的输入表的首地址,和pbModule想减后就得到它的RVA了
        obBase = (ULONG)((ULONG)pbNewIid - (ULONG)pImageBase);

        // 将旧的输入表读入到本地内存,注意有一个偏移obRem
        RtlCopyMemory((PUCHAR)((ULONG)pbNew + obRem), pImportDesc, pHeader->IMPORT_DIRECTORY.Size);

        {
            PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew;
            ULONG_PTR *pt = NULL;
            ULONG nOffset = 0;

            for(n=0; n<nDlls; n++)
            {
                if(!StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, lpDlls[n]))
                {
                    DbgPrint("StringCchCopyA 拷贝DLL路径失败\n");
                    __leave;
                }

                nOffset = obTab + (sizeof(ULONG_PTR) * (4 * n));
                piid[n].OriginalFirstThunk = obBase + nOffset;
                pt = ((ULONG_PTR*)((ULONG)pbNew + nOffset));
                pt[0] = IMAGE_ORDINAL_FLAG + 1;
                pt[1] = 0;

                nOffset = obTab + (sizeof(ULONG_PTR) * ((4 * n) + 2));
                piid[n].FirstThunk = obBase + nOffset;
                pt = ((ULONG_PTR*)((ULONG)pbNew + nOffset));
                pt[0] = IMAGE_ORDINAL_FLAG + 1;
                pt[1] = 0;

                piid[n].TimeDateStamp = 0;
                piid[n].ForwarderChain = 0;
                piid[n].Name = obBase + obStr;

                obStr += PadToDword((ULONG)strlen(lpDlls[n]) + 1);
            }
        }

        //Update the CLR header.
        if (pHeader->CLR_DIRECTORY.VirtualAddress != 0 && pHeader->CLR_DIRECTORY.Size != 0) 
        {
            ULONG flg = 0;
            pClr = (PDETOUR_CLR_HEADER)((ULONG)pImageBase + pHeader->CLR_DIRECTORY.VirtualAddress);
            flg = pClr->Flags & 0xfffffffe;

            lpTemp1 = (PVOID)(&pClr->Flags);
            dwTemp1 = 4;
            ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, PAGE_EXECUTE_READWRITE, &OldProtect);
            pClr->Flags = flg;
            ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, OldProtect, NULL);
        }

        if(pHeader->IMPORT_DIRECTORY.VirtualAddress > 0)
        {
            //拷贝本地内存中的新的输入表数据到虚拟内存中
            ntStatus = ZwWriteVirtualMemory(hProcessHandle, pbNewIid, pbNew, obStr, NULL);
            if(!NT_SUCCESS(ntStatus))
            {
                DbgPrint("[XXXXXDLL] ZwWriteVirtualMemory pbNewIid failed error [%08X]\n", ntStatus);
                __leave;
            }


            KdPrint(("原导入表: [%08X] - [%d]\n", pHeader->IMPORT_DIRECTORY.VirtualAddress, pHeader->IMPORT_DIRECTORY.Size));
            //设置输入表的地址和大小,为刚才分配的虚拟内存
            lpTemp1 = (PVOID)(&pHeader->IMPORT_DIRECTORY.VirtualAddress);
            dwTemp1 = 4;
            ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, PAGE_EXECUTE_READWRITE, &OldProtect);
            pHeader->IMPORT_DIRECTORY.VirtualAddress = obBase;
            ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, OldProtect, NULL);

            lpTemp1 = (PVOID)(&pHeader->IMPORT_DIRECTORY.Size);
            dwTemp1 = 4;
            ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, PAGE_EXECUTE_READWRITE, &OldProtect);
            pHeader->IMPORT_DIRECTORY.Size = cbNew;
            ZwProtectVirtualMemory(hProcessHandle, &lpTemp1, &dwTemp1, OldProtect, NULL);

            KdPrint(("新导入表: [%08X] - [%d]\n", pHeader->IMPORT_DIRECTORY.VirtualAddress, pHeader->IMPORT_DIRECTORY.Size));
        }
    }
    __finally
    {
        if(pbNew)
        {
            ExFreePool(pbNew);
        }

        if(hProcessHandle)
        {
            ZwClose(hProcessHandle);
            hProcessHandle = NULL;
        }

        KeUnstackDetachProcess(&ApcState);
    }

    ObDereferenceObject(EProcess);
    return TRUE;
}
//--------------------------------------------------------------------------------------


//LoadImage回调,在此注入DLL
VOID LoadImageRoutine(
                      IN PUNICODE_STRING  FullImageName,
                      IN HANDLE  ProcessId, // where image is mapped
                      IN PIMAGE_INFO  ImageInfo
                      )
{
    PVOID pProcessBase = NULL;

    if(ImageInfo->SystemModeImage)
    {
    }
    else
    {
        pProcessBase = GetProcessBaseAddress(ProcessId);
        if(pProcessBase == ImageInfo->ImageBase)
        {
            //注入DLL
            CHAR *rlpDlls[2];
            ULONG nDlls = 0;
            rlpDlls[nDlls++] = "HookReg.dll";
            XXXXXDLL(ProcessId, ImageInfo->ImageBase, rlpDlls, nDlls);
        }
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值