Переглянути джерело

新增工程:添加Inject测试工具,用于注入DLL来验证Call劫持的有效性。

Jeff Wang 3 роки тому
батько
коміт
97bd599c3c

+ 116 - 0
Source/Assist/Assist/Assist.cpp

@@ -4,4 +4,120 @@
 #include "stdafx.h"
 #include "Assist.h"
 
+// 8组寄存器存储;
+BYTE byEAX[8] = {0};
+BYTE byEBX[8] = {0};
+BYTE byECX[8] = {0};
+BYTE byEDX[8] = {0};
+BYTE byEBP[8] = {0};
+BYTE byESP[8] = {0};
+BYTE byESI[8] = {0};
+BYTE byEDI[8] = {0};
 
+DWORD dwEAX = 0;
+DWORD dwEBX = 0;
+DWORD dwECX = 0;
+DWORD dwEDX = 0;
+DWORD dwEBP = 0;
+DWORD dwESP = 0;
+DWORD dwESI = 0;
+DWORD dwEDI = 0;
+
+// 新的Call;
+BYTE byNewCall[5] = {0};
+
+// 旧的Call备份;
+BYTE byOldCall[5] = {0};
+
+void __declspec(naked) Call_MySaveAsOutputData()
+{
+    //004AB3FC
+    __asm {
+        // 保存寄存器;
+        mov dwEAX, EAX;
+        mov dwEBX, EBX;
+        mov dwECX, ECX;
+        mov dwEDX, EDX;
+        mov dwEBP, EBP;
+        mov dwESP, ESP;
+        mov dwESI, ESI;
+        mov dwEDI, EDI;
+        // my call
+        mov eax,0x004AB3FC
+        mov dl,1
+        call dword ptr[eax]
+        // 恢复寄存器; 
+        mov EAX, dwEAX;
+        mov EBX, dwEBX;
+        mov ECX, dwECX;
+        mov EDX, dwEDX;
+        mov EBP, dwEBP;
+        mov ESP, dwESP;
+        mov ESI, dwESI;
+        mov EDI, dwEDI;
+        // 返回
+        ret
+    }
+}
+
+
+DWORD dwGoNextAddr = 0x00417B2A;
+void __declspec(naked) MyGo()
+{
+    // 备份寄存器;
+    __asm{
+        // 保存寄存器;
+        mov dwEAX, EAX;
+        mov dwEBX, EBX;
+        mov dwECX, ECX;
+        mov dwEDX, EDX;
+        mov dwEBP, EBP;
+        mov dwESP, ESP;
+        mov dwESI, ESI;
+        mov dwEDI, EDI;
+    }
+
+
+    MessageBox(NULL, _T("MyGo Function"), _T("MyGo"), MB_OK);
+
+
+    __asm{
+        // 恢复寄存器; 
+        mov EAX, dwEAX;
+        mov EBX, dwEBX;
+        mov ECX, dwECX;
+        mov EDX, dwEDX;
+        mov EBP, dwEBP;
+        mov ESP, dwESP;
+        mov ESI, dwESI;
+        mov EDI, dwEDI;
+        // 最后返回原Call地址下一行;
+        jmp dwGoNextAddr;
+    }
+}
+
+// 00417A84
+// 00417B25 | E8 FA9F0E00          | call demo.501B24                        |
+void Call_MyGo()
+{
+    BYTE szMyCall[5] = {0};
+    szMyCall[0] = 0xE9; // 硬编码:jmp或call
+    *(LPDWORD)(&szMyCall[1]) = (DWORD)MyGo - 0x00417B25 - 5;
+
+    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
+    // 将要Hook的地址指令备份下来;
+    if ( !ReadProcessMemory(GetCurrentProcess(), (LPVOID)0x00417B25, byOldCall, 5, NULL) )
+    {
+        MessageBox(NULL, _T("读取内存失败"), _T("提示"),MB_OK);
+        return;
+    }
+
+    // 将我们的Call地址指令写入目标地址;
+    if ( !WriteProcessMemory(hProc, (LPVOID)0x00417B25, szMyCall, 5, NULL) )
+    {
+        MessageBox(NULL, _T("写入内存失败"), _T("提示"),MB_OK);
+        return;
+    }
+
+    MessageBox(NULL, _T("替换成功"), _T("提示"), MB_OK);
+}

+ 2 - 0
Source/Assist/Assist/Assist.rc

@@ -59,6 +59,8 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
     DEFPUSHBUTTON   "È·¶¨",IDOK,205,161,50,14
     PUSHBUTTON      "È¡Ïû",IDCANCEL,259,161,50,14
+    PUSHBUTTON      "SaveAsOutputData",BTN_SAVE_AS_OUTPUT_DATA,19,18,92,14
+    PUSHBUTTON      "MyGo",BTN_GO,27,43,50,14
 END
 
 

+ 12 - 5
Source/Assist/Assist/dllmain.cpp

@@ -3,6 +3,7 @@
 // 斐膘敦諳;
 #include <process.h>
 #include "resource.h"
+#include "Assist.h"
 
 // �擁曹講;
 HMODULE g_hModule = NULL;
@@ -19,6 +20,8 @@ BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserv
     case DLL_PROCESS_ATTACH:
         g_hModule = hModule;
         _beginthread(MyWinThread, 0, NULL);
+        //g_hDlgWnd = CreateDialogParam(g_hModule, MAKEINTRESOURCE(IDD_DLG_ASSIST), NULL, DialogProc, WM_INITDIALOG);
+        //ShowWindow(g_hDlgWnd, SW_SHOW);
     case DLL_THREAD_ATTACH:
     case DLL_THREAD_DETACH:
     case DLL_PROCESS_DETACH:
