Browse Source

正式注入DLL

Jeff 3 years ago
parent
commit
436f7be396

+ 20 - 0
Source/OGCAssist/OGCAssist.sln

@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OGCAssist", "OGCAssist\OGCAssist.vcproj", "{3A08430B-2381-49B3-8C6B-1D733C6357D5}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{3A08430B-2381-49B3-8C6B-1D733C6357D5}.Debug|Win32.ActiveCfg = Debug|Win32
+		{3A08430B-2381-49B3-8C6B-1D733C6357D5}.Debug|Win32.Build.0 = Debug|Win32
+		{3A08430B-2381-49B3-8C6B-1D733C6357D5}.Release|Win32.ActiveCfg = Release|Win32
+		{3A08430B-2381-49B3-8C6B-1D733C6357D5}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 699 - 0
Source/OGCAssist/OGCAssist/OGCAssist.cpp

@@ -0,0 +1,699 @@
+// OGCAssist.cpp : 定义 DLL 应用程序的导出函数。
+//
+
+#include "stdafx.h"
+#include "OGCAssist.h"
+#include <process.h>
+
+namespace Assist
+{
+	// 全局Call Data;
+	CALLDATA _cd_Go;
+	CALLDATA _cd_Connect;
+	CALLDATA _cd_Disconnect;
+	CALLDATA _cd_CheckFW;
+	CALLDATA _cd_CheckFW_CommunicationError;
+	CALLDATA _cd_SaveAsOutputData;
+	CALLDATA _cd_Go_SN;
+	CALLDATA _cd_Go_CommunicationError;
+	CALLDATA _cd_Go_SetCommunicationError;
+	CALLDATA _cd_Initial_failed;
+	CALLDATA _cd_ExternalException;
+
+	// 调试耗时值ms;
+	DWORD dwElapsed = 0;
+
+	TCHAR g_szGoSN[32] = {0};
+
+	DWORD dwCallAddr = 0;
+
+	// 8组全局寄存器存储;
+	DWORD dwEAX = 0;
+	DWORD dwEBX = 0;
+	DWORD dwECX = 0;
+	DWORD dwEDX = 0;
+	DWORD dwEBP = 0;
+	DWORD dwESP = 0;
+	DWORD dwESI = 0;
+	DWORD dwEDI = 0;
+
+	BOOL HijackedCall(CALLDATA *pCallData);
+	// 自定义跳转函数;
+	void Call_MyDisconnect();
+	void Call_MyConnect();
+	void Call_MyGo();
+	void Call_MyGoSN();
+	void Call_MyCheckFW();
+	void Call_MyCheckFWCommunicationError();
+	void Call_MySaveAsOutputData();
+	void Call_MyInitial_Failed();
+	void Call_MyGoCommunicationError();
+	void Call_MyGoSetCommunicationError();
+	void Call_MyExternalException();
+
+
+	void InitCallData()
+	{
+#pragma region 启动时Initial Communication:需要程序启动时注入;
+		// 00401EB8 | E8 7BCB0C00 | call demo.4CEA38 |
+		_cd_Initial_failed.myCall = Call_MyInitial_Failed;
+		// 00401EBD | FF4D CC | dec dword ptr ss:[ebp-34] |
+		_cd_Initial_failed.dwBack2Addr = 0x00401EBD;
+		// 00401EB8 | E8 7BCB0C00 | call demo.4CEA38 |
+		_cd_Initial_failed.dwOriginalAddr = 0x00401EB8;
+		_cd_Initial_failed.dwOriginalCallAddr = 0x004CEA38;
+
+		_cd_Initial_failed.nMyCallDataLen = JMP_DLEN;
+		memset(_cd_Initial_failed.szMyCallData, 0x90, CALL_LEN);
+		_cd_Initial_failed.szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&_cd_Initial_failed.szMyCallData[1]) = (DWORD)_cd_Initial_failed.myCall - _cd_Initial_failed.dwOriginalAddr - JMP_DLEN;
+#pragma endregion
+
+#pragma region Connect按钮劫持
+		//00415ECB | 0F84 6A040000 | je demo.41633B 
+		_cd_Connect.myCall = Call_MyConnect;
+		// 00415ED1 | 6A 00                  | push 0 
+		_cd_Connect.dwBack2Addr = 0x00415ED1;
+		_cd_Connect.dwOriginalAddr = 0x00415ECB;
+		_cd_Connect.dwOriginalCallAddr = 0x0041633B;	// 此处是JMP,注意注入时不要调用为Call
+
+		_cd_Connect.nMyCallDataLen = JMP_DLEN;
+		memset(_cd_Connect.szMyCallData, 0x90, CALL_LEN);
+		_cd_Connect.szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&_cd_Connect.szMyCallData[1]) = (DWORD)_cd_Connect.myCall - _cd_Connect.dwOriginalAddr - JMP_DLEN;
+#pragma endregion
+
+#pragma region Disconnect按钮劫持
+		// 0043790B | E8 E4C90900 | call demo.4D42F4 | # 此处可能用于SetWindowText之类处理
+		// 00437910 | FF4D F4 | dec dword ptr ss:[ebp-C]                 |
+		_cd_Disconnect.myCall = Call_MyDisconnect;
+		_cd_Disconnect.dwBack2Addr = 0x00437910;
+		_cd_Disconnect.dwOriginalAddr = 0x0043790B;
+		_cd_Disconnect.dwOriginalCallAddr = 0x004D42F4;
+
+		_cd_Disconnect.nMyCallDataLen = JMP_DLEN;
+		memset(_cd_Disconnect.szMyCallData, 0x90, CALL_LEN);
+		_cd_Disconnect.szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&_cd_Disconnect.szMyCallData[1]) = (DWORD)_cd_Disconnect.myCall - _cd_Disconnect.dwOriginalAddr - JMP_DLEN;
+#pragma endregion
+
+#pragma region ExternalException
+		// 必须获取模块地址:ca210ctrl.dll
+		HMODULE hModule = GetModuleHandle(_T("Ca210Ctrl.dll"));
+		// 044D677C | FF15 78645404 | call dword ptr ds:[<&RaiseException>] |
+		_cd_ExternalException.myCall = Call_MyExternalException;
+		// 044D6782 | 5F | pop edi |
+		_cd_ExternalException.dwBack2Addr = (DWORD)hModule + 0x106782;
+		_cd_ExternalException.dwOriginalAddr = (DWORD)hModule + 0x10677C;
+		_cd_ExternalException.dwOriginalCallAddr = 0x769F05B0;
+
+		_cd_ExternalException.nMyCallDataLen = JMP_DLEN;
+		memset(_cd_ExternalException.szMyCallData, 0x90, CALL_LEN);
+		_cd_ExternalException.szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&_cd_ExternalException.szMyCallData[1]) = (DWORD)_cd_ExternalException.myCall - _cd_ExternalException.dwOriginalAddr - JMP_DLEN;
+#pragma endregion
+
+#pragma region Go按钮劫持
+		/* 成功执行后的处理 */
+		_cd_Go.myCall = Call_MyGo;
+		_cd_Go.dwBack2Addr = 0x004376B0;
+		// 004376AB | E8 50A30C00 | call demo.501A00 
+		_cd_Go.dwOriginalAddr = 0x004376AB;
+		_cd_Go.dwOriginalCallAddr = 0x00501A00;
+
+		_cd_Go.nMyCallDataLen = JMP_DLEN;
+		memset(_cd_Go.szMyCallData, 0x90, CALL_LEN);
+		_cd_Go.szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&_cd_Go.szMyCallData[1]) = (DWORD)_cd_Go.myCall - _cd_Go.dwOriginalAddr - JMP_DLEN;
+
+		// 获取SN字符串;
+		// 00417AEC | E8 9BA5FEFF | call demo.40208C |
+		// 00417AF1 | E8 722C0700 | call demo.48A768 |
+		_cd_Go_SN.myCall = Call_MyGoSN;
+		_cd_Go_SN.dwBack2Addr = 0x00417AF1;
+		// 004376AB | E8 50A30C00 | call demo.501A00 
+		_cd_Go_SN.dwOriginalAddr = 0x00417AEC;
+		_cd_Go_SN.dwOriginalCallAddr = 0x0040208C;
+
+		_cd_Go_SN.nMyCallDataLen = JMP_DLEN;
+		memset(_cd_Go_SN.szMyCallData, 0x90, CALL_LEN);
+		_cd_Go_SN.szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&_cd_Go_SN.szMyCallData[1]) = (DWORD)_cd_Go_SN.myCall - _cd_Go_SN.dwOriginalAddr - JMP_DLEN;
+
+		// 消除 Set Communication Error 弹框;
+		// 00417FCD | E8 666A0B00 | call demo.4CEA38 |
+		_cd_Go_SetCommunicationError.myCall = Call_MyGoSetCommunicationError;
+		_cd_Go_SetCommunicationError.dwBack2Addr = 0x00417FD2;
+		// 00417FD2 | FF8D F4E8FFFF| dec dword ptr ss:[ebp-170C]|
+		_cd_Go_SetCommunicationError.dwOriginalAddr = 0x00417FCD;
+		_cd_Go_SetCommunicationError.dwOriginalCallAddr = 0x004CEA38;
+
+		_cd_Go_SetCommunicationError.nMyCallDataLen = JMP_DLEN;
+		memset(_cd_Go_SetCommunicationError.szMyCallData, 0x90, CALL_LEN);
+		_cd_Go_SetCommunicationError.szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&_cd_Go_SetCommunicationError.szMyCallData[1]) = (DWORD)_cd_Go_SetCommunicationError.myCall - _cd_Go_SetCommunicationError.dwOriginalAddr - JMP_DLEN;
+
+		// 消除Communication Error弹框;
+		// 00404408 | E8 2BA60C00| call demo.4CEA38| 
+		_cd_Go_CommunicationError.myCall = Call_MyGoCommunicationError;
+		_cd_Go_CommunicationError.dwBack2Addr = 0x0040440D;
+		// 0040440D | FF4D BC | dec dword ptr ss:[ebp-44] | 
+		_cd_Go_CommunicationError.dwOriginalAddr = 0x00404408;
+		_cd_Go_CommunicationError.dwOriginalCallAddr = 0x004CEA38;
+
+		_cd_Go_CommunicationError.nMyCallDataLen = JMP_DLEN;
+		memset(_cd_Go_CommunicationError.szMyCallData, 0x90, CALL_LEN);
+		_cd_Go_CommunicationError.szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&_cd_Go_CommunicationError.szMyCallData[1]) = (DWORD)_cd_Go_CommunicationError.myCall - _cd_Go_CommunicationError.dwOriginalAddr - JMP_DLEN;
+#pragma endregion
+
+#pragma region CheckFW按钮处理
+		// 00404458 | E8 E7F70400       | call demo.453C44 | # 此处应该是执行I2CReadEx
+		_cd_CheckFW.myCall = Call_MyCheckFW;	// 成功获取版本后跳转处理;
+		// 0040445D | 83C4 1C           | add esp,1C                    |
+		_cd_CheckFW.dwBack2Addr = 0x0040445D;
+		_cd_CheckFW.dwOriginalAddr = 0x00404458;
+		_cd_CheckFW.dwOriginalCallAddr = 0x453C44;
+
+		_cd_CheckFW.nMyCallDataLen = JMP_DLEN;
+		memset(_cd_CheckFW.szMyCallData, 0x90, CALL_LEN);
+		_cd_CheckFW.szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&_cd_CheckFW.szMyCallData[1]) = (DWORD)_cd_CheckFW.myCall - _cd_CheckFW.dwOriginalAddr - JMP_DLEN;
+
+		/* 针对弹框Communication Error的消除处理 */
+		// 00404408 | E8 2BA60C00       | call demo.4CEA38 | # Dailogs::ShowMessage(string) 弹出提示框:Communication Error
+		_cd_CheckFW_CommunicationError.myCall = Call_MyCheckFWCommunicationError;	// 成功获取版本后跳转处理;
+		// 0040440D | FF4D BC           | dec dword ptr ss:[ebp-44]     | [ebp-44]:&"脥I"
+		_cd_CheckFW_CommunicationError.dwBack2Addr = 0x0040440D;
+		_cd_CheckFW_CommunicationError.dwOriginalAddr = 0x00404408;
+		_cd_CheckFW_CommunicationError.dwOriginalCallAddr = 0x4CEA38;
+
+		_cd_CheckFW_CommunicationError.nMyCallDataLen = JMP_DLEN;
+		memset(_cd_CheckFW_CommunicationError.szMyCallData, 0x90, CALL_LEN);
+		_cd_CheckFW_CommunicationError.szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&_cd_CheckFW_CommunicationError.szMyCallData[1]) = (DWORD)_cd_CheckFW_CommunicationError.myCall - _cd_CheckFW_CommunicationError.dwOriginalAddr - JMP_DLEN;
+#pragma endregion
+	}
+
+	BOOL HijackedAllCall()
+	{
+		BOOL bHijack=FALSE;
+		if ( !(bHijack = HijackedCall(&_cd_Connect)) )
+			goto end;
+
+		if ( !(bHijack = HijackedCall(&_cd_Disconnect)) )
+			goto end;
+
+		if ( !(bHijack = HijackedCall(&_cd_Go)) )
+			goto end;
+
+		if ( !(bHijack = HijackedCall(&_cd_Go_SN)) )
+			goto end;
+
+		if ( !(bHijack = HijackedCall(&_cd_Go_CommunicationError)) )
+			goto end;
+
+		if ( !(bHijack = HijackedCall(&_cd_Go_SetCommunicationError)) )
+			goto end;
+
+		if ( !(bHijack = HijackedCall(&_cd_ExternalException)) )
+			goto end;
+
+		if ( !(bHijack = HijackedCall(&_cd_CheckFW)) )
+			goto end;
+
+		if ( !(bHijack = HijackedCall(&_cd_CheckFW_CommunicationError)) )
+			goto end;
+
+end:
+		return bHijack;
+	}
+
+	void RestoreAllCall()
+	{
+
+	}
+
+	// 劫持原始地址;
+	BOOL HijackedCall(CALLDATA *pCallData)
+	{
+		if ( !pCallData )
+			return FALSE;
+
+		memset(pCallData->szMyCallData, 0, CALL_LEN);
+		pCallData->szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&pCallData->szMyCallData[1]) = (DWORD)pCallData->myCall - pCallData->dwOriginalAddr - CALL_LEN;
+
+		HANDLE hProc = GetCurrentProcess();
+		// 将要劫持的地址指令备份下来;
+		memset(pCallData->szOriginalAddrData, 0, CALL_LEN);
+		if ( !ReadProcessMemory(hProc, (LPVOID)pCallData->dwOriginalAddr, pCallData->szOriginalAddrData, CALL_LEN, NULL) )
+		{
+			MessageBox(NULL, _T("读取内存失败"), _T("提示"),MB_OK);
+			return FALSE;
+		}
+
+		// 将我们的Call地址指令写入目标地址;
+		if ( !WriteProcessMemory(hProc, (LPVOID)pCallData->dwOriginalAddr, pCallData->szMyCallData, CALL_LEN, NULL) )
+		{
+			MessageBox(NULL, _T("写入内存失败"), _T("提示"),MB_OK);
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	// 劫持原始地址;
+	BOOL HijackedCall(LPVOID MyCall, LPVOID OriginalCall, BYTE (&szOriginalCallData)[CALL_LEN])
+	{
+		BYTE szMyCallData[CALL_LEN] = {0};
+		szMyCallData[0] = 0xE9; // 汇编硬编码:jmp [4字节地址];
+		*(LPDWORD)(&szMyCallData[1]) = (DWORD)MyCall - (DWORD)OriginalCall - CALL_LEN;
+
+		HANDLE hProc = GetCurrentProcess();
+		// 将要劫持的地址指令备份下来;
+		if ( !ReadProcessMemory(hProc, OriginalCall, szOriginalCallData, CALL_LEN, NULL) )
+		{
+			MessageBox(NULL, _T("读取内存失败"), _T("提示"),MB_OK);
+			return FALSE;
+		}
+
+		// 将我们的Call地址指令写入目标地址;
+		if ( !WriteProcessMemory(hProc, OriginalCall, szMyCallData, CALL_LEN, NULL) )
+		{
+			MessageBox(NULL, _T("写入内存失败"), _T("提示"),MB_OK);
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	BOOL RecoveryCall(CALLDATA *pCallData)
+	{
+		if ( !pCallData )
+			return FALSE;
+
+		// 将我们的Call地址指令写入目标地址;
+		if ( !WriteProcessMemory(GetCurrentProcess(), (LPVOID)pCallData->dwOriginalAddr, pCallData->szOriginalAddrData, CALL_LEN, NULL) )
+		{
+			MessageBox(NULL, _T("写入内存失败"), _T("提示"),MB_OK);
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	void MyInitialFailed()
+	{
+		MessageBox(NULL, _T("MyInitialFailed"), _T("MyInitialFailed"), MB_OK);
+	}
+
+	void __declspec(naked) Call_MyInitial_Failed()
+	{
+		__asm pushad;
+		MyInitialFailed();
+		__asm popad;
+		// 不执行原call:原Call是Messagebox弹框,需要消除掉它;
+		// __asm call _cd_Initial_failed.dwOriginalCallAddr;
+		__asm jmp _cd_Initial_failed.dwBack2Addr;
+	}
+
+	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
+		}
+	}
+
+	void MyGo()
+	{   
+		CHAR szMsg[MAX_PATH];
+		DWORD dwElapsedAddr = 0x0052DF54;
+		DWORD dwSNAddr = dwEBP - 0x5D0;
+		sprintf_s(szMsg, "MyGo耗时:%ldms, SN:%08X, %s", *(LPDWORD)dwElapsedAddr, dwSNAddr, (CHAR*)(*(LPDWORD)dwSNAddr));
+		MessageBoxA(NULL, szMsg, "MyGo", MB_OK);
+	}
+
+	void __declspec(naked) Call_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;
+		}
+
+		MyGo();
+
+		__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;
+			call _cd_Go.dwOriginalCallAddr
+				// 返回劫持地址下一行;
+				jmp _cd_Go.dwBack2Addr
+		}
+	}
+
+	void MyGoSN()
+	{
+		CHAR szMsg[MAX_PATH];
+		DWORD dwSNAddr = dwEBP - 0x5D0;
+		//_stprintf_s(szMsg, _T("MyGo %08X, %08X, %08X, %s"), dwEAX, dwSNAddr, DWORD(*(LPDWORD)dwSNAddr), (TCHAR*)(*(LPDWORD)dwSNAddr));
+		sprintf_s(szMsg, "MyGo %08X, %08X, %08X, %s", dwEAX, dwSNAddr, DWORD(*(LPDWORD)dwSNAddr), (CHAR*)(*(LPDWORD)dwSNAddr));
+		MessageBoxA(NULL, szMsg, "MyGoSN", MB_OK);
+	}
+
+	void __declspec(naked) Call_MyGoSN()
+	{
+		// 备份寄存器;
+		__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;
+		}
+
+		MyGoSN();
+
+		__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;
+			call _cd_Go_SN.dwOriginalCallAddr
+				// 返回劫持地址下一行;
+				jmp _cd_Go_SN.dwBack2Addr
+		}
+	}
+
+	void MyGoSetCommunicationError()
+	{
+		MessageBox(NULL, _T("MyGoSetCommunicationError"), _T("劫持"), MB_OK);
+	}
+
+	void __declspec(naked) Call_MyGoSetCommunicationError()
+	{
+		// 备份寄存器;
+		__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;
+		}
+
+		MyGoSetCommunicationError();
+
+		__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;
+			//call _cd_Go_SetCommunicationError.dwOriginalCallAddr	// 经验证,即使不执行原call,也会弹异常框;
+			// 返回劫持地址下一行;
+			jmp _cd_Go_SetCommunicationError.dwBack2Addr
+		}
+	}
+
+	void MyGoCommunicationError()
+	{
+		MessageBox(NULL, _T("MyGoCommunicationError"), _T("劫持"), MB_OK);
+	}
+
+	void __declspec(naked) Call_MyGoCommunicationError()
+	{
+		// 备份寄存器;
+		__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;
+		}
+
+		MyGoCommunicationError();
+
+		__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;
+			//call _cd_Go_CommunicationError.dwOriginalCallAddr
+			// 返回劫持地址下一行;
+			jmp _cd_Go_CommunicationError.dwBack2Addr
+		}
+	}
+
+	BOOL MyConnect()
+	{
+		// 读取AL的值; 0表示Connect失败;1表示成功;
+		BYTE AL = LOBYTE(LOWORD(dwEAX));
+		if ( AL == 0 )
+		{
+			MessageBox(NULL, _T("连接失败"), _T("连接提示"), MB_OK);
+			return FALSE;
+		}
+		else
+		{
+			MessageBox(NULL, _T("连接成功"), _T("连接提示"), MB_OK);
+		}
+		return TRUE;
+	}
+
+	void __declspec(naked) Call_MyConnect()
+	{
+		// 备份寄存器;
+		__asm mov dwEAX, eax;
+		__asm pushad;
+
+		if ( MyConnect() )
+		{
+			__asm{
+				// 恢复寄存器; 
+				popad;
+				// 成功:则继续正常的流程;
+				jmp _cd_Connect.dwBack2Addr;
+			}
+
+		}
+		else
+		{
+			__asm{
+				// 恢复寄存器; 
+				popad;
+				// 失败:JMP到出错处理;
+				jmp _cd_Connect.dwOriginalCallAddr;
+			}
+		}   
+	}
+
+	void MyExternalException()
+	{
+		MessageBox(NULL, _T("MyExternalExceptionE06D7363,重启异常待重启"), _T("提示"), MB_OK);
+		::exit(0);
+	}
+
+	void __declspec(naked) Call_MyExternalException()
+	{
+		// 备份寄存器;
+		__asm {
+			pushad;
+		}
+
+		MyExternalException();
+
+		__asm
+		{
+			// 恢复寄存器; 
+			popad;
+			// 失败:JMP到出错处理;
+			call _cd_ExternalException.dwOriginalCallAddr;
+			jmp _cd_ExternalException.dwBack2Addr;
+		} 
+	}
+
+	void MyDisconnect()
+	{
+		MessageBox(NULL, _T("MyDisconnect Function"), _T("MyDisconnect"), MB_OK);
+	}
+
+	void __declspec(naked) Call_MyDisconnect()
+	{
+		__asm pushad;
+		MyDisconnect();
+		__asm
+		{
+			popad;
+			call _cd_Disconnect.dwOriginalCallAddr;
+			jmp _cd_Disconnect.dwBack2Addr;
+		}
+	}
+
+	void __declspec(naked) Call_MyCheckFW()
+	{
+		// 备份寄存器;
+		__asm pushad;
+
+
+		MessageBox(NULL, _T("Call_MyCheckFW"), _T("MyCheckFW"), MB_OK);
+
+
+		__asm{
+			// 恢复寄存器; 
+			popad;
+			// 执行原call;
+			call _cd_CheckFW.dwOriginalCallAddr;
+			// 最后返回原Call地址下一行;
+			jmp _cd_CheckFW.dwBack2Addr;
+		}
+	}
+
+	void __declspec(naked) Call_MyCheckFWCommunicationError()
+	{
+		// 备份寄存器;
+		__asm pushad;
+
+
+		MessageBox(NULL, _T("Call_MyCheckFWCommunicationError"), _T("MyCheckFWCommunicationError"), MB_OK);
+
+
+		__asm{
+			// 恢复寄存器; 
+			popad;
+			// 消除原call;
+			// call _cd_CheckFW.dwOriginalCallAddr;
+			// 最后返回原Call地址下一行;
+			jmp _cd_CheckFW_CommunicationError.dwBack2Addr;
+		}
+	}
+
+	void __declspec(naked) SetChannel()
+	{
+		// 备份寄存器;
+		__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 _cd_Go.dwBack2Addr;
+		}
+	}
+
+	void SetSN(LPCTSTR lpSN)
+	{
+
+	}
+
+	void ChangeSDK(int nSDK)   // 0=410SDK, 1=310SDK;
+	{
+
+	}
+
+	void __declspec(naked) Call_Connect()
+	{
+		//dwCallAddr = 0x004D5864;//0x004378B0;
+		/*dwCallAddr = 0x004378B0;
+		__asm {
+		pushad;
+		mov eax,0x02393F78;
+		mov ebx,0x024856CC;
+		mov ecx,0x004AB16C;
+		mov edx,0x024156CC;
+		call dwCallAddr;
+		popad;
+		}*/
+		dwCallAddr = 0x00415DFC;
+		__asm call dwCallAddr;
+	}
+};

