为什么我注入的dll 在目标进程还没结束时就已经触发 DLL_PROCESS_DETACH?

新手上路,请多包涵

比如说user32.dll会在什么时候被解除映射?
我所写的dll好像是被loadlibrary调用完,就被freelibrary了.
图片描述


这是我的dll的代码

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include <stdio.h>
#include <ImageHlp.h>                //for ImageDirectoryEntryToData
#include <TlHelp32.h>                 //for Module32First,MODULEENTRY32 and CreateToolhelp32Snapshot
#pragma comment(lib,"ImageHlp")       //for ImageDirectoryEntryToData


//替换了的MessageBoxA.注意函数原型要和原来的一致,包括WIAPI
//它显示一个消息框指明MessageBoxA已被截获
int WINAPI MyMessageBoxA(HWND hwnd, LPCSTR lpszContent, LPCSTR lpszCaption, UINT uType) {
    return MessageBoxW(hwnd, TEXT("Call to MessageBoxW is interceptedZZZZZZZZZZ!"), TEXT("Hook"), MB_OK);
}
//修改输入表
VOID ModifyIAT(HMODULE hmodCaller, LPCSTR szDllName, PROC pfnCurent, PROC pfnNew) {

    ULONG ulSize;

    PIMAGE_IMPORT_DESCRIPTOR pid = (PIMAGE_IMPORT_DESCRIPTOR)
        ImageDirectoryEntryToData(
            hmodCaller,
            TRUE,
            IMAGE_DIRECTORY_ENTRY_IMPORT,
            &ulSize);
    // if this image has no import section, just simply return and do nothing

    if (pid == NULL)
        return;

    // find the corresponding item
    while (pid->Name)
    {
        // pid->Name contains the RVA addr of the module name string

        PSTR pszModName = (PSTR)((PBYTE)hmodCaller + pid->Name);

        if (lstrcmpiA(szDllName, pszModName) == 0)
        {
            // found
            break;
        }

        pid++;
    }
    if (pid->Name == 0)

    {
        // not found, just return
        return;
    }
    // get caller's import address table(IAT) for the callee's functions

    PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hmodCaller + pid->FirstThunk);

    while (pThunk->u1.Function)

    {

        PROC *ppfn = (PROC*) &(pThunk->u1.Function);

        if (*ppfn == pfnCurent)
        {

            SIZE_T sBytesWritten;
            BOOL bProtectResult = FALSE;
            DWORD dwOldProtect = 0;

            MEMORY_BASIC_INFORMATION memInfo;
            if (VirtualQuery(pfnCurent, &memInfo, sizeof(memInfo)) > 0)
            {
                // change the pages to read/write
                bProtectResult = VirtualProtect(
                    memInfo.BaseAddress,
                    memInfo.RegionSize,
                    PAGE_READWRITE,
                    &dwOldProtect);
                printf("ok\n");
                WriteProcessMemory(GetCurrentProcess(),
                    ppfn,
                    &pfnNew,
                    sizeof(pfnNew),
                    &sBytesWritten);
                bProtectResult = VirtualProtect(
                    memInfo.BaseAddress,
                    memInfo.RegionSize,
                    PAGE_READONLY,
                    &dwOldProtect);
            }
            return;
        }
        pThunk++;
    }
}
//dll的入口函数.每当这个dll被映射到一个进程的地址空间中,我们就挂接MessageBoxW
//在dll从进程的地址空间中缷载时,我们将原来的MessageboxW的地址写回进程中
//要取得这个进程的基地址,要用到MODULEENTRY32和CreateToolhelp32Snapshot
//MODULEENTRY32的hModule成员就是进程的基地址
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved)
{
    HMODULE hCurrentProcess;
    MODULEENTRY32 me32;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
    me32.dwSize = sizeof(MODULEENTRY32);
    Module32First(hSnapshot, &me32);
    hCurrentProcess = me32.hModule;
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        printf("Process attach. \n");
        ModifyIAT(
            hCurrentProcess,
            "USER32.DLL",
            GetProcAddress(GetModuleHandle(TEXT("USER32.DLL")), "MessageBoxA"),
            (PROC)MyMessageBoxA
        );
        
        break;
    case DLL_THREAD_ATTACH:
        printf("Thread attach. \n");
    case DLL_THREAD_DETACH:
        printf("Thread detach. \n");
    case DLL_PROCESS_DETACH:
        printf("Process detach. \n");
        break;
    }
    return TRUE;
}

这是我编写的测试程序代码

#include "stdafx.h"
#include<Windows.h>
#include<iostream>
using namespace std;
int main()
{
    int a;
    cin >> a;
    MessageBoxA(NULL, "666", "666", MB_OK);
    system("pause");
    return 0;
    
}

这是我创建远程线程注入dll的程序

// injectdll.cpp: 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include <Windows.h>
#include <TlHelp32.h>

int main()
{
    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获得进程快照
    if (hProcessSnap == FALSE)
    {
        printf("CreateToolhelp32Snapshot error");
        return -1;
    }
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);
    TCHAR m_processToFind[128] = TEXT("ConsoleApplication1.exe");//所要注入的进程名
    BOOL bRet = Process32First(hProcessSnap, &pe32);
    while (bRet)
    {
        printf("[process name]:%ws\n", pe32.szExeFile);
        printf("[PID]:%d\n\n", pe32.th32ProcessID);
        if (lstrcmp(pe32.szExeFile, m_processToFind) == 0)
        {

            printf("进程:%ws找到,它的进程ID为:%d\n", m_processToFind, pe32.th32ProcessID);
            HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pe32.th32ProcessID);//获得所要注入进程的句柄
                                                                                     //执行openprocess之前可能需要开启特权
            PVOID addr = VirtualAllocEx(hProcess, NULL, 50, MEM_COMMIT, PAGE_READWRITE);//在所注入进程开辟一段空间
            if (addr == NULL)
            {
                int ret = GetLastError();
                printf("在远程进程申请空间失败!错误码为:%d\n", ret);
            }
            else
            {
                printf("远程进程地址空间中申请空间成功!\n");
            }
            char path[50] = "F:\\injertdll.dll";//自己编写的注入dll
            int retval = WriteProcessMemory(hProcess, addr, (LPVOID)path, sizeof(path), NULL);//将自己dll写入到所找进程空间
            if (retval)
            {
                printf("写入成功!\n");
            }
            else
                printf("写入失败!\n");
            PTHREAD_START_ROUTINE pfnThread = (PTHREAD_START_ROUTINE)
                GetProcAddress(GetModuleHandle(TEXT("kernel32.DLL")), "LoadLibraryA");//用loadlibrary注入自己的dll
            HANDLE hRemoteThread = CreateRemoteThread(
                hProcess,//目标进程的句柄   
                NULL,//指向线程的安全描述结构体的指针,一般设置为NULL,表示使用默认的安全级别
                0, //线程堆栈大小,一般设置为0
                pfnThread,//线程函数的地址(loadlibrary)
                addr,//线程参数(传入loadlibrary的dll)
                0,//线程的创建方式
                NULL); //输出参数,记录创建的远程线程的ID
            if (hRemoteThread == INVALID_HANDLE_VALUE)
            {
                printf("远程线程创建失败!\n");
            }
            else
            {
                printf("远程线程创建成功!\n");
            }


            break;
        }
        bRet = Process32Next(hProcessSnap, &pe32);
    }
    system("pause");
    CloseHandle(hProcessSnap); // 经常忘记这句
    return 0;
}

在测试程序执行messageboxA时会报错,是不是因为注入的DLL已经被解除映射了

阅读 4.3k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题