@@ -29,14 +32,13 @@ BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserv
 
 void __cdecl MyWinThread(LPVOID lpParam)
 {
-    ///Sleep(15000);
     g_hDlgWnd = CreateDialogParam(g_hModule, MAKEINTRESOURCE(IDD_DLG_ASSIST), NULL, DialogProc, NULL);
     ShowWindow(g_hDlgWnd, SW_SHOW);
 
     MSG msg;
     while (GetMessage(&msg, NULL, 0, 0))
     {
-#if 0
+#if 1
         if ( !IsDialogMessage(g_hDlgWnd, &msg) ) // 硌隅敦諳;
         {
             TranslateMessage(&msg);
@@ -60,6 +62,7 @@ BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
         break;
     case WM_CLOSE:
         DestroyWindow(hwndDlg);
+        //EndDialog(hwndDlg, 0);
         break;
     case WM_DESTROY:
         PostQuitMessage(0);
@@ -74,11 +77,15 @@ BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
             {
             case IDOK:
                 MessageBox(hwndDlg, _T("�隅"), _T("等僻"), MB_OK);
-                return 0;
                 break;
             case IDCANCEL:
                 MessageBox(hwndDlg, _T("龰秏"), _T("等僻"), MB_OK);
-                return 0;
+                break;
+            case BTN_SAVE_AS_OUTPUT_DATA:
+                Call_MySaveAsOutputData();
+                break;
+            case BTN_GO:
+                Call_MyGo();
                 break;
             default:
                 break;
@@ -92,5 +99,5 @@ BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
         break;
     }
 
-    return 0;
+    return FALSE;
 }

+ 4 - 1
Source/Assist/Assist/resource.h

@@ -4,6 +4,9 @@
 //
 #define IDD_DIALOG1                     101
 #define IDD_DLG_ASSIST                  101
+#define BTN_SAVE_AS_OUTPUT_DATA         1001
+#define IDC_BUTTON1                     1002
+#define BTN_GO                          1002
 
 // Next default values for new objects
 // 
@@ -11,7 +14,7 @@
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NEXT_RESOURCE_VALUE        102
 #define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_CONTROL_VALUE         1003
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif

+ 20 - 0
Source/InjectDLL/InjectDLL.sln

@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InjectDLL", "InjectDLL\InjectDLL.vcproj", "{F8345D6D-4F75-438E-9989-1B8D8E8F752E}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{F8345D6D-4F75-438E-9989-1B8D8E8F752E}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F8345D6D-4F75-438E-9989-1B8D8E8F752E}.Debug|Win32.Build.0 = Debug|Win32
+		{F8345D6D-4F75-438E-9989-1B8D8E8F752E}.Release|Win32.ActiveCfg = Release|Win32
+		{F8345D6D-4F75-438E-9989-1B8D8E8F752E}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 1098 - 0
Source/InjectDLL/InjectDLL/Global.cpp

@@ -0,0 +1,1098 @@
+#include "StdAfx.h"
+#include "Global.h"
+
+// 获取文件版本号函数头文件;
+#include <WinVer.h>		
+#pragma comment(lib,"version.lib")
+using namespace std;
+#include <psapi.h>
+#pragma comment(lib,"Psapi.lib")
+#include <locale.h>
+#include <io.h>//_access头文件;
+
+TCHAR g_szModulePath[MAX_PATH] = _T("");			// 软件目录;
+TCHAR g_szModuleFileName[MAX_PATH] = _T("");		// 软件名称;
+TCHAR g_szIniFile[MAX_PATH] = _T("");
+
+// 配置文件信息;
+TCHAR g_szServAddress[MAX_PATH] = _T("");		
+DWORD g_dwServPort = 0;		
+TCHAR g_szAccount[MAX_PATH] = _T("");		
+TCHAR g_szPassword[MAX_PATH] = _T("");	
+TCHAR g_szWeChatPath[MAX_PATH] = _T("");		
+TCHAR g_szCacheDir[MAX_PATH] = _T("");		
+TCHAR g_szDynamicLibraryPath[MAX_PATH] = _T("");
+
+// 控制台输出;
+BOOL g_bStdOut = FALSE;
+
+/************************************************************************/
+/*  函数:[1/6/2019 Home];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int GetIniInfo(LPCTSTR lpIniDir /* = NULL */, LPCTSTR lpIniName /* = NULL */)
+{
+	TCHAR szDrive[_MAX_DRIVE] = { 0 };
+	TCHAR szDir[_MAX_DIR] = { 0 };
+	TCHAR szFna[_MAX_DIR] = { 0 };
+	TCHAR szExt[_MAX_DIR] = { 0 };
+	::GetModuleFileName(NULL, g_szModulePath, sizeof(g_szModulePath) / sizeof(TCHAR));
+	_stprintf_s(g_szModuleFileName, _T("%s"), g_szModulePath);
+
+	_tsplitpath_s(g_szModulePath, szDrive, szDir, szFna, szExt);
+	_tcscpy_s(g_szModulePath, szDrive);
+	_tcscat_s(g_szModulePath, szDir);
+
+	// 动态库路径;
+	_stprintf_s(g_szDynamicLibraryPath, _T("%shook.dll"), g_szModulePath);
+#ifdef _DEBUG
+	//_stprintf_s(g_szDynamicLibraryPath, _T("%shook.dll"), _T("E:\\bin\\WeChats2017\\"));
+	WriteTextLog(_T("DLL路径=%s"),g_szDynamicLibraryPath);
+#endif
+
+	if (lpIniDir != NULL && lpIniName != NULL)
+		_stprintf_s(g_szIniFile, _T("%s%s"), lpIniDir, lpIniName);
+	else
+		_stprintf_s(g_szIniFile, _T("%sconfig.ini"), g_szModulePath);
+
+	HANDLE hFile = CreateFile(g_szIniFile, 0/*GENERIC_READ*/, 0, NULL, OPEN_EXISTING, 0, NULL);
+
+	if (ERROR_FILE_NOT_FOUND == GetLastError())
+	{
+		return -1;
+	}
+
+	CloseHandle(hFile);
+	hFile = NULL;
+
+	// 获取服务器端信息;
+	GetPrivateProfileString(_T("ServerInfo"), _T("IP"), _T(""), g_szServAddress, MAX_PATH, g_szIniFile);
+	g_dwServPort = GetPrivateProfileInt(_T("ServerInfo"), _T("Port"), 0, g_szIniFile);
+	GetPrivateProfileString(_T("CustomerInfo"), _T("Account"), _T(""), g_szAccount, MAX_PATH, g_szIniFile);
+	GetPrivateProfileString(_T("CustomerInfo"), _T("Password"), _T(""), g_szPassword, MAX_PATH, g_szIniFile);
+	GetPrivateProfileString(_T("CustomerInfo"), _T("WeChat"), _T(""), g_szWeChatPath, MAX_PATH, g_szIniFile);
+	GetPrivateProfileString(_T("CustomerInfo"), _T("Cache"), _T(""), g_szCacheDir, MAX_PATH, g_szIniFile);
+
+	g_bStdOut = GetPrivateProfileInt(_T("CustomerInfo"), _T("StdOut"), 0, g_szIniFile);
+	if ( g_bStdOut )
+	{
+		AllocConsole();                             // 开辟控制台;
+		SetConsoleTitle(_T("调试输出"));			// 设置控制台窗口标题;
+		freopen("CONOUT$", "w+t", stdout);			// 重定向输出;
+		freopen("CONIN$", "r+t", stdin);			// 重定向输入;
+
+		HWND hWnd = NULL;
+again:
+		hWnd = ::FindWindow(NULL, _T("调试输出"));
+		if( hWnd )
+		{
+			if (!::SetWindowPos(hWnd, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE)) 
+			{
+				_tprintf_s(_T("前置设置失败\n"));
+			}
+			else
+			{
+				_tprintf_s(_T("前置设置成功\n"));
+			}
+		}
+		else
+		{
+			goto again;
+		}
+	}
+
+	return 0;
+}
+
+/************************************************************************/
+/*  函数:[1/6/2019 Home];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+DWORD FindProcess(LPCTSTR lpProName)
+{
+	ASSERT(lpProName!=NULL);
+
+	DWORD dwPID = 0;
+	PROCESSENTRY32 pe32 = { 0 };
+
+	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+	if (hSnapshot == NULL)
+	{
+		return 0;
+	}
+	pe32.dwSize = sizeof(PROCESSENTRY32);
+
+	if (Process32First(hSnapshot, &pe32))
+	{
+		do {
+			if (_tcsicmp(lpProName, pe32.szExeFile) == 0)
+			{
+				dwPID = pe32.th32ProcessID;
+				break;
+			}
+		} while (Process32Next(hSnapshot, &pe32));
+	}
+	CloseHandle(hSnapshot);
+
+	return dwPID;
+}
+
+vector<DWORD> FindAllProcess(LPCTSTR lpProName)
+{
+	ASSERT(lpProName!=NULL);
+
+	vector<DWORD> vtPID;
+	PROCESSENTRY32 pe32 = { 0 };
+
+	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+	if (hSnapshot == NULL)
+		return vector<DWORD>();
+
+	pe32.dwSize = sizeof(PROCESSENTRY32);
+	if (Process32First(hSnapshot, &pe32))
+	{
+		do {
+			if (_tcsicmp(lpProName, pe32.szExeFile) == 0)
+			{
+				vtPID.push_back(pe32.th32ProcessID);
+			}
+		} while (Process32Next(hSnapshot, &pe32));
+	}
+	CloseHandle(hSnapshot);
+
+	return vtPID;
+}
+
+void FindAllProcess(std::vector<ProInfo> &vtProInfo)
+{
+    PROCESSENTRY32 pe32 = { 0 };
+    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+    if (hSnapshot == NULL)
+        return;
+
+    pe32.dwSize = sizeof(PROCESSENTRY32);
+    if (!Process32First(hSnapshot, &pe32))
+        goto end;
+
+    do 
+    {
+        ProInfo proinfo;
+        proinfo.dwProId = pe32.th32ProcessID;
+        proinfo.strProName = pe32.szExeFile;
+        vtProInfo.push_back(proinfo);
+    } while (Process32Next(hSnapshot, &pe32));
+
+end:
+    CloseHandle(hSnapshot);
+}
+
+HANDLE FindModule(LPCTSTR lpModuleName, DWORD dwPID)
+{
+	ASSERT(lpModuleName!=NULL);
+
+	DWORD dwMID = 0;
+	MODULEENTRY32 me32 = { 0 };
+	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, dwPID);
+	if (hSnapshot == NULL)
+		return NULL;
+
+	me32.dwSize = sizeof(PROCESSENTRY32);
+	if (Module32First(hSnapshot, &me32))
+	{
+		do {
+			if (_tcsicmp(lpModuleName, me32.szModule) == 0)
+			{
+				break;
+			}
+		} while (Module32Next(hSnapshot, &me32));
+	}
+	CloseHandle(hSnapshot);
+
+	return me32.hModule;
+}
+
+HANDLE FindModuleEx(LPCTSTR lpModuleName, DWORD dwPid)
+{
+	HMODULE hMods[1024] = {0};
+	DWORD cbNeeded = 0;
+	TCHAR szModName[MAX_PATH];
+	BOOL Wow64Process;
+
+	HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwPid);
+	IsWow64Process(hProcess, &Wow64Process); //判断是32位还是64位进程
+	if ( EnumProcessModulesEx(hProcess, hMods, sizeof(hMods), &cbNeeded, Wow64Process?LIST_MODULES_32BIT:LIST_MODULES_64BIT) )
+	{
+		for (UINT i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
+		{
+			GetModuleFileNameEx(hProcess, hMods[i], szModName, _countof(szModName));
+#ifdef _DEBUG
+			WriteTextLog(_T("目标=%s, 原始=%s, 地址=%p"), szModName, lpModuleName, hMods[i]);
+#endif
+			if (_tcsicmp(lpModuleName, szModName) == 0)
+			{
+				CloseHandle(hProcess);
+				WriteTextLog(_T("【目标=%s, 原始=%s, 地址=%p】"), szModName, lpModuleName, hMods[i]);
+				return hMods[i];
+			}
+		}
+	}
+
+	CloseHandle(hProcess);
+
+	return NULL;
+}
+
+// WINDOWS NT 以上的内核需要提权,才能对系统进行高级管理;
+/************************************************************************/
+/*  函数:[1/6/2019 Home];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+BOOL GetDebugPriv()
+{
+	// 返回的访问令牌指针;
+	HANDLE	hToken;
+	// 接收所返回的制定特权名称的信息;
+	LUID	sedebugnameValue;
+	// 新特权信息的指针(结构体);
+	TOKEN_PRIVILEGES tkp;
+	//DWORD	dwCurProcId = GetCurrentProcessId();
+	// 要修改访问权限的进程句柄;
+	HANDLE	hCurProc = ::GetCurrentProcess();
+	//hCurProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwCurProcId);
+
+	if (!::OpenProcessToken(hCurProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+	{
+		return FALSE;
+	}
+
+	if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
+	{
+		CloseHandle(hToken);
+		return FALSE;
+	}
+
+	tkp.PrivilegeCount = 1;
+	tkp.Privileges[0].Luid = sedebugnameValue;
+	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+	if (!::AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL))
+	{
+		CloseHandle(hToken);
+		return FALSE;
+	}
+
+	CloseHandle(hCurProc);
+	CloseHandle(hToken);
+	return TRUE;
+}
+
+/************************************************************************/
+/* 
+	函数:GetFileVersion
+	描述:获取可执行文件的文件版号;
+	参数:
+	hModule[IN]		可执行文件模块句柄;
+	dwArray[OUT]	返回的文件版本号;
+	返回:
+	成功返回TRUE,失败返回FALSE;
+	注意:
+	当hModule为空时,表示要获取的可执行文件为本程序的文件版本号;
+*/
+/************************************************************************/
+BOOL GetFileVersion( IN HMODULE hModule, OUT DWORD (&dwArray)[4])
+{
+	TCHAR fname[MAX_PATH];
+	VS_FIXEDFILEINFO *pVi;
+	DWORD dwHandle;
+
+	if ( GetModuleFileName(hModule, fname, MAX_PATH))
+	{
+		INT nSize = GetFileVersionInfoSize(fname, &dwHandle);
+
+		if (nSize > 0)
+		{
+			BYTE *pBuffer = new BYTE[nSize];
+			memset(pBuffer, 0, nSize);
+
+			if (GetFileVersionInfo(fname, dwHandle, nSize, pBuffer))
+			{
+				if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
+				{
+					dwArray[0] = HIWORD(pVi->dwFileVersionMS);
+					dwArray[1] = LOWORD(pVi->dwFileVersionMS);
+					dwArray[2] = HIWORD(pVi->dwFileVersionLS);
+					dwArray[3] = LOWORD(pVi->dwFileVersionLS);
+
+					delete[]pBuffer;
+					return TRUE;
+				}
+			}
+
+			if ( pBuffer )
+				delete[]pBuffer;
+		}
+	}
+
+	return FALSE;
+}
+
+/************************************************************************/
+/* 
+	函数:GetFileVersion
+	描述:获取可执行文件的文件版号;
+	参数:
+	lpFileName[IN]	可执行文件名全路径;
+	dwArray[OUT]	返回的文件版本号;
+	返回:
+	成功返回TRUE,失败返回FALSE;
+	注意:
+*/
+/************************************************************************/
+BOOL GetFileVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] )
+{
+	if ( lpFileName == NULL || !PathFileExists(lpFileName) )
+	{
+		OutputDebugString(_T("文件名错误或文件不存在\n"));
+		return FALSE;
+	}
+
+	DWORD dwHandle = 0;
+	VS_FIXEDFILEINFO *pVi = NULL;
+	INT nSize = GetFileVersionInfoSize(lpFileName, &dwHandle);
+	if ( nSize > 0 )
+	{
+		BYTE *pBuffer = new BYTE[nSize];
+		memset(pBuffer, 0, nSize);
+
+		if ( GetFileVersionInfo(lpFileName, dwHandle, nSize, pBuffer) )
+		{
+			if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
+			{
+				dwArray[0] = HIWORD(pVi->dwFileVersionMS);
+				dwArray[1] = LOWORD(pVi->dwFileVersionMS);
+				dwArray[2] = HIWORD(pVi->dwFileVersionLS);
+				dwArray[3] = LOWORD(pVi->dwFileVersionLS);
+
+				if (pBuffer)
+					delete[]pBuffer;
+				return TRUE;
+			}
+		}
+
+		if (pBuffer)
+			delete[]pBuffer;
+	}
+
+	return FALSE;
+}
+
+/************************************************************************/
+/* 
+	函数:GetProductVersion
+	描述:获取可执行文件的产品版号;
+	参数:
+	hModule[IN]		可执行文件模块句柄;
+	dwArray[OUT]	返回的产品版本号;
+	返回:
+	成功返回TRUE,失败返回FALSE;
+	注意:
+	当hModule为空时,表示要获取的可执行文件为本程序的产品版本号;
+*/
+/************************************************************************/
+BOOL GetProductVersion(IN HMODULE hModule, IN DWORD (&dwArray)[4] )
+{
+	TCHAR fname[MAX_PATH];
+	VS_FIXEDFILEINFO *pVi;
+	DWORD dwHandle;
+
+	if (::GetModuleFileName(hModule, fname, MAX_PATH))
+	{
+		INT nSize = GetFileVersionInfoSize(fname, &dwHandle);
+
+		if (nSize > 0)
+		{
+			BYTE *pBuffer = new BYTE[nSize];
+			memset(pBuffer, 0, nSize);
+
+			if (GetFileVersionInfo(fname, dwHandle, nSize, pBuffer))
+			{
+				if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
+				{
+					dwArray[0] = HIWORD(pVi->dwProductVersionMS);
+					dwArray[1] = LOWORD(pVi->dwProductVersionMS);
+					dwArray[2] = HIWORD(pVi->dwProductVersionLS);
+					dwArray[3] = LOWORD(pVi->dwProductVersionLS);
+
+					if(pBuffer)
+						delete[]pBuffer;
+					return TRUE;
+				}
+			}
+			if(pBuffer)
+				delete[]pBuffer;
+		}
+	}
+
+	return FALSE;
+}
+
+/************************************************************************/
+/* 
+	函数:GetProductVersion
+	描述:获取可执行文件的产品版号;
+	参数:
+	lpFileName[IN]	可执行文件名全路径;
+	dwArray[OUT]	返回的产品版本号;
+	返回:
+	成功返回TRUE,失败返回FALSE;
+	注意:
+*/
+/************************************************************************/
+BOOL GetProductVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] )
+{
+	if ( lpFileName == NULL || !PathFileExists(lpFileName) )
+	{
+		OutputDebugString(_T("文件名错误或文件不存在\n"));
+		return FALSE;
+	}
+
+	DWORD dwHandle = 0;
+	VS_FIXEDFILEINFO *pVi = NULL;
+	INT nSize = GetFileVersionInfoSize(lpFileName, &dwHandle);
+	if ( nSize > 0 )
+	{
+		BYTE *pBuffer = new BYTE[nSize];
+		memset(pBuffer, 0, nSize);
+
+		if ( GetFileVersionInfo(lpFileName, dwHandle, nSize, pBuffer) )
+		{
+			if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
+			{
+				dwArray[0] = HIWORD(pVi->dwProductVersionMS);
+				dwArray[1] = LOWORD(pVi->dwProductVersionMS);
+				dwArray[2] = HIWORD(pVi->dwProductVersionLS);
+				dwArray[3] = LOWORD(pVi->dwProductVersionLS);
+
+				if (pBuffer)
+					delete[]pBuffer;
+				return TRUE;
+			}
+		}
+
+		if (pBuffer)
+			delete[]pBuffer;
+	}
+
+	return FALSE;
+}
+
+/************************************************************************/
+/*  函数:WriteTextLog[7/28/2016 IT];
+/*  描述:写文本日志;
+/*  参数:;
+/*  	[IN] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void WriteTextLog(const TCHAR *format, ...)
+{
+#if 0
+	try
+	{
+		//static ThreadSection _critSection;
+		//AutoThreadSection aSection(&_critSection);
+		// 解析出日志路径;
+		TCHAR szlogpath[MAX_PATH] = {0};
+		static TCHAR szModulePath[MAX_PATH] = {0};
+		static TCHAR szFna[_MAX_DIR] = { 0 };
+		if ( szModulePath[0] == _T('\0') )
+		{
+			TCHAR szDrive[_MAX_DRIVE] = { 0 };
+			TCHAR szDir[_MAX_DIR] = { 0 };
+			TCHAR szExt[_MAX_DIR] = { 0 };
+			::GetModuleFileName(NULL, szModulePath, sizeof(szModulePath) / sizeof(TCHAR));
+			_tsplitpath_s(szModulePath, szDrive, szDir, szFna, szExt);
+			_tcscpy_s(szModulePath, szDrive);
+			_tcscat_s(szModulePath, szDir);
+		}
+
+		_stprintf_s(szlogpath, _T("%s日志\\%s%s.txt"), szModulePath, szFna, CTime::GetCurrentTime().Format("[%Y-%m-%d]"));
+
+		// 打开或创建文件;
+		CStdioFile fp;
+		if (PathFileExists(szlogpath))
+		{
+			if (fp.Open(szlogpath, CFile::modeWrite) == FALSE)
+			{
+				return;
+			}
+			fp.SeekToEnd();
+		}
+		else
+		{
+			fp.Open(szlogpath, CFile::modeCreate | CFile::modeWrite);
+		}
+
+		// 格式化前设置语言区域;
+		TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
+		_tsetlocale(LC_CTYPE, _T("chs"));//设定中文;
+
+		// 格式化日志内容;
+		va_list		args = NULL;
+		int			len = 0;
+		TCHAR		*buffer = NULL;
+		va_start( args, format );
+		// _vscprintf doesn't count. terminating '\0'
+		len = _vsctprintf( format, args )  + 1;
+		buffer = (TCHAR*)malloc( len * sizeof(TCHAR) );
+		_vstprintf_s( buffer, len, format, args ); // C4996
+		// Note: vsprintf is deprecated; consider using vsprintf_s instead
+
+		// 将日志内容输入到文件中;
+		fp.WriteString( CTime::GetCurrentTime().Format(_T("%Y-%m-%d %H:%M:%S ")) );
+		fp.WriteString(buffer);
+		fp.WriteString(_T("\n"));
+
+		// 关闭文件,释放资源并设置回原语言区域;
+		free( buffer );
+		_tsetlocale(LC_CTYPE, old_locale);
+		free(old_locale);//还原区域设定;
+		fp.Close();
+	}
+	catch (CException *e)
+	{
+		e->ReportError();
+		e->Delete();
+	}
+#else
+	// 解析出日志路径;
+	TCHAR szlogpath[MAX_PATH] = { 0 };
+	static TCHAR szModulePath[MAX_PATH] = { 0 };
+	static TCHAR szFna[MAX_PATH] = { 0 };
+	if (szModulePath[0] == _T('\0'))
+	{
+		TCHAR szDrive[MAX_PATH] = { 0 };
+		TCHAR szDir[MAX_PATH] = { 0 };
+		TCHAR szExt[MAX_PATH] = { 0 };
+		::GetModuleFileName(NULL, szModulePath, sizeof(szModulePath) / sizeof(TCHAR));
+		_tsplitpath_s(szModulePath, szDrive, szDir, szFna, szExt);
+		_tcscpy_s(szModulePath, szDrive);
+		_tcscat_s(szModulePath, szDir);
+	}
+
+	_stprintf_s(szlogpath, _T("%s%s.txt"), szModulePath, szFna);
+	// 打开或创建文件;
+	FILE *fp = NULL;
+	//if (_taccess(szlogpath, 0) != -1)
+#ifndef UNICODE
+	if (_access(szlogpath, 0) != -1)
+#else
+	if (_taccess(szlogpath, 0) != -1)
+#endif
+	{// 存在;
+		fp = _tfopen(szlogpath, _T("a+"));
+		// 移动到末尾;
+		fseek(fp, 0, SEEK_END);
+	}
+	else
+	{// 不存在;
+		fp = _tfopen(szlogpath, _T("w+"));
+	}
+
+	if (fp == NULL)
+		return;
+
+	// 格式化前设置语言区域;
+	TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
+	_tsetlocale(LC_CTYPE, _T("chs"));//设定中文;
+
+	// 格式化日志内容;
+	va_list		args = NULL;
+	int			len = 0;
+	TCHAR		*buffer = NULL;
+	va_start(args, format);
+	// _vscprintf doesn't count. terminating '\0'
+	len = _vsctprintf(format, args) + 1;
+	buffer = (TCHAR*)malloc(len * sizeof(TCHAR));
+	_vstprintf_s(buffer, len, format, args);
+	// 将日志内容输入到文件中;
+	// 获取今年年份;
+	__time64_t gmt = time(NULL);// 获取当前日历时间(1900-01-01开始的Unix时间戳);
+	struct tm gmtm = { 0 };
+	localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
+	_ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year + 1990, gmtm.tm_mon + 1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, buffer);
+
+	// 关闭文件,释放资源并设置回原语言区域;
+	free(buffer);
+	fclose(fp);
+	_tsetlocale(LC_CTYPE, old_locale);
+	free(old_locale);//还原区域设定;
+#endif
+}
+
+
+//---------------------------------------------------------------------
+// add by Jeff 2014.10.27
+// 函数:全局函数IsDirectoryLegitimate,多字节版本,非UNICODE
+// 描述:判断一个目录路径字符串,是否属于合法的、可创建的目录路径。
+// 参数:strDirectory 被验证的路径字符串;
+//		
+// 返回:合法路径返回TRUE;
+//---------------------------------------------------------------------
+BOOL IsDirectoryLegitimate(const CString &strDirectory)
+{
+	if (strDirectory.Find('/') != -1 ||
+		strDirectory.Find('\\') != -1 ||
+		strDirectory.Find(':') != -1 ||
+		strDirectory.Find('*') != -1 ||
+		strDirectory.Find('?') != -1 ||
+		strDirectory.Find('\"') != -1 ||
+		strDirectory.Find('>') != -1 ||
+		strDirectory.Find('<') != -1 ||
+		strDirectory.Find('|') != -1
+		)
+		return FALSE;
+
+	return TRUE;
+}
+
+
+//--------------------------------------------------------------------------------
+// Jeff add 2014.06.23;
+// 函数:ErrorExit
+// 描述:
+// 参数:
+//     lpszFunction:函数名;
+//     dwError:错误码; 
+//
+//--------------------------------------------------------------------------------
+void ShowSystemErrorInfo(CString strDescription, const DWORD &dwError)
+{
+#if 1
+	LPVOID lpMsgBuf;
+
+	BOOL fOk = FormatMessage(
+		FORMAT_MESSAGE_ALLOCATE_BUFFER |
+		FORMAT_MESSAGE_FROM_SYSTEM |
+		FORMAT_MESSAGE_IGNORE_INSERTS,
+		NULL,
+		dwError,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPTSTR)&lpMsgBuf,
+		0, NULL);
+
+	if (!fOk)
+	{
+		// Is it a network-related error?
+		HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
+
+		if (hDll != NULL)
+		{
+			FormatMessage(
+				FORMAT_MESSAGE_FROM_HMODULE |
+				FORMAT_MESSAGE_FROM_SYSTEM |
+				FORMAT_MESSAGE_IGNORE_INSERTS,
+				hDll,
+				dwError,
+				MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+				(LPTSTR)&lpMsgBuf,
+				0,
+				NULL);
+
+			FreeLibrary(hDll);
+		}
+	}
+
+	if (lpMsgBuf != NULL)
+	{
+		CString strDisplay;
+		strDisplay.Format(_T("%s.错误码=%d,Windows描述:%s"), strDescription, dwError, (PCTSTR)LocalLock(lpMsgBuf));
+		//WriteLog(strDisplay);
+		LocalFree(lpMsgBuf);
+	}
+	else
+	{
+		//WriteLog(strDescription);
+	}
+#else
+	HLOCAL hlocal = NULL;   // Buffer that gets the error message string
+
+	// Get the error code's textual description
+	BOOL fOk = FormatMessage(
+		FORMAT_MESSAGE_FROM_SYSTEM |
+		FORMAT_MESSAGE_ALLOCATE_BUFFER |
+		FORMAT_MESSAGE_IGNORE_INSERTS,
+		NULL,
+		dwError,
+		MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+		(PTSTR)&hlocal,
+		0,
+		NULL);
+
+	if (!fOk)
+	{
+		// Is it a network-related error?
+		HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
+
+		if (hDll != NULL)
+		{
+			FormatMessage(
+				FORMAT_MESSAGE_FROM_HMODULE |
+				FORMAT_MESSAGE_FROM_SYSTEM |
+				FORMAT_MESSAGE_IGNORE_INSERTS,
+				hDll,
+				dwError,
+				MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+				(PTSTR)&hlocal,
+				0,
+				NULL);
+			FreeLibrary(hDll);
+		}
+	}
+
+	if (hlocal != NULL)
+	{
+		CString strDisplay;
+		strDisplay.Format("%s 失败错误码=%d,Windows系统描述:%s", strDescription, dwError, (PCTSTR)LocalLock(hlocal));
+		//WriteLog(strDisplay);
+		LocalFree(hlocal);
+	}
+	else
+	{
+		//WriteLog("Error number not found.");
+	}
+#endif
+
+}
+
+// The system displays a dialog box with a custom message and a message to the user to close applications within the specified time-out interval (30 seconds). 
+// After the time-out interval elapses, the system is restarted.
+//The application must enable the SE_SHUTDOWN_NAME privilege before calling InitiateSystemShutdown
+BOOL MySystemShutdown(LPTSTR lpMsg)
+{
+	HANDLE hToken;              // handle to process token 
+	TOKEN_PRIVILEGES tkp;       // pointer to token structure 
+
+	BOOL fResult;               // system shutdown flag 
+
+	// Get the current process token handle so we can get shutdown 
+	// privilege. 
+
+	if (!OpenProcessToken(GetCurrentProcess(),
+		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+		return FALSE;
+
+	// Get the LUID for shutdown privilege. 
+
+	LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
+		&tkp.Privileges[0].Luid);
+
+	tkp.PrivilegeCount = 1;  // one privilege to set    
+	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+	// Get shutdown privilege for this process. 
+
+	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+		(PTOKEN_PRIVILEGES)NULL, 0);
+
+	// Cannot test the return value of AdjustTokenPrivileges. 
+
+	if (GetLastError() != ERROR_SUCCESS)
+		return FALSE;
+
+	// Display the shutdown dialog box and start the countdown. 
+
+	fResult = InitiateSystemShutdown(
+		NULL,    // shut down local computer 
+		lpMsg,   // message for user
+		30,      // time-out period, in seconds 
+		FALSE,   // ask user to close apps 
+		TRUE);   // reboot after shutdown 
+
+	if (!fResult)
+		return FALSE;
+
+	// Disable shutdown privilege. 
+
+	tkp.Privileges[0].Attributes = 0;
+	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+		(PTOKEN_PRIVILEGES)NULL, 0);
+
+	return TRUE;
+}
+
+// If the AbortSystemShutdown function is executed in the time-out period specified by InitiateSystemShutdown, 
+// the system does not shut down. For example, if PreventSystemShutdown is called after MySystemShutdown, 
+// the system closes the dialog box and does not restart the system.
+BOOL PreventSystemShutdown()
+{
+	HANDLE hToken;              // handle to process token 
+	TOKEN_PRIVILEGES tkp;       // pointer to token structure 
+
+	// Get the current process token handle  so we can get shutdown 
+	// privilege. 
+
+	if (!OpenProcessToken(GetCurrentProcess(),
+		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+		return FALSE;
+
+	// Get the LUID for shutdown privilege. 
+
+	LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
+		&tkp.Privileges[0].Luid);
+
+	tkp.PrivilegeCount = 1;  // one privilege to set    
+	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+	// Get shutdown privilege for this process. 
+
+	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+		(PTOKEN_PRIVILEGES)NULL, 0);
+
+	if (GetLastError() != ERROR_SUCCESS)
+		return FALSE;
+
+	// Prevent the system from shutting down. 
+
+	if (!AbortSystemShutdown(NULL))
+		return FALSE;
+
+	// Disable shutdown privilege. 
+
+	tkp.Privileges[0].Attributes = 0;
+	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+		(PTOKEN_PRIVILEGES)NULL, 0);
+
+	return TRUE;
+}
+
+// Shutting down flushes file buffers to disk and brings the system to a condition in which it is safe to turn off the computer
+// The application must first enable the SE_SHUTDOWN_NAME privilege. 
+// The final parameter in the call to ExitWindowsEx indicates that the system was shut down for a planning update of the operating system.
+BOOL MySystemShutdown()
+{
+	HANDLE hToken;
+	TOKEN_PRIVILEGES tkp;
+
+	// Get a token for this process. 
+
+	if (!OpenProcessToken(GetCurrentProcess(),
+		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+		return(FALSE);
+
+	// Get the LUID for the shutdown privilege. 
+
+	LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
+		&tkp.Privileges[0].Luid);
+
+	tkp.PrivilegeCount = 1;  // one privilege to set    
+	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+	// Get the shutdown privilege for this process. 
+
+	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+		(PTOKEN_PRIVILEGES)NULL, 0);
+
+	if (GetLastError() != ERROR_SUCCESS)
+		return FALSE;
+
+	// Shut down the system and force all applications to close. 
+
+	if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE,
+		SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
+		SHTDN_REASON_MINOR_UPGRADE |
+		SHTDN_REASON_FLAG_PLANNED))
+		return FALSE;
+
+	return TRUE;
+}
+
+BOOL GetWeChatPath()
+{
+	// 通过注册表获取微信安装目录;
+	HKEY hKey = NULL;
+	if(ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, _T("Software\\Tencent\\WeChat"), &hKey))
+	{
+		return FALSE;
+	}
+
+	DWORD Type = REG_SZ;
+	DWORD cbData = MAX_PATH*sizeof(WCHAR);
+	if(ERROR_SUCCESS != RegQueryValueEx(hKey, _T("InstallPath"), 0, &Type, (LPBYTE)g_szWeChatPath, &cbData))
+	{
+		RegCloseKey(hKey);
+		return FALSE;
+	}
+
+	PathAppend(g_szWeChatPath, _T("WeChat.exe"));
+
+	return TRUE;
+}
+
+BOOL OpenWeChat()
+{
+	STARTUPINFO si;
+	PROCESS_INFORMATION pi;
+	ZeroMemory(&si, sizeof(si));
+	si.cb = sizeof(si);
+	ZeroMemory(&pi, sizeof(pi));
+
+	si.dwFlags = STARTF_USESHOWWINDOW;		// 指定wShowWindow成员有效
+	si.wShowWindow = SW_HIDE;				// 设置创建进程时,窗口不显示,
+	// 为FALSE的话则不显示
+	BOOL bRet = ::CreateProcess (
+		g_szWeChatPath,		// 不在此指定可执行文件的文件名
+		NULL,				// 命令行参数
+		NULL,				// 默认进程安全性
+		NULL,				// 默认线程安全性
+		FALSE,				// 指定当前进程内的句柄不可以被子进程继承
+		NULL,
+		NULL,				// 使用本进程的环境变量
+		NULL,				// 使用本进程的驱动器和目录
+		&si,
+		&pi);
+
+	if(bRet)
+	{
+		// 进程挂起后,仍能成功注入dll;
+// 		TCHAR szDllPath[MAX_PATH];
+// 		ZeroMemory(szDllPath,MAX_PATH);
+// 		_stprintf_s(szDllPath, _T("%shook.dll"), g_szModulePath);
+// 		for (int i = 0; i < 10; i++)
+// 		{
+// 			CInjection inject(pi.dwProcessId,szDllPath);
+// 			inject.InjectDynamicLibrary();
+// 			inject.EjectDynamicLibrary();
+// 		}
+
+		// 既然我们不使用两个句柄,最好是立刻将它们关闭
+		::CloseHandle (pi.hThread);
+		::CloseHandle (pi.hProcess);
+
+		// 当进程挂起时,是无法修改关闭微信句柄;
+		//PatchWeChat();
+	}
+
+	return TRUE;
+}
+
+BOOL OpenWeChat2()
+{
+	SHELLEXECUTEINFO sei;
+	memset(&sei, 0, sizeof(SHELLEXECUTEINFO));
+	sei.cbSize = sizeof(SHELLEXECUTEINFO);
+	sei.hwnd = NULL;
+	sei.lpVerb = _T("open");
+	//sei.lpVerb = _T("runas");
+	//sei.fMask = SEE_MASK_NOCLOSEPROCESS;
+	sei.lpFile = g_szWeChatPath;
+	sei.lpParameters = NULL;
+	sei.lpDirectory = NULL;
+	sei.nShow = SW_NORMAL;
+	sei.hInstApp = NULL;
+
+	if (!ShellExecuteEx(&sei))
+	{
+		DWORD dw = GetLastError();
+		return FALSE;
+	}
+//PatchWeChat();
+
+	return TRUE;
+}
+
+BOOL OpenWeChatAndSuspended()
+{
+	STARTUPINFO si;
+	PROCESS_INFORMATION pi;
+	ZeroMemory(&si, sizeof(si));
+	si.cb = sizeof(si);
+	ZeroMemory(&pi, sizeof(pi));
+
+	si.dwFlags = STARTF_USESHOWWINDOW;  // 指定wShowWindow成员有效
+	si.wShowWindow = TRUE;				// 此成员设为TRUE的话则显示新建进程的主窗口,
+	// 为FALSE的话则不显示
+	BOOL bRet = ::CreateProcess(
+		g_szWeChatPath,		// 不在此指定可执行文件的文件名
+		NULL,				// 命令行参数
+		NULL,				// 默认进程安全性
+		NULL,				// 默认线程安全性
+		FALSE,				// 指定当前进程内的句柄不可以被子进程继承
+		CREATE_SUSPENDED,	// 挂起进程;CREATE_SUSPENDED
+		NULL,				// 使用本进程的环境变量
+		NULL,				// 使用本进程的驱动器和目录
+		&si,
+		&pi);
+
+	if (bRet)
+	{
+		// 进程挂起后,仍能成功注入dll;
+// 		TCHAR szDllPath[MAX_PATH];
+// 		ZeroMemory(szDllPath,MAX_PATH);
+// 		_stprintf_s(szDllPath, _T("%shook.dll"), g_szModulePath);
+// 		for (int i = 0; i < 10; i++)
+// 		{
+// 			CInjection inject(pi.dwProcessId,szDllPath);
+// 			inject.InjectDynamicLibrary();
+// 			inject.EjectDynamicLibrary();
+// 		}
+
+		//不sleep就会出现读取不到的297错误
+		//Sleep(5000);				
+
+		//获取线程上下文
+ 		CONTEXT ct = { 0 };
+ 		ct.ContextFlags = CONTEXT_CONTROL;
+ 		GetThreadContext(pi.hThread, &ct);
+
+ 		::ResumeThread(pi.hThread);	
+
+		// 既然我们不使用两个句柄,最好是立刻将它们关闭
+		::CloseHandle(pi.hThread);
+		::CloseHandle(pi.hProcess);
+
+		// 当进程挂起时,是无法修改关闭微信句柄;
+		//PatchWeChat();
+	}
+
+
+	return TRUE;
+}

+ 73 - 0
Source/InjectDLL/InjectDLL/Global.h

@@ -0,0 +1,73 @@
+#ifndef __GLOBAL_WECHAT__
+#define __GLOBAL_WECHAT__
+
+#include <tlhelp32.h>
+#include <vector>
+#include <string>
+using namespace std;
+
+#ifdef UNICODE
+typedef wstring TString;
+#else
+typedef string TString;
+#endif
+
+#define WECHAT _T("WeChat.exe")
+#define OGC_TOOL _T("Demo.exe")
+
+
+typedef struct __PROCINFO__
+{
+    DWORD   dwProId;        // 进程id;
+    TString strProName;     // 进程名称;
+    TString strProFile;     // 进程路径;
+}ProInfo, *pProInfo;
+
+// 全局变量;
+extern TCHAR g_szModulePath[MAX_PATH];			// 软件目录;
+extern TCHAR g_szModuleFileName[MAX_PATH];		// 软件名称;
+extern TCHAR g_szIniFile[MAX_PATH];
+
+// 配置文件信息;
+extern TCHAR g_szServAddress[MAX_PATH];		
+extern DWORD g_dwServPort;					
+extern TCHAR g_szAccount[MAX_PATH];			
+extern TCHAR g_szPassword[MAX_PATH];		
+extern TCHAR g_szWeChatPath[MAX_PATH];		
+extern TCHAR g_szCacheDir[MAX_PATH];	
+extern TCHAR g_szDynamicLibraryPath[MAX_PATH];
+
+
+// 控制台输出;
+extern BOOL g_bStdOut;
+
+extern int GetIniInfo(LPCTSTR lpIniDir = NULL, LPCTSTR lpIniName = NULL);
+extern DWORD FindProcess(LPCTSTR lpProName);
+extern vector<DWORD> FindAllProcess(LPCTSTR lpProName);
+extern void FindAllProcess(std::vector<ProInfo> &vtProInfo);
+extern HANDLE FindModule(LPCTSTR lpModuleName, DWORD dwPID);
+extern HANDLE FindModuleEx(LPCTSTR lpModuleName, DWORD dwPid);
+extern BOOL GetDebugPriv();
+
+extern BOOL GetFileVersion( IN HMODULE hModule, IN DWORD (&dwArray)[4]);
+extern BOOL GetFileVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] );
+extern BOOL GetProductVersion( IN HMODULE hModule, IN DWORD (&dwArray)[4]);
+extern BOOL GetProductVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] );
+
+extern BOOL GetOSDisplayString(LPTSTR pszOS);
+extern void WriteTextLog(const TCHAR *format, ...);
+extern BOOL CopyFileEx(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, const BOOL &bFailIfExists=TRUE);
+extern void tSplitpath(const char *path, char *drive, char *dir, char *fname, char *ext);
+extern void tSplitpath(const char *path, char *drive, char *dir, const int &nTimes);
+extern BOOL IsDirectoryLegitimate(const CString &strDirectory);
+extern void ShowSystemErrorInfo(CString strDescription, const DWORD &dwError);
+extern BOOL MySystemShutdown(LPTSTR lpMsg);
+extern BOOL PreventSystemShutdown();
+extern BOOL MySystemShutdown();
+
+
+//////////////////////////////////////////////////////////////////////////
+extern BOOL GetWeChatPath();
+extern BOOL OpenWeChat();
+
+#endif

+ 79 - 0
Source/InjectDLL/InjectDLL/InjectDLL.cpp

@@ -0,0 +1,79 @@
+
+// InjectDLL.cpp : 定义应用程序的类行为。
+//
+
+#include "stdafx.h"
+#include "InjectDLL.h"
+#include "InjectDLLDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CInjectDLLApp
+
+BEGIN_MESSAGE_MAP(CInjectDLLApp, CWinAppEx)
+	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+
+// CInjectDLLApp 构造
+
+CInjectDLLApp::CInjectDLLApp()
+{
+	// TODO: 在此处添加构造代码,
+	// 将所有重要的初始化放置在 InitInstance 中
+}
+
+
+// 唯一的一个 CInjectDLLApp 对象
+
+CInjectDLLApp theApp;
+
+
+// CInjectDLLApp 初始化
+
+BOOL CInjectDLLApp::InitInstance()
+{
+	// 如果一个运行在 Windows XP 上的应用程序清单指定要
+	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
+	//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
+	INITCOMMONCONTROLSEX InitCtrls;
+	InitCtrls.dwSize = sizeof(InitCtrls);
+	// 将它设置为包括所有要在应用程序中使用的
+	// 公共控件类。
+	InitCtrls.dwICC = ICC_WIN95_CLASSES;
+	InitCommonControlsEx(&InitCtrls);
+
+	CWinAppEx::InitInstance();
+
+	AfxEnableControlContainer();
+
+	// 标准初始化
+	// 如果未使用这些功能并希望减小
+	// 最终可执行文件的大小,则应移除下列
+	// 不需要的特定初始化例程
+	// 更改用于存储设置的注册表项
+	// TODO: 应适当修改该字符串,
+	// 例如修改为公司或组织名
+	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
+
+	CInjectDLLDlg dlg;
+	m_pMainWnd = &dlg;
+	INT_PTR nResponse = dlg.DoModal();
+	if (nResponse == IDOK)
+	{
+		// TODO: 在此放置处理何时用
+		//  “确定”来关闭对话框的代码
+	}
+	else if (nResponse == IDCANCEL)
+	{
+		// TODO: 在此放置处理何时用
+		//  “取消”来关闭对话框的代码
+	}
+
+	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
+	//  而不是启动应用程序的消息泵。
+	return FALSE;
+}

+ 32 - 0
Source/InjectDLL/InjectDLL/InjectDLL.h

@@ -0,0 +1,32 @@
+
+// InjectDLL.h : PROJECT_NAME 应用程序的主头文件
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
+#endif
+
+#include "resource.h"		// 主符号
+
+
+// CInjectDLLApp:
+// 有关此类的实现,请参阅 InjectDLL.cpp
+//
+
+class CInjectDLLApp : public CWinAppEx
+{
+public:
+	CInjectDLLApp();
+
+// 重写
+	public:
+	virtual BOOL InitInstance();
+
+// 实现
+
+	DECLARE_MESSAGE_MAP()
+};
+
+extern CInjectDLLApp theApp;

+ 207 - 0
Source/InjectDLL/InjectDLL/InjectDLL.rc

@@ -0,0 +1,207 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// 中文(中华人民共和国) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+#ifdef _WIN32
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
+#pragma code_page(936)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#ifndef APSTUDIO_INVOKED\r\n"
+    "#include ""targetver.h""\r\n"
+    "#endif\r\n"
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+    "#define _AFX_NO_OLE_RESOURCES\r\n"
+    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+    "\r\n"
+    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
+    "LANGUAGE 4, 2\r\n"
+    "#pragma code_page(936)\r\n"
+    "#include ""res\\InjectDLL.rc2""  // 非 Microsoft Visual C++ 编辑的资源\r\n"
+    "#include ""l.CHS\\afxres.rc""      // 标准组件\r\n"
+    "#endif\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME           ICON                    "res\\InjectDLL.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "关于 InjectDLL"
+FONT 9, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
+    LTEXT           "InjectDLL,1.0 版",IDC_STATIC,42,14,114,8,SS_NOPREFIX
+    LTEXT           "Copyright (C) 2022",IDC_STATIC,42,26,114,8
+    DEFPUSHBUTTON   "确定",IDOK,113,41,50,14,WS_GROUP
+END
+
+IDD_INJECTDLL_DIALOG DIALOGEX 0, 0, 319, 106
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "InjectDLL"
+FONT 9, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+    DEFPUSHBUTTON   "确定",IDOK,209,85,50,14
+    PUSHBUTTON      "取消",IDCANCEL,262,85,50,14
+    LTEXT           "选择要注入的进程 :",IDC_STATIC,10,21,65,8
+    COMBOBOX        COMBO_PROCESS,74,19,187,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+    PUSHBUTTON      "注入DLL",BTN_INJECT,97,42,50,14
+    PUSHBUTTON      "卸载DLL",BTN_EJECT,162,42,50,14
+    PUSHBUTTON      "刷新",BTN_REFLESH,264,17,46,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "080403a8"
+        BEGIN
+            VALUE "CompanyName", "TODO: <公司名>"
+            VALUE "FileDescription", "TODO: <文件说明>"
+            VALUE "FileVersion", "1.0.0.1"
+            VALUE "InternalName", "InjectDLL.exe"
+            VALUE "LegalCopyright", "TODO: (C) <公司名>。保留所有权利。"
+            VALUE "OriginalFilename", "InjectDLL.exe"
+            VALUE "ProductName", "TODO: <产品名>"
+            VALUE "ProductVersion", "1.0.0.1"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x804, 936
+    END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO 
+BEGIN
+    IDD_ABOUTBOX, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 163
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 55
+    END
+
+    IDD_INJECTDLL_DIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 312
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 99
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE 
+BEGIN
+    IDS_ABOUTBOX            "关于 InjectDLL(&A)..."
+END
+
+#endif    // 中文(中华人民共和国) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+#include "res\InjectDLL.rc2"  // 非 Microsoft Visual C++ 编辑的资源
+#include "l.CHS\afxres.rc"      // 标准组件
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+

+ 288 - 0
Source/InjectDLL/InjectDLL/InjectDLL.vcproj

@@ -0,0 +1,288 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="InjectDLL"
+	ProjectGUID="{F8345D6D-4F75-438E-9989-1B8D8E8F752E}"
+	RootNamespace="InjectDLL"
+	Keyword="MFCProj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="true"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="true"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG"
+				MinimalRebuild="false"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\Global.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\InjectDLL.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\InjectDLLDlg.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Injection.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\Global.h"
+				>
+			</File>
+			<File
+				RelativePath=".\InjectDLL.h"
+				>
+			</File>
+			<File
+				RelativePath=".\InjectDLLDlg.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Injection.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\res\InjectDLL.ico"
+				>
+			</File>
+			<File
+				RelativePath=".\InjectDLL.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\res\InjectDLL.rc2"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+		<Global
+			Name="RESOURCE_FILE"
+			Value="InjectDLL.rc"
+		/>
+	</Globals>
+</VisualStudioProject>

+ 232 - 0
Source/InjectDLL/InjectDLL/InjectDLLDlg.cpp

@@ -0,0 +1,232 @@
+
+// InjectDLLDlg.cpp : 实现文件
+//
+
+#include "stdafx.h"
+#include "InjectDLL.h"
+#include "InjectDLLDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
+
+class CAboutDlg : public CDialog
+{
+public:
+	CAboutDlg();
+
+// 对话框数据
+	enum { IDD = IDD_ABOUTBOX };
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
+
+// 实现
+protected:
+	DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
+{
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
+END_MESSAGE_MAP()
+
+
+// CInjectDLLDlg 对话框
+
+
+
+
+CInjectDLLDlg::CInjectDLLDlg(CWnd* pParent /*=NULL*/)
+	: CDialog(CInjectDLLDlg::IDD, pParent)
+{
+	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+}
+
+void CInjectDLLDlg::DoDataExchange(CDataExchange* pDX)
+{
+    CDialog::DoDataExchange(pDX);
+    DDX_Control(pDX, COMBO_PROCESS, m_cbProcess);
+}
+
+BEGIN_MESSAGE_MAP(CInjectDLLDlg, CDialog)
+	ON_WM_SYSCOMMAND()
+	ON_WM_PAINT()
+	ON_WM_QUERYDRAGICON()
+	//}}AFX_MSG_MAP
+    ON_BN_CLICKED(BTN_INJECT, &CInjectDLLDlg::OnBnClickedInject)
+    ON_BN_CLICKED(BTN_EJECT, &CInjectDLLDlg::OnBnClickedEject)
+    ON_BN_CLICKED(BTN_REFLESH, &CInjectDLLDlg::OnBnClickedReflesh)
+END_MESSAGE_MAP()
+
+
+// CInjectDLLDlg 消息处理程序
+
+BOOL CInjectDLLDlg::OnInitDialog()
+{
+	CDialog::OnInitDialog();
+
+	// 将“关于...”菜单项添加到系统菜单中。
+
+	// IDM_ABOUTBOX 必须在系统命令范围内。
+	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+	ASSERT(IDM_ABOUTBOX < 0xF000);
+
+	CMenu* pSysMenu = GetSystemMenu(FALSE);
+	if (pSysMenu != NULL)
+	{
+		BOOL bNameValid;
+		CString strAboutMenu;
+		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
+		ASSERT(bNameValid);
+		if (!strAboutMenu.IsEmpty())
+		{
+			pSysMenu->AppendMenu(MF_SEPARATOR);
+			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+		}
+	}
+
+	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
+	//  执行此操作
+	SetIcon(m_hIcon, TRUE);			// 设置大图标
+	SetIcon(m_hIcon, FALSE);		// 设置小图标
+
+	// TODO: 在此添加额外的初始化代码
+    InitCommbox();
+
+	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
+}
+
+void CInjectDLLDlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+	{
+		CAboutDlg dlgAbout;
+		dlgAbout.DoModal();
+	}
+	else
+	{
+		CDialog::OnSysCommand(nID, lParam);
+	}
+}
+
+// 如果向对话框添加最小化按钮,则需要下面的代码
+//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
+//  这将由框架自动完成。
+
+void CInjectDLLDlg::OnPaint()
+{
+	if (IsIconic())
+	{
+		CPaintDC dc(this); // 用于绘制的设备上下文
+
+		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
+
+		// 使图标在工作区矩形中居中
+		int cxIcon = GetSystemMetrics(SM_CXICON);
+		int cyIcon = GetSystemMetrics(SM_CYICON);
+		CRect rect;
+		GetClientRect(&rect);
+		int x = (rect.Width() - cxIcon + 1) / 2;
+		int y = (rect.Height() - cyIcon + 1) / 2;
+
+		// 绘制图标
+		dc.DrawIcon(x, y, m_hIcon);
+	}
+	else
+	{
+		CDialog::OnPaint();
+	}
+}
+
+//当用户拖动最小化窗口时系统调用此函数取得光标
+//显示。
+HCURSOR CInjectDLLDlg::OnQueryDragIcon()
+{
+	return static_cast<HCURSOR>(m_hIcon);
+}
+
+
+void CInjectDLLDlg::OnBnClickedInject()
+{
+    // TODO: 在此添加控件通知处理程序代码
+    CString strInjectDLL = OpenInectDLL();
+    INT nCurSel = m_cbProcess.GetCurSel();
+    if ( nCurSel == CB_ERR )
+    {
+        MessageBox(_T("请选择要注入的进程"), _T("提醒"), MB_ICONWARNING);
+        return;
+    }
+
+    ProInfo *ptr = (ProInfo*)m_cbProcess.GetItemDataPtr(nCurSel);
+    if ( ptr )
+    {
+        if ( m_Inject.GetInjectProcess() )
+        {
+            m_Inject.EjectDynamicLibrary();
+        }
+
+        m_Inject.setInjectionObj(ptr->dwProId, strInjectDLL.GetString());
+        m_Inject.InjectDynamicLibrary();
+    }
+}
+
+void CInjectDLLDlg::OnBnClickedEject()
+{
+    // TODO: 在此添加控件通知处理程序代码
+    if ( m_Inject.GetInjectProcess() )
+    {
+        m_Inject.EjectDynamicLibrary();
+    }
+}
+
+
+void CInjectDLLDlg::InitCommbox()
+{
+    m_vtProInfo.clear();
+    m_cbProcess.ResetContent();
+    // 获取全部进程到Commbox;
+    FindAllProcess(m_vtProInfo);
+
+    int nIndex = 0;
+    TCHAR szName[MAX_PATH] = {0};
+    for (std::vector<ProInfo>::iterator it = m_vtProInfo.begin(); it != m_vtProInfo.end(); it++ )
+    {
+        _stprintf(szName, _T("%s %ld"), it->strProName.c_str(),it->dwProId);
+        nIndex = m_cbProcess.AddString(szName);
+        m_cbProcess.SetItemDataPtr(nIndex, &*it);
+#ifdef _DEBUG
+        TRACE3("%ld-%s:%p\n", it->dwProId, it->strProName.c_str(), *it);
+#endif
+    }
+
+    m_cbProcess.SelectString(0, _T("Demo"));
+}
+
+CString CInjectDLLDlg::OpenInectDLL()
+{
+    CString strInjectDLL = _T("");
+    CFileDialog dlg(TRUE, _T("DLL"), _T("*.DLL"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("要注入的DLL (*.dll)|*.dll||"));
+    if ( dlg.DoModal() == IDOK )
+    {
+        strInjectDLL = dlg.GetPathName();
+    }
+        
+    return strInjectDLL;
+}
+
+void CInjectDLLDlg::OnBnClickedReflesh()
+{
+    // TODO: 在此添加控件通知处理程序代码
+    InitCommbox();
+}

+ 43 - 0
Source/InjectDLL/InjectDLL/InjectDLLDlg.h

@@ -0,0 +1,43 @@
+
+// InjectDLLDlg.h : 头文件
+//
+
+#pragma once
+#include "afxwin.h"
+
+
+// CInjectDLLDlg 对话框
+class CInjectDLLDlg : public CDialog
+{
+// 构造
+public:
+	CInjectDLLDlg(CWnd* pParent = NULL);	// 标准构造函数
+
+// 对话框数据
+	enum { IDD = IDD_INJECTDLL_DIALOG };
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
+
+
+// 实现
+protected:
+	HICON m_hIcon;
+
+	// 生成的消息映射函数
+	virtual BOOL OnInitDialog();
+	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+	afx_msg void OnPaint();
+	afx_msg HCURSOR OnQueryDragIcon();
+	DECLARE_MESSAGE_MAP()
+
+    std::vector<ProInfo> m_vtProInfo;
+    CInjection m_Inject;
+public:
+    void InitCommbox();
+    CString OpenInectDLL();
+    afx_msg void OnBnClickedInject();
+    afx_msg void OnBnClickedEject();
+    afx_msg void OnBnClickedReflesh();
+    CComboBox m_cbProcess;
+};

+ 155 - 0
Source/InjectDLL/InjectDLL/Injection.cpp

@@ -0,0 +1,155 @@
+#include "StdAfx.h"
+#include "Injection.h"
+#include "Global.h"
+
+CInjection::CInjection()
+{
+}
+
+CInjection::CInjection(DWORD dwPid, LPCTSTR lpDynamicLibraryPath)
+:m_dwInjectPID(dwPid),
+m_hInjectProcess(NULL),
+m_lpInjectData(NULL),
+m_lpEjectData(NULL),
+m_hInjectThread(NULL),
+m_hEjectThread(NULL),
+m_dwPathLen(0)
+{
+	ASSERT(dwPid!=0);
+	ASSERT(lpDynamicLibraryPath!=NULL);
+
+	memset(m_szDllPath, 0, sizeof(m_szDllPath));
+	_tcscpy_s(m_szDllPath,lpDynamicLibraryPath);
+	
+	m_hInjectProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwInjectPID);
+	if ( m_hInjectProcess == NULL)
+	{
+		WriteTextLog(_T("打开WeChat.exe进程失败"));
+	}
+	//m_hInjectProcess = OpenProcess(PROCESS_CREATE_THREAD	| PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, m_dwInjectPID);
+}
+
+CInjection::~CInjection(void)
+{
+	// 卸载dll;
+	EjectDynamicLibrary();
+
+	// 释放所有资源;
+	if (m_hInjectThread)
+		CloseHandle(m_hInjectThread);
+	m_hInjectThread = NULL;
+
+	if (m_hEjectThread)
+		CloseHandle(m_hEjectThread);
+	m_hEjectThread = NULL;
+
+	if (m_lpInjectData)
+		VirtualFreeEx(m_hInjectProcess, m_lpInjectData, m_dwPathLen, MEM_RELEASE);
+	m_lpInjectData = NULL;
+
+	if (m_lpEjectData)
+		VirtualFreeEx(m_hInjectProcess, m_lpEjectData, m_dwPathLen, MEM_RELEASE);
+	m_lpEjectData = NULL;
+
+	if (m_hInjectProcess)
+		CloseHandle(m_hInjectProcess);
+	m_hInjectProcess = NULL;
+}
+
+void CInjection::setInjectionObj(DWORD dwPid, LPCTSTR lpDynamicLibraryPath)
+{
+	ASSERT(dwPid != 0);
+	ASSERT(lpDynamicLibraryPath != NULL);
+
+	m_dwInjectPID = dwPid;
+	memset(m_szDllPath, 0, sizeof(m_szDllPath));
+	_tcscpy_s(m_szDllPath, lpDynamicLibraryPath);
+
+	m_hInjectProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwInjectPID);
+	if (m_hInjectProcess == NULL)
+	{
+		WriteTextLog(_T("打开WeChat.exe进程失败"));
+	}
+	//m_hInjectProcess = OpenProcess(PROCESS_CREATE_THREAD	| PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, m_dwInjectPID);
+}
+
+BOOL CInjection::InjectDynamicLibrary()
+{
+	ASSERT(m_hInjectProcess!=NULL);
+
+	m_dwPathLen = _tcslen(m_szDllPath)*sizeof(TCHAR)+1;
+	m_lpInjectData = VirtualAllocEx(m_hInjectProcess,NULL, m_dwPathLen, MEM_COMMIT, PAGE_READWRITE);
+	if (NULL == m_lpInjectData)
+	{
+		WriteTextLog(_T("创建WeChat.exe进程虚拟内存失败"));
+		return FALSE;
+	}
+
+	if (WriteProcessMemory(m_hInjectProcess, m_lpInjectData, m_szDllPath, m_dwPathLen, NULL) == 0)
+	{
+		// 注意:MEM_RELEASE释放时第三参数一定要为0,请查看MSDN;
+		VirtualFreeEx(m_hInjectProcess, m_lpInjectData, 0, MEM_RELEASE);
+		return FALSE;
+	}
+
+	HMODULE hk32 = GetModuleHandle(_T("kernel32.dll"));
+	// 注意:微信使用的是W版本;
+	LPVOID lpAddr = GetProcAddress(hk32,"LoadLibraryW");
+
+	m_hInjectThread = CreateRemoteThread(m_hInjectProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpAddr, m_lpInjectData, 0, NULL);
+	if (NULL == m_hInjectThread)
+	{
+		// 注意:MEM_RELEASE释放时第三参数一定要为0,请查看MSDN;
+		VirtualFreeEx(m_hInjectProcess, m_lpInjectData, 0, MEM_RELEASE);
+		return FALSE;
+	}
+
+	WaitForSingleObject(m_hInjectThread, INFINITE);
+	if (m_hInjectThread)
+		CloseHandle(m_hInjectThread);
+	m_hInjectThread = NULL;
+	
+	/* 注入成功后,不能释放内存否则微信会挂;
+	if (m_lpInjectData != NULL)
+		VirtualFreeEx(m_hInjectProcess, m_lpInjectData, 0, MEM_RELEASE);
+	*/
+
+	return TRUE;
+}
+
+BOOL CInjection::EjectDynamicLibrary()
+{
+	if(m_hInjectProcess==NULL)
+		return TRUE;
+
+	// 获取模块句柄;
+	HANDLE hModule = FindModuleEx(m_szDllPath, m_dwInjectPID);
+	if (hModule == NULL )
+	{
+		WriteTextLog(_T("获取WeChat.exe进程模块hook.dll失败"));
+		return FALSE;
+	}
+
+	LPVOID lpAddr = GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "FreeLibraryAndExitThread");//FreeLibraryAndExitThread//FreeLibrary
+	if (lpAddr == NULL )
+	{
+		WriteTextLog(_T("获取kernel32.dll中的FreeLibraryAndExitThread失败"));
+		return FALSE;
+	}
+
+	m_hEjectThread = CreateRemoteThread(m_hInjectProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpAddr, hModule, 0, NULL);
+	if ( m_hEjectThread == NULL )
+	{
+		WriteTextLog(_T("创建WeChat.exe远程线程(FreeLibraryAndExitThread)失败"));
+		return FALSE;
+	}
+
+	WaitForSingleObject(m_hEjectThread, INFINITE);
+	if (m_hEjectThread)
+		CloseHandle(m_hEjectThread);
+	m_hEjectThread = NULL;
+
+	return TRUE;
+}
+
+