+ 36 - 0
Source/OGCAssist/OGCAssist/OGCAssist.h

@@ -0,0 +1,36 @@
+#include "stdafx.h"
+
+// jmp指令长度;
+#define JMP_DLEN 5
+// call指令长度;
+#define CALL_LEN 5
+
+namespace Assist
+{
+	typedef struct __CALL_DATA__
+	{
+		LPVOID  myCall;                             // 自定义的地址;
+		DWORD   dwOriginalAddr;                     // 被劫持的原始地址;
+		DWORD   dwOriginalCallAddr;                 // 被劫持的原始函数地址;
+		DWORD   dwBack2Addr;                        // 劫持Call完成后要返回的原始地址的下一地址;
+		INT     nMyCallDataLen;
+		BYTE    szMyCallData[CALL_LEN];             // 劫持Call的硬编码数据;
+		INT     nOriginalAddrDataLen;
+		BYTE    szOriginalAddrData[CALL_LEN];       // 被劫持的原始Call数据备份;
+
+		__CALL_DATA__() {
+			myCall = NULL;
+			dwBack2Addr = 0;
+			dwOriginalAddr = 0;
+			memset(szMyCallData, 0, CALL_LEN);
+			memset(szOriginalAddrData, 0, CALL_LEN);
+		}
+	}CALLDATA, *LPCALLDATA;
+
+	// 初始化Call Data
+	void InitCallData();
+	// 劫持所有Call Data;
+	BOOL HijackedAllCall();
+	// 恢复所有Call Data;
+	void RestoreAllCall();
+};

