205 lines
5.2 KiB
C++
205 lines
5.2 KiB
C++
#include "Shlwapi.h"
|
||
#include "framework.h"
|
||
#include <string.h>
|
||
#include <strsafe.h>
|
||
#include <wchar.h>
|
||
|
||
#include "util.h"
|
||
|
||
#pragma comment(lib, "shlwapi")
|
||
#pragma comment(lib, "Version.lib")
|
||
|
||
using namespace std;
|
||
|
||
int GetWeChatPath(wchar_t *path);
|
||
int GetWeChatWinDLLPath(wchar_t *path);
|
||
int GetWeChatVersion(wchar_t *version);
|
||
bool GetFileVersion(const wchar_t *filePath, wchar_t *version);
|
||
|
||
int GetWeChatPath(wchar_t *path)
|
||
{
|
||
int ret = -1;
|
||
HKEY hKey = NULL;
|
||
// HKEY_CURRENT_USER\Software\Tencent\WeChat InstallPath = xx
|
||
if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, L"Software\\Tencent\\WeChat", &hKey)) {
|
||
ret = GetLastError();
|
||
return ret;
|
||
}
|
||
|
||
DWORD Type = REG_SZ;
|
||
DWORD cbData = MAX_PATH * sizeof(WCHAR);
|
||
if (ERROR_SUCCESS != RegQueryValueEx(hKey, L"InstallPath", 0, &Type, (LPBYTE)path, &cbData)) {
|
||
ret = GetLastError();
|
||
goto __exit;
|
||
}
|
||
|
||
if (path != NULL) {
|
||
PathAppend(path, WECHAREXE);
|
||
}
|
||
|
||
__exit:
|
||
if (hKey) {
|
||
RegCloseKey(hKey);
|
||
}
|
||
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
int GetWeChatWinDLLPath(wchar_t *path)
|
||
{
|
||
int ret = GetWeChatPath(path);
|
||
if (ret != ERROR_SUCCESS) {
|
||
return ret;
|
||
}
|
||
|
||
PathRemoveFileSpecW(path);
|
||
PathAppendW(path, WECHATWINDLL);
|
||
if (!PathFileExists(path)) {
|
||
// 微信从(大约)3.7开始,增加了一层版本目录: [3.7.0.29]
|
||
PathRemoveFileSpec(path);
|
||
_wfinddata_t findData;
|
||
wstring dir = wstring(path) + L"\\[*.*";
|
||
intptr_t handle = _wfindfirst(dir.c_str(), &findData);
|
||
if (handle == -1) { // 检查是否成功
|
||
return -1;
|
||
}
|
||
wstring dllPath = wstring(path) + L"\\" + findData.name;
|
||
wcscpy_s(path, MAX_PATH, dllPath.c_str());
|
||
PathAppend(path, WECHATWINDLL);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
int GetWeChatVersion(wchar_t *version)
|
||
{
|
||
WCHAR Path[MAX_PATH] = { 0 };
|
||
|
||
int ret = GetWeChatWinDLLPath(Path);
|
||
if (ret != ERROR_SUCCESS) {
|
||
return ret;
|
||
}
|
||
|
||
ret = GetFileVersion(Path, version);
|
||
|
||
return ret;
|
||
}
|
||
|
||
bool GetFileVersion(const wchar_t *filePath, wchar_t *version)
|
||
{
|
||
if (wcslen(filePath) > 0 && PathFileExists(filePath)) {
|
||
VS_FIXEDFILEINFO *pVerInfo = NULL;
|
||
DWORD dwTemp, dwSize;
|
||
BYTE *pData = NULL;
|
||
UINT uLen;
|
||
|
||
dwSize = GetFileVersionInfoSize(filePath, &dwTemp);
|
||
if (dwSize == 0) {
|
||
return false;
|
||
}
|
||
|
||
pData = new BYTE[dwSize + 1];
|
||
if (pData == NULL) {
|
||
return false;
|
||
}
|
||
|
||
if (!GetFileVersionInfo(filePath, 0, dwSize, pData)) {
|
||
delete[] pData;
|
||
return false;
|
||
}
|
||
|
||
if (!VerQueryValue(pData, TEXT("\\"), (void **)&pVerInfo, &uLen)) {
|
||
delete[] pData;
|
||
return false;
|
||
}
|
||
|
||
DWORD verMS = pVerInfo->dwFileVersionMS;
|
||
DWORD verLS = pVerInfo->dwFileVersionLS;
|
||
DWORD major = HIWORD(verMS);
|
||
DWORD minor = LOWORD(verMS);
|
||
DWORD build = HIWORD(verLS);
|
||
DWORD revision = LOWORD(verLS);
|
||
delete[] pData;
|
||
|
||
StringCbPrintf(version, 0x20, TEXT("%d.%d.%d.%d"), major, minor, build, revision);
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
int OpenWeChat(DWORD *pid)
|
||
{
|
||
int ret = -1;
|
||
STARTUPINFO si = { sizeof(si) };
|
||
PROCESS_INFORMATION pi = { 0 };
|
||
|
||
WCHAR Path[MAX_PATH] = { 0 };
|
||
ret = GetWeChatPath(Path);
|
||
if (ERROR_SUCCESS != ret) {
|
||
return ret;
|
||
}
|
||
|
||
if (!CreateProcess(NULL, Path, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
|
||
ret = GetLastError();
|
||
return ret;
|
||
}
|
||
|
||
CloseHandle(pi.hThread);
|
||
CloseHandle(pi.hProcess);
|
||
|
||
*pid = pi.dwProcessId;
|
||
|
||
ret = ERROR_SUCCESS;
|
||
|
||
return ret;
|
||
}
|
||
|
||
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
|
||
{
|
||
DWORD strLength = GET_DWORD(address + 4);
|
||
if (strLength == 0) {
|
||
return 0;
|
||
} else if (strLength > buffer_size) {
|
||
strLength = buffer_size - 1;
|
||
}
|
||
|
||
wmemcpy_s(buffer, strLength + 1, GET_WSTRING(address), strLength + 1);
|
||
|
||
return strLength;
|
||
}
|
||
|
||
DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address)
|
||
{
|
||
DWORD value = 0;
|
||
|
||
unsigned char data[4] = { 0 };
|
||
if (ReadProcessMemory(hProcess, (LPVOID)address, data, 4, 0)) {
|
||
value = data[0] & 0xFF;
|
||
value |= ((data[1] << 8) & 0xFF00);
|
||
value |= ((data[2] << 16) & 0xFF0000);
|
||
value |= ((data[3] << 24) & 0xFF000000);
|
||
}
|
||
|
||
return value;
|
||
}
|
||
|
||
wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address)
|
||
{
|
||
wstring value = L"";
|
||
|
||
DWORD strAddress = GetMemoryIntByAddress(hProcess, address);
|
||
DWORD strLen = GetMemoryIntByAddress(hProcess, address + 0x4);
|
||
if (strLen > 500)
|
||
return value;
|
||
|
||
wchar_t cValue[500] = { 0 };
|
||
memset(cValue, 0, sizeof(cValue) / sizeof(wchar_t));
|
||
if (ReadProcessMemory(hProcess, (LPVOID)strAddress, cValue, (strLen + 1) * 2, 0)) {
|
||
value = wstring(cValue);
|
||
}
|
||
|
||
return value;
|
||
}
|