C++ DLL远程注入与卸载函数

第一个函数是成功的,第二个函数运行发现会将目标程序挂死,也许是目标程序有保护机制
支持Unicode编码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
    //-----------------------------------------------------------------------------------------------------------  
    // 函数: InjectDll  
    // 功能: 向目标进程中注入一个指定 Dll 模块文件.  
    // 参数: [in] const TCHAR* ptszDllFile - Dll 文件名及路径  
    //       [in] DWORD dwProcessId - 目标进程 ID  
    // 返回: bool - 注入成功返回 true, 注入失败则返回 false.  
    // 说明: 采用远程线程注入技术实现  
    //-----------------------------------------------------------------------------------------------------------  
    bool InjectDll(const TCHAR* ptszDllFile, DWORD dwProcessId)  
    {  
        // 参数无效  
        if (NULL == ptszDllFile || 0 == ::_tcslen(ptszDllFile))  
        {  
            return false;  
        }  
        // 指定 Dll 文件不存在  
        if (-1 == _taccess(ptszDllFile, 0))  
        {  
            return false;  
        }  
        HANDLE hProcess = NULL;  
        HANDLE hThread = NULL;  
        DWORD dwSize = 0;  
        TCHAR* ptszRemoteBuf = NULL;  
        LPTHREAD_START_ROUTINE lpThreadFun = NULL;  
        // 获取目标进程句柄  
        hProcess = ::OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwProcessId);  
        if (NULL == hProcess)  
        {  
            return false;  
        }  
        // 在目标进程中分配内存空间  
        dwSize = (DWORD)::_tcslen(ptszDllFile) + 1;  
        ptszRemoteBuf = (TCHAR*)::VirtualAllocEx(hProcess, NULL, dwSize * sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE);  
        if (NULL == ptszRemoteBuf)  
        {  
            ::CloseHandle(hProcess);  
            return false;  
        }  
        // 在目标进程的内存空间中写入所需参数(模块名)  
        if (FALSE == ::WriteProcessMemory(hProcess, ptszRemoteBuf, (LPVOID)ptszDllFile, dwSize * sizeof(TCHAR), NULL))  
        {  
            ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT);  
            ::CloseHandle(hProcess);  
            return false;  
        }  
        // 从 Kernel32.dll 中获取 LoadLibrary 函数地址  
    #ifdef _UNICODE  
        lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "LoadLibraryW");  
    #else  
        lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "LoadLibraryA");  
    #endif  
        if (NULL == lpThreadFun)  
        {  
            ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT);  
            ::CloseHandle(hProcess);  
            return false;  
        }  
        // 创建远程线程调用 LoadLibrary  
        hThread = ::CreateRemoteThread(hProcess, NULL, 0, lpThreadFun, ptszRemoteBuf, 0, NULL);  
        if (NULL == hThread)  
        {  
            ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT);  
            ::CloseHandle(hProcess);  
            return false;  
        }  
        // 等待远程线程结束  
        ::WaitForSingleObject(hThread, INFINITE);  
        // 清理  
        ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT);  
        ::CloseHandle(hThread);  
        ::CloseHandle(hProcess);  
        return true;  
    }  
    //-----------------------------------------------------------------------------------------------------------  
    // 函数: UnInjectDll  
    // 功能: 从目标进程中卸载一个指定 Dll 模块文件.  
    // 参数: [in] const TCHAR* ptszDllFile - Dll 文件名及路径  
    //       [in] DWORD dwProcessId - 目标进程 ID  
    // 返回: bool - 卸载成功返回 true, 卸载失败则返回 false.  
    // 说明: 采用远程线程注入技术实现  
    //-----------------------------------------------------------------------------------------------------------  
    bool UnInjectDll(const TCHAR* ptszDllFile, DWORD dwProcessId)  
    {  
        // 参数无效  
        if (NULL == ptszDllFile || 0 == ::_tcslen(ptszDllFile))  
        {  
            return false;  
        }  
        HANDLE hModuleSnap = INVALID_HANDLE_VALUE;  
        HANDLE hProcess = NULL;  
        HANDLE hThread = NULL;  
        // 获取模块快照  
        hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);  
        if (INVALID_HANDLE_VALUE == hModuleSnap)  
        {  
            return false;  
        }  
        MODULEENTRY32 me32;  
        memset(&me32, 0, sizeof(MODULEENTRY32));  
        me32.dwSize = sizeof(MODULEENTRY32);  
        // 开始遍历  
        if(FALSE == ::Module32First(hModuleSnap, &me32))  
        {  
            ::CloseHandle(hModuleSnap);  
            return false;  
        }  
        // 遍历查找指定模块  
        bool isFound = false;  
        do  
        {  
            isFound = (0 == ::_tcsicmp(me32.szModule, ptszDllFile) || 0 == ::_tcsicmp(me32.szExePath, ptszDllFile));  
            if (isFound) // 找到指定模块  
            {  
                break;  
            }  
        } while (TRUE == ::Module32Next(hModuleSnap, &me32));  
        ::CloseHandle(hModuleSnap);  
        if (false == isFound)  
        {  
            return false;  
        }  
        // 获取目标进程句柄  
        hProcess = ::OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION, FALSE, dwProcessId);  
        if (NULL == hProcess)  
        {  
            return false;  
        }  
        // 从 Kernel32.dll 中获取 FreeLibrary 函数地址  
        LPTHREAD_START_ROUTINE lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "FreeLibrary");  
        if (NULL == lpThreadFun)  
        {  
            ::CloseHandle(hProcess);  
            return false;  
        }  
        // 创建远程线程调用 FreeLibrary  
        hThread = ::CreateRemoteThread(hProcess, NULL, 0, lpThreadFun, me32.modBaseAddr /* 模块地址 */, 0, NULL);  
        if (NULL == hThread)  
        {  
            ::CloseHandle(hProcess);  
            return false;  
        }  
        // 等待远程线程结束  
        ::WaitForSingleObject(hThread, INFINITE);  
        // 清理  
        ::CloseHandle(hThread);  
        ::CloseHandle(hProcess);  
        return true;  
    }