+ 56 - 0
Source/InjectDLL/InjectDLL/Injection.h

@@ -0,0 +1,56 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Home], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Home];
+/*  日    期:[1/6/2019];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Home];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __INJECTION_OBJ__
+#define __INJECTION_OBJ__
+
+#pragma once
+
+class CInjection
+{
+public:
+	CInjection();
+	explicit CInjection(DWORD dwPid, LPCTSTR lpDynamicLibraryPath);
+	~CInjection(void);
+	// dll路径和要注入的进程id;
+	void setInjectionObj(DWORD dwPid, LPCTSTR lpDynamicLibraryPath);
+
+public:
+	BOOL InjectDynamicLibrary();
+	BOOL EjectDynamicLibrary();
+	inline HANDLE GetInjectProcess(){
+		return m_hInjectProcess;
+	}
+private:
+	// 当前注入的进程ID;
+	DWORD			m_dwInjectPID;
+	// 动态库路径;
+	TCHAR			m_szDllPath[MAX_PATH];
+	// 当前注入的进程句柄;
+	HANDLE			m_hInjectProcess;
+	// 路径分配的内存;
+	LPVOID			m_lpInjectData;
+	LPVOID			m_lpEjectData;
+	// 路径长度;
+	DWORD			m_dwPathLen;
+	// 注入线程句柄;
+	HANDLE			m_hInjectThread;
+	// 卸载线程句柄;
+	HANDLE			m_hEjectThread;
+};
+
+#endif

+ 69 - 0
Source/InjectDLL/InjectDLL/ReadMe.txt

@@ -0,0 +1,69 @@
+================================================================================
+    MICROSOFT 基础类库: InjectDLL 项目概述
+===============================================================================
+
+应用程序向导已为您创建此 InjectDLL 应用程序。此应用程序不仅演示使用 Microsoft 基础类的基本知识,而且可作为编写应用程序的起点。
+
+此文件包含组成 InjectDLL 应用程序的各个文件的内容摘要。
+
+InjectDLL.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件。
+    它包含有关生成文件的 Visual C++ 版本的信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+InjectDLL.h
+    这是应用程序的主要头文件。它包括其他项目特定的头文件(包括 Resource.h),并声明 CInjectDLLApp 应用程序类。
+
+InjectDLL.cpp
+    这是包含应用程序类 CInjectDLLApp 的主要应用程序源文件。
+
+InjectDLL.rc
+    这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。项目资源位于 2052 中。
+
+res\InjectDLL.ico
+    这是用作应用程序图标的图标文件。此图标包括在主要资源文件 InjectDLL.rc 中。
+
+res\InjectDLL.rc2
+    此文件包含不是由 Microsoft Visual C++ 编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+应用程序向导创建一个对话框类:
+
+InjectDLLDlg.h,InjectDLLDlg.cpp - 对话框
+    这些文件包含 CInjectDLLDlg 类。该类定义应用程序主对话框的行为。该对话框的模板位于 InjectDLL.rc 中,该文件可以在 Microsoft Visual C++ 中进行编辑。
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+其他功能:
+
+ActiveX 控件
+    应用程序包括对使用 ActiveX 控件的支持。
+
+打印及打印预览支持
+    应用程序向导已通过从 MFC 库调用 CView 类中的成员函数,生成了用于处理打印、打印设置和打印预览命令的代码。
+
+/////////////////////////////////////////////////////////////////////////////
+
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 InjectDLL.pch 的预编译头(PCH)文件和名为 StdAfx.obj 的预编译类型文件。
+
+Resource.h
+    这是标准头文件,它定义新资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+InjectDLL.manifest
+	Windows XP 使用应用程序清单文件描述应用程序	对特定版本并行程序集的依赖性。加载程序使用此	信息从程序集缓存加载相应程序集或	从应用程序加载私有信息。应用程序清单可能作为	与应用程序可执行文件安装在同一文件夹中的外部 .manifest 文件包括在内以便重新发布,	也可能以资源的形式包括在该可执行文件中。
+/////////////////////////////////////////////////////////////////////////////
+
+其他注释:
+
+应用程序向导使用“TODO:”指示应添加或自定义的源代码部分。
+
+如果应用程序在共享 DLL 中使用 MFC,则将需要重新发布 MFC DLL。如果应用程序所用与操作系统的区域设置不同,则也将必须重新发布对应的本地化资源 MFC90XXX.DLL。
+有关这两个主题的详细信息,请参阅 MSDN 文档中有关重新发布 Visual C++ 应用程序的部分。
+
+/////////////////////////////////////////////////////////////////////////////

BIN
Source/InjectDLL/InjectDLL/res/InjectDLL.ico


+ 13 - 0
Source/InjectDLL/InjectDLL/res/InjectDLL.rc2

@@ -0,0 +1,13 @@
+//
+// InjectDLL.RC2 - Microsoft Visual C++ 不会直接编辑的资源
+//
+
+#ifdef APSTUDIO_INVOKED
+#error 此文件不能用 Microsoft Visual C++ 编辑
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// 在此处添加手动编辑的资源...
+
+/////////////////////////////////////////////////////////////////////////////

+ 25 - 0
Source/InjectDLL/InjectDLL/resource.h

@@ -0,0 +1,25 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by InjectDLL.rc
+//
+#define IDM_ABOUTBOX                    0x0010
+#define IDD_ABOUTBOX                    100
+#define IDS_ABOUTBOX                    101
+#define IDD_INJECTDLL_DIALOG            102
+#define IDR_MAINFRAME                   128
+#define COMBO_PROCESS                   1000
+#define BTN_INJECT                      1001
+#define BTN_EJECT                       1002
+#define IDC_BUTTON1                     1003
+#define BTN_REFLESH                     1003
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        129
+#define _APS_NEXT_COMMAND_VALUE         32771
+#define _APS_NEXT_CONTROL_VALUE         1004
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif

+ 8 - 0
Source/InjectDLL/InjectDLL/stdafx.cpp

@@ -0,0 +1,8 @@
+
+// stdafx.cpp : 只包括标准包含文件的源文件
+// InjectDLL.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+

+ 61 - 0
Source/InjectDLL/InjectDLL/stdafx.h

@@ -0,0 +1,61 @@
+
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+
+#pragma once
+
+#ifndef _SECURE_ATL
+#define _SECURE_ATL 1
+#endif
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include "targetver.h"
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+
+
+#include <afxdisp.h>        // MFC 自动化类
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>             // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxcontrolbars.h>     // 功能区和控件条的 MFC 支持
+
+
+#include "Global.h"
+#include "Injection.h"
+
+
+
+
+
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+

+ 26 - 0
Source/InjectDLL/InjectDLL/targetver.h

@@ -0,0 +1,26 @@
+
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif
+