+ 271 - 0
Source/OGCAssist/OGCAssist/OGCAssist.vcproj

@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="OGCAssist"
+	ProjectGUID="{3A08430B-2381-49B3-8C6B-1D733C6357D5}"
+	RootNamespace="OGCAssist"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;OGCASSIST_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<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="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;OGCASSIST_EXPORTS"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<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=".\dllmain.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="0"
+						CompileAsManaged="0"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="0"
+						CompileAsManaged="0"
+					/>
+				</FileConfiguration>
+			</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=".\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}"
+			>
+		</Filter>
+		<Filter
+			Name="Core"
+			>
+			<File
+				RelativePath=".\OGCAssist.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\OGCAssist.h"
+				>
+			</File>
+			<File
+				RelativePath=".\PipeClient.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\PipeClient.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Utility.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Utility.h"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 188 - 0
Source/OGCAssist/OGCAssist/PipeClient.cpp

@@ -0,0 +1,188 @@
+#include "StdAfx.h"
+#include "PipeClient.h"
+#include "Utility.h"
+
+#define BUFSIZE 512
+
+CPipeClient::CPipeClient(LPCTSTR lpPipeName, DWORD dwMode)
+{
+    m_hPipeInst = INVALID_HANDLE_VALUE;
+    m_bClientStop = FALSE;
+    m_dwMode = dwMode;
+    memset(m_szPipeName, 0, MAX_PATH*sizeof(TCHAR));
+    memset(m_szWriteBuff, 0, 1024*sizeof(TCHAR));
+    memset(m_szReceiveBuff, 0, 1024*sizeof(TCHAR));
+    if ( lpPipeName )
+        _stprintf_s(m_szPipeName, _T("%s"), lpPipeName);
+}
+
+CPipeClient::~CPipeClient(void)
+{
+    StopWork();
+    if ( m_hPipeInst != INVALID_HANDLE_VALUE )
+        CloseHandle(m_hPipeInst);
+}
+
+BOOL CPipeClient::StartWork()
+{
+    if ( !m_bClientStop )
+    {
+        BOOL bRet = TRUE;
+        HANDLE hConnect = CreateThread(NULL, 0, ConnectThread, this, 0, NULL);
+        HANDLE hReadMsg = CreateThread(NULL, 0, ReadMsgThread, this, 0, NULL);
+
+        if ( hConnect == NULL || hReadMsg == NULL )
+            bRet = FALSE;
+
+        if ( hConnect )
+            CloseHandle(hConnect);
+
+        if ( hReadMsg )
+            CloseHandle(hReadMsg);
+
+        return bRet;
+    }
+
+    return TRUE;
+}
+
+DWORD CPipeClient::ConnectThread(LPVOID lpParam)
+{
+    CPipeClient *pInstance = (CPipeClient*)lpParam;
+    if ( !pInstance ) 
+        return 0L;
+
+    while(!pInstance->m_bClientStop)
+    {
+        if ( pInstance->m_hPipeInst != INVALID_HANDLE_VALUE ) {
+            // 1分钟检测;
+            Sleep(60000);
+            Utility::dprintf(_T("m_hPipeInst 已存在\n"));
+            continue;
+        }
+
+        // 等待10秒;
+        if ( !WaitNamedPipe(pInstance->m_szPipeName, 10000) )
+        {// 如果管道不存在,会立即返回而不考虑超时值,所以此处仍要Sleep;
+            Utility::dprintf(_T("<%ld> WaitNamedPipe 失败\n"), Utility::g_WndInfo.dwProcessId);
+            Sleep(10000);
+            continue;
+        }
+
+        pInstance->m_hPipeInst = CreateFile(
+            pInstance->m_szPipeName,        // pipe name 
+            GENERIC_READ | GENERIC_WRITE,   // read and write access 
+            0,                              // no sharing 
+            NULL,                           // default security attributes
+            OPEN_EXISTING,                  // opens existing pipe 
+            0,                              // default attributes 
+            NULL);                          // no template file 
+
+        // 创建成功,退出;
+        if ( pInstance->m_hPipeInst != INVALID_HANDLE_VALUE ) 
+        {
+            // 管道连接成功,修改管道通信模式:message-read mode. 
+            BOOL fSuccess = SetNamedPipeHandleState( 
+                pInstance->m_hPipeInst,     // pipe handle 
+                &pInstance->m_dwMode,       // new pipe mode 
+                NULL,                       // don't set maximum bytes 
+                NULL);                      // don't set maximum time 
+
+            if (!fSuccess) {
+                Utility::dprintf(_T("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError() ); 
+                CloseHandle(pInstance->m_hPipeInst);
+            }
+        }
+        else
+        {
+            // Exit if an error other than ERROR_PIPE_BUSY occurs. 
+            if ( GetLastError() != ERROR_PIPE_BUSY ) 
+            {
+                Utility::dprintf(_T("Could not open pipe. GLE=%d\n"), GetLastError() ); 
+            }
+        }
+    }
+
+    Utility::dprintf(_T("<%ld> ConnectThread 退出\n"), Utility::g_WndInfo.dwProcessId);
+
+    return 0;
+}
+
+DWORD CPipeClient::ReadMsgThread(LPVOID lpParam)
+{
+    DWORD cbRead = 0;
+    BOOL bSuccess = FALSE;
+    TCHAR chBuf[BUFSIZE]; 
+    DWORD dwDataIndex = 0;
+    DWORD dwError = 0;
+    
+    CPipeClient *pInstance = (CPipeClient*)lpParam;
+    if ( !pInstance ) 
+        return 0L;
+
+    while(!pInstance->m_bClientStop)
+    {
+        if ( pInstance->m_hPipeInst == INVALID_HANDLE_VALUE ) {
+            Sleep(2000);
+            continue;
+        }
+
+        do 
+        { 
+            bSuccess = ReadFile( 
+                pInstance->m_hPipeInst,     // pipe handle 
+                chBuf,                      // buffer to receive reply 
+                BUFSIZE*sizeof(TCHAR),      // size of buffer 
+                &cbRead,                    // number of bytes read 
+                NULL);                      // not overlapped 
+
+            if ( !bSuccess && (dwError = GetLastError()) != ERROR_MORE_DATA )
+                break; 
+
+            Utility::dprintf(_T("读取数据:%ld, %ld, %s"), dwError, cbRead, chBuf);
+            //Utility::dprintf(_T("读取数据:%ld, %ld"), dwError, cbRead);
+#if 0
+            TCHAR szMsg[8912] = {0};
+            _stprintf_s(szMsg, _T("读取数据:%d, %ld, %ld, %s\n"), (int)bSuccess, dwError, cbRead, chBuf);
+            OutputDebugString(szMsg);
+#endif
+            // 追回数据;
+            memcpy(pInstance->m_szReceiveBuff + dwDataIndex, chBuf, cbRead);
+            dwDataIndex += cbRead;
+            Sleep(50);
+        } while ( !bSuccess );  // repeat loop if ERROR_MORE_DATA 
+
+        // 清空缓存数据;
+        dwDataIndex = 0;
+        memset(chBuf, 0, BUFSIZE*sizeof(TCHAR));
+       
+        if ( bSuccess )
+        {
+            Utility::dprintf(_T("读取到的消息=%d"), sizeof(pInstance->m_szReceiveBuff));
+            Sleep(3000);
+            Utility::dprintf(_T("读取到的消息=%s"), pInstance->m_szReceiveBuff);
+
+            // 消息处理;
+            // ...
+        }
+        else
+        {
+            Utility::dprintf(_T("ReadFile from pipe failed. GLE=%d\n"), dwError );
+            if ( dwError == ERROR_PIPE_NOT_CONNECTED || dwError == ERROR_BROKEN_PIPE)
+            {
+                CloseHandle(pInstance->m_hPipeInst);
+                pInstance->m_hPipeInst = INVALID_HANDLE_VALUE;
+            }
+
+#ifdef _DEBUG
+            Sleep(10000);
+#endif
+        }
+
+         memset(pInstance->m_szReceiveBuff, 0, BUFSIZE*sizeof(TCHAR));
+    }
+
+    Utility::dprintf(_T("<%ld> ReadMsgThread 退出\n"),Utility::g_WndInfo.dwProcessId);
+
+    return 0;
+}

+ 43 - 0
Source/OGCAssist/OGCAssist/PipeClient.h

@@ -0,0 +1,43 @@
+#pragma once
+
+#pragma region Simple communication protocol
+
+typedef enum
+{
+    CP_REQ_1,
+    CP_REP_1,
+};
+
+typedef struct _SPCP_
+{
+
+}SimpleCP, *pSimpleCP;
+
+#pragma endregion 简单通信协议
+
+class CPipeClient
+{
+public:
+    // 客户端只有PIPE_READMODE_BYTE PIPE_READMODE_MESSAGE两种模式;
+    CPipeClient(LPCTSTR lpPipeName, DWORD dwMode=PIPE_READMODE_MESSAGE);
+    ~CPipeClient(void);
+
+private:
+    HANDLE m_hPipeInst;
+    // 客户端状态;
+    BOOL m_bClientStop;
+    // 管道名称;
+    TCHAR m_szPipeName[MAX_PATH];
+    // 管道通信模式;
+    DWORD m_dwMode;
+    // 缓存区;
+    TCHAR m_szWriteBuff[1024];
+    TCHAR m_szReceiveBuff[1024];
+public:
+    BOOL StartWork();
+    void StopWork() { m_bClientStop = TRUE;Sleep(100000);}
+    // 连续管道服务器线程;
+    static DWORD WINAPI ConnectThread(LPVOID lpParam);
+    // 读取管道消息线程;
+    static DWORD WINAPI ReadMsgThread(LPVOID lpParam);
+};

+ 37 - 0
Source/OGCAssist/OGCAssist/ReadMe.txt

@@ -0,0 +1,37 @@
+========================================================================
+    动态链接库:OGCAssist 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 OGCAssist DLL。
+
+本文件概要介绍组成 OGCAssist 应用程序的
+的每个文件的内容。
+
+
+OGCAssist.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+OGCAssist.cpp
+    这是主 DLL 源文件。
+
+	此 DLL 在创建时不导出任何符号。因此,在生成此 DLL 时
+	将不会产生 .lib 文件。如果希望此项目
+	成为其他某个项目的项目依赖项,则需要
+	添加代码以从 DLL 导出某些符号,
+	以便产生一个导出库,或者,也可以在项目“属性页”对话框中的
+	“链接器”文件夹中,将“常规”属性页上的
+	“忽略输入库”属性设置为“是”。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 OGCAssist.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 84 - 0
Source/OGCAssist/OGCAssist/Utility.cpp

@@ -0,0 +1,84 @@
+#include "StdAfx.h"
+#include "Utility.h"
+#include <time.h>
+
+#define MAX_SIZE 8192
+
+namespace Utility
+{
+    // 当前DLL模块句柄;
+    HMODULE g_hDLLModule = NULL;
+    // 当前DLL内部工作者线程句柄;
+    HANDLE hWorkThreadProc = NULL;
+    // 当前DLL所在路径;
+    TCHAR g_szCurModulePath[MAX_PATH] = {0};
+    // 管道实例;
+    CPipeClient *g_pPipeClient = NULL;
+
+    // 配置文件名称;
+    TCHAR g_szConfigFile[MAX_PATH] = {0};
+    // 配置文件内容;
+    CFG_CTX g_cfgCtx;
+    // DLL所在进程窗口信息;
+    WndInfo g_WndInfo;
+
+    //////////////////////////////////////////////////////////////////////////
+    // 全局函数;
+    // 获取配置文件内容;
+    void GetConfigContent()
+    {
+#if 0
+        // 获取dll的目录;
+        TCHAR szDrive[MAX_PATH] = { 0 };
+        TCHAR szDir[MAX_PATH] = { 0 };
+        TCHAR szExt[MAX_PATH] = { 0 };
+        TCHAR szFna[MAX_PATH] = { 0 };
+        ::GetModuleFileName(g_hDLLModule, g_szCurModulePath, sizeof(g_szCurModulePath) / sizeof(TCHAR));
+        _tsplitpath_s(g_szCurModulePath, szDrive, szDir, szFna, szExt);
+        _tcscpy_s(g_szCurModulePath, szDrive);
+        _tcscat_s(g_szCurModulePath, szDir);
+        // 设置配置文件;
+        _stprintf_s(g_szConfigFile, _T("%s%s"), g_szCurModulePath, _T("Assist.ini"));
+
+        // 读取配置文件;
+        TCHAR szValue[MAX_PATH] = {0};
+        GetPrivateProfileString(_T("Windows"), _T("Title"), _T(""), g_cfgCtx.szWindowTitel, MAX_PATH, g_szConfigFile);
+        GetPrivateProfileString(_T("Pipe"), _T("Name"), _T("OGCAssist"), szValue, MAX_PATH, g_szConfigFile);
+        _stprintf_s(g_cfgCtx.szPipeName, _T("\\\\.\\pipe\\%s"), szValue);
+        GetPrivateProfileString(_T("Process"), _T("Name"), _T("Dome.exe"), g_cfgCtx.szWndProcessName, MAX_PATH, g_szConfigFile);
+#else
+		_stprintf_s(g_cfgCtx.szPipeName, _T("\\\\.\\pipe\\%s"), _T("OGCAssist"));
+#endif
+    }
+
+    void FreeLibraryAndExit()
+    {
+        if ( g_pPipeClient )
+            delete g_pPipeClient;
+        g_pPipeClient = NULL;
+
+        if ( g_hDLLModule )
+            FreeLibraryAndExitThread(g_hDLLModule, 0);
+    }
+
+    void dprintf(TCHAR* pszStr, ...)
+    {
+        TCHAR szData[MAX_SIZE] = {0};
+        // 获取今年年份;
+        __time64_t gmt = time(NULL);// 获取当前日历时间(1900-01-01开始的Unix时间戳);
+        struct tm gmtm = { 0 };
+        localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
+#if _MSC_VER >= 1200 && _MSC_VER < 1500
+        sprintf(szData, _T("[Assist] %04d-%02d-%02d %02d:%02d:%02d "), gmtm.tm_year + 1900, gmtm.tm_mon + 1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec);
+#else
+        _stprintf_s(szData, _T("[Assist] %04d-%02d-%02d %02d:%02d:%02d "), gmtm.tm_year + 1900, gmtm.tm_mon + 1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec);
+#endif
+        int len = _tcslen(szData)*sizeof(TCHAR);
+        va_list args;
+        va_start(args, pszStr);
+        _vsntprintf_s(szData + len, MAX_SIZE - len, MAX_SIZE - len, pszStr, args);
+        va_end(args);
+        _tcscat_s(szData, _T("\n"));
+        OutputDebugString(szData);
+    }
+};

+ 72 - 0
Source/OGCAssist/OGCAssist/Utility.h

@@ -0,0 +1,72 @@
+#pragma once
+
+#include "PipeClient.h"
+
+namespace Utility
+{
+#pragma region 定义的全局结构体;
+    // 配置文件内容;
+    typedef struct __CFG_CONTENT__
+    {
+        // 窗口标题;
+        TCHAR szWindowTitel[MAX_PATH];
+        // 窗口进程名称(防止名称一样);
+        TCHAR szWndProcessName[MAX_PATH];
+        // 管道名称;
+        TCHAR szPipeName[MAX_PATH];
+
+        __CFG_CONTENT__()
+        {
+            memset(szWindowTitel, 0, MAX_PATH*sizeof(TCHAR));
+            memset(szWndProcessName, 0, MAX_PATH*sizeof(TCHAR));
+            memset(szPipeName, 0, MAX_PATH*sizeof(TCHAR));
+        }
+    }CFG_CTX, *pCFG_CTX;
+
+    // DLL所在窗口信息;
+    typedef struct __WND_INFO__
+    {
+        // DLL所在进程窗口句柄;
+        HWND hWnd;
+        // 窗口名称;
+        TCHAR szWindowTitle[MAX_PATH];
+        // DLL所在进程ID;
+        DWORD dwProcessId;
+
+        __WND_INFO__()
+        {
+            hWnd = NULL;
+            dwProcessId = 0;
+            memset(szWindowTitle, 0, MAX_PATH*sizeof(TCHAR));
+        }
+    }WndInfo, *pWndInfo;
+#pragma endregion
+
+#pragma region 全局变量;
+    // 当前DLL模块句柄;
+    extern HMODULE g_hDLLModule;
+    // 当前DLL内部工作者线程句柄;
+    extern HANDLE hWorkThreadProc;
+    // 当前DLL所在路径;
+    extern TCHAR g_szCurModulePath[MAX_PATH];
+    // 管道实例;
+    extern CPipeClient *g_pPipeClient;
+    // 配置文件名称;
+    extern TCHAR g_szConfigFile[MAX_PATH];
+    // 配置文件内容;
+    extern CFG_CTX g_cfgCtx;
+    // DLL所在窗口信息;
+    extern WndInfo g_WndInfo;
+#pragma endregion
+
+#pragma region 全局函数
+    //////////////////////////////////////////////////////////////////////////
+    // 全局函数;
+    // 获取配置文件内容;
+    void GetConfigContent();
+    // 卸载DLL;
+    void FreeLibraryAndExit();
+    // Debug日志输出;
+    void dprintf(TCHAR* pszStr, ...);
+#pragma endregion
+};

+ 55 - 0
Source/OGCAssist/OGCAssist/dllmain.cpp

@@ -0,0 +1,55 @@
+// dllmain.cpp : 定义 DLL 应用程序的入口点。
+#include "stdafx.h"
+#include "PipeClient.h"
+#include "Utility.h"
+#include "OGCAssist.h"
+
+DWORD WINAPI WorkThreadProc(LPVOID lParam)
+{
+	// 注入成功后,启动管道进行通信;
+	if ( Utility::g_pPipeClient == NULL )
+	{
+		Utility::g_pPipeClient = new CPipeClient(Utility::g_cfgCtx.szPipeName);
+		Utility::g_pPipeClient->StartWork();
+	}
+
+	Assist::InitCallData();
+	if ( !Assist::HijackedAllCall() )
+	{
+		// 劫持失败要通知服务端;
+		return -1;
+	}
+
+	//::MessageBox(NULL, _T("劫持成功"), _T(""), MB_OK);
+	Utility::dprintf(_T("劫持成功\n"));
+
+	WaitForSingleObject(Utility::hWorkThreadProc,INFINITE);
+
+	// 恢复劫持数据;
+	Assist::RestoreAllCall();
+
+	// 主线程结束,DLL自我卸载;
+	Utility::FreeLibraryAndExit();
+
+	return 0;
+}
+
+BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
+{
+	switch (ul_reason_for_call)
+	{
+	case DLL_PROCESS_ATTACH:
+		{
+			Utility::dprintf(_T("注入\n"));
+			Utility::g_hDLLModule = hModule;
+			Utility::GetConfigContent();
+			Utility::hWorkThreadProc = CreateThread(NULL, 0, WorkThreadProc, NULL, 0, NULL);
+		}
+	case DLL_THREAD_ATTACH:
+	case DLL_THREAD_DETACH:
+	case DLL_PROCESS_DETACH:
+		break;
+	}
+	return TRUE;
+}
+

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

@@ -0,0 +1,8 @@
+// stdafx.cpp : 只包括标准包含文件的源文件
+// OGCAssist.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+// TODO: 在 STDAFX.H 中
+// 引用任何所需的附加头文件,而不是在此文件中引用

+ 16 - 0
Source/OGCAssist/OGCAssist/stdafx.h

@@ -0,0 +1,16 @@
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN             // 从 Windows 头中排除极少使用的资料
+// Windows 头文件:
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h> 
+
+// TODO: 在此处引用程序需要的其他头文件

+ 24 - 0
Source/OGCAssist/OGCAssist/targetver.h

@@ -0,0 +1,24 @@
+#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