pch.cpp 10.9 KB
Newer Older
L
ljc545w 已提交
1 2 3
// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"
L
ljc545w 已提交
4
#include "io.h"
L
ljc545w 已提交
5
#include <functional>
L
ljc545w 已提交
6 7

// 当使用预编译的头时,需要使用此源文件,编译才能成功。
L
ljc545w 已提交
8 9

/*
L
ljc545w 已提交
10 11 12
 * 创建一个控制台窗口
 * return:BOOL,成功返回`0`,失败返回`1`
 */
L
ljc545w 已提交
13 14 15 16
BOOL CreateConsole(void)
{
    if (AllocConsole())
    {
L
ljc545w 已提交
17
        AttachConsole(GetCurrentProcessId());
L
ljc545w 已提交
18
        FILE *retStream;
L
ljc545w 已提交
19
        freopen_s(&retStream, "CONOUT$", "w", stdout);
L
ljc545w 已提交
20 21
        if (!retStream)
            throw std::runtime_error("Stdout redirection failed.");
L
ljc545w 已提交
22
        freopen_s(&retStream, "CONOUT$", "w", stderr);
L
ljc545w 已提交
23 24
        if (!retStream)
            throw std::runtime_error("Stderr redirection failed.");
L
ljc545w 已提交
25 26 27 28 29
        return 0;
    }
    return 1;
}

L
ljc545w 已提交
30
/*
L
ljc545w 已提交
31 32 33
 * 获取`WeChatWin.dll`基址
 * return:DWORD,`WeChatWin.dll`模块基址
 */
L
ljc545w 已提交
34 35
DWORD GetWeChatWinBase()
{
L
ljc545w 已提交
36 37 38
    return (DWORD)GetModuleHandleA("WeChatWin.dll");
}

L
ljc545w 已提交
39
BOOL FindOrCreateDirectory(const wchar_t *pszPath)
L
ljc545w 已提交
40
{
L
ljc545w 已提交
41 42 43
    string dir = unicode_to_gb2312((wchar_t *)pszPath);
    char last_char = dir.back();
    if (last_char != '\\')
L
ljc545w 已提交
44
    {
L
ljc545w 已提交
45
        dir += '\\';
L
ljc545w 已提交
46
    }
L
ljc545w 已提交
47 48 49
    if (!_access(dir.c_str(), 0))
        return true;
    return MakeSureDirectoryPathExists(dir.c_str());
L
ljc545w 已提交
50 51
}

L
ljc545w 已提交
52
/*
L
ljc545w 已提交
53 54
 * 将宽字节字符串转换成`std::string`
 */
L
ljc545w 已提交
55
string unicode_to_gb2312(wchar_t *wchar)
L
ljc545w 已提交
56
{
L
ljc545w 已提交
57
    wchar_t *wText = wchar;
L
ljc545w 已提交
58 59 60 61 62
    DWORD dwNum = WideCharToMultiByte(CP_ACP, NULL, wText, -1, NULL, 0, NULL, FALSE);
    char *psText = new char[dwNum + 1];
    WideCharToMultiByte(CP_ACP, NULL, wText, -1, psText, dwNum, NULL, FALSE);
    psText[dwNum] = '\0';
    string szDst(psText);
L
ljc545w 已提交
63
    delete[] psText;
L
ljc545w 已提交
64
    return szDst;
L
ljc545w 已提交
65 66
}

L
ljc545w 已提交
67
/*
L
ljc545w 已提交
68 69
 * 将UTF8编码数据转换为GBK编码
 */
L
ljc545w 已提交
70
string utf8_to_gb2312(const char *strUTF8)
L
ljc545w 已提交
71
{
L
ljc545w 已提交
72 73
    int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8, -1, NULL, 0);
    wchar_t *wszGBK = new wchar_t[len + 1];
L
ljc545w 已提交
74
    memset(wszGBK, 0, len * 2 + 2);
L
ljc545w 已提交
75
    MultiByteToWideChar(CP_UTF8, 0, strUTF8, -1, wszGBK, len);
L
ljc545w 已提交
76 77

    len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
L
ljc545w 已提交
78
    char *szGBK = new char[len + 1];
L
ljc545w 已提交
79 80
    memset(szGBK, 0, len + 1);
    WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL);
L
ljc545w 已提交
81 82 83
    string strTemp(szGBK);
    delete[] szGBK;
    delete[] wszGBK;
L
ljc545w 已提交
84 85 86
    return strTemp;
}

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
string gb2312_to_utf8(const char *strGB2312)
{
    int len = MultiByteToWideChar(CP_ACP, 0, strGB2312, -1, NULL, 0);
    wchar_t *wszGBK = new wchar_t[len + 1];
    memset(wszGBK, 0, len * 2 + 2);
    MultiByteToWideChar(CP_ACP, 0, strGB2312, -1, wszGBK, len);

    len = WideCharToMultiByte(CP_UTF8, 0, wszGBK, -1, NULL, 0, NULL, NULL);
    char *szGBK = new char[len + 1];
    memset(szGBK, 0, len + 1);
    WideCharToMultiByte(CP_UTF8, 0, wszGBK, -1, szGBK, len, NULL, NULL);
    string strTemp(szGBK);
    delete[] szGBK;
    delete[] wszGBK;
    return strTemp;
}

L
ljc545w 已提交
104 105 106 107 108 109 110 111 112 113 114 115
wstring gb2312_to_unicode(const char *buffer)
{
    int c_size = MultiByteToWideChar(CP_ACP, 0, buffer, -1, 0, 0);
    wchar_t *temp = new wchar_t[c_size + 1];
    MultiByteToWideChar(CP_ACP, 0, buffer, -1, temp, c_size);
    temp[c_size] = L'\0';
    wstring ret(temp);
    delete[] temp;
    temp = NULL;
    return ret;
}

L
ljc545w 已提交
116
/*
L
ljc545w 已提交
117
 * 将UTF8编码数据转换为UNICODE编码
L
ljc545w 已提交
118
 */
L
ljc545w 已提交
119 120 121 122 123 124 125 126 127 128 129 130
wstring utf8_to_unicode(const char *buffer)
{
    int c_size = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, 0, 0);
    wchar_t *temp = new wchar_t[c_size + 1];
    MultiByteToWideChar(CP_UTF8, 0, buffer, -1, temp, c_size);
    temp[c_size] = L'\0';
    wstring ret(temp);
    delete[] temp;
    temp = NULL;
    return ret;
}

L
ljc545w 已提交
131 132 133 134 135 136 137 138 139 140 141 142
string unicode_to_utf8(wchar_t *wstr)
{
    int c_size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, FALSE);
    char *buffer = new char[c_size + 1];
    WideCharToMultiByte(CP_UTF8, 0, wstr, -1, buffer, c_size, NULL, FALSE);
    buffer[c_size] = '\0';
    string str(buffer);
    delete[] buffer;
    buffer = NULL;
    return str;
}

L
ljc545w 已提交
143
/*
L
ljc545w 已提交
144 145 146 147 148 149
 * 对任意地址添加HOOK
 * dwHookAddr:HOOK的目标地址
 * dwJmpAddress:跳转到的地址
 * originalRecieveCode:保存旧指令的数组
 * return:void
 */
L
ljc545w 已提交
150
void HookAnyAddress(DWORD dwHookAddr, LPVOID dwJmpAddress, char *originalRecieveCode)
L
ljc545w 已提交
151 152
{
    //组装跳转数据
L
ljc545w 已提交
153
    BYTE jmpCode[5] = {0};
L
ljc545w 已提交
154 155 156
    jmpCode[0] = 0xE9;

    //计算偏移
L
ljc545w 已提交
157
    *(DWORD *)&jmpCode[1] = (DWORD)dwJmpAddress - dwHookAddr - 5;
L
ljc545w 已提交
158 159 160 161 162 163 164 165 166

    // 保存以前的属性用于还原
    DWORD OldProtext = 0;

    // 因为要往代码段写入数据,又因为代码段是不可写的,所以需要修改属性
    VirtualProtect((LPVOID)dwHookAddr, 5, PAGE_EXECUTE_READWRITE, &OldProtext);
    ReadProcessMemory(GetCurrentProcess(), (LPVOID)dwHookAddr, originalRecieveCode, 5, 0);

    //写入自己的代码
L
ljc545w 已提交
167
    memcpy((void *)dwHookAddr, jmpCode, 5);
L
ljc545w 已提交
168 169 170 171 172

    // 执行完了操作之后需要进行还原
    VirtualProtect((LPVOID)dwHookAddr, 5, OldProtext, &OldProtext);
}

L
ljc545w 已提交
173
/*
L
ljc545w 已提交
174 175 176 177 178
 * 对任意地址取消HOOK
 * dwHookAddr:HOOK的目标地址
 * originalRecieveCode:保存旧指令的数组
 * return:void
 */
L
ljc545w 已提交
179
void UnHookAnyAddress(DWORD dwHookAddr, char *originalRecieveCode)
L
ljc545w 已提交
180 181 182 183 184 185 186
{
    DWORD OldProtext = 0;
    VirtualProtect((LPVOID)dwHookAddr, 5, PAGE_EXECUTE_READWRITE, &OldProtext);
    WriteProcessMemory(GetCurrentProcess(), (LPVOID)dwHookAddr, originalRecieveCode, 5, 0);
    VirtualProtect((LPVOID)dwHookAddr, 5, OldProtext, &OldProtext);
}

L
ljc545w 已提交
187
/*
L
ljc545w 已提交
188 189 190
 * 取消所有HOOK
 * return:void
 */
L
ljc545w 已提交
191 192
void UnHookAll()
{
193
    UnHookLogMsgInfo();
L
ljc545w 已提交
194
    UnHookReceiveMessage();
L
ljc545w 已提交
195 196
    UnHookFriendStatusCode();
    UnHookSearchContact();
L
ljc545w 已提交
197 198
    UnHookVoiceMsg();
    UnHookImageMsg();
L
ljc545w 已提交
199
    UnHookH5ExtBuf();
200
    UnHookQrcodeImage();
L
ljc545w 已提交
201
    UnHookA8KeyBuf();
L
ljc545w 已提交
202
    return;
L
ljc545w 已提交
203 204
}

L
ljc545w 已提交
205
/*
L
ljc545w 已提交
206 207 208 209 210 211
 * 将单字符替换为指定的字符串
 * source:源字符串
 * replaced:被替换的单字符
 * replaceto:替换成的字符串
 * return:std::wstring,替换后的字符串
 */
L
ljc545w 已提交
212 213
wstring wreplace(wstring source, wchar_t replaced, wstring replaceto)
{
L
ljc545w 已提交
214
    wstring temp = L"";
L
ljc545w 已提交
215 216 217 218 219
    wchar_t *buffer = (wchar_t *)source.c_str();
    for (unsigned int i = 0; i < source.length(); i++)
    {
        if (buffer[i] == replaced)
        {
L
ljc545w 已提交
220 221 222 223 224 225
            temp += replaceto;
            continue;
        }
        temp += buffer[i];
    }
    return temp;
L
ljc545w 已提交
226 227
}

L
ljc545w 已提交
228
/*
L
ljc545w 已提交
229 230
 * 获取当前时间
 */
L
ljc545w 已提交
231 232
wstring GetTimeW(long long timestamp)
{
L
ljc545w 已提交
233 234 235 236 237 238 239 240 241 242 243
    wchar_t *wstr = new wchar_t[20];
    memset(wstr, 0, 20 * 2);
    // time_t cTime = time(NULL);
    tm tm_out;
    localtime_s(&tm_out, &timestamp);
    swprintf_s(wstr, 20, L"%04d-%02d-%02d %02d:%02d:%02d",
               1900 + tm_out.tm_year, tm_out.tm_mon + 1, tm_out.tm_mday,
               tm_out.tm_hour, tm_out.tm_min, tm_out.tm_sec);
    wstring strTimeW(wstr);
    delete[] wstr;
    return strTimeW;
L
ljc545w 已提交
244 245
}

L
ljc545w 已提交
246 247
void PrintProcAddr()
{
L
ljc545w 已提交
248
    CreateConsole();
L
ljc545w 已提交
249
    printf("WeChatVersion %s\n", GetWeChatVerStr().c_str());
L
ljc545w 已提交
250 251 252 253 254 255 256 257
    printf("SendImage 0x%08X\n", (DWORD)SendImage);
    printf("SendText 0x%08X\n", (DWORD)SendText);
    printf("SendFile 0x%08X\n", (DWORD)SendFile);
    printf("SendAtText 0x%08X\n", (DWORD)SendAtText);
    printf("GetFriendList 0x%08X\n", (DWORD)GetFriendList);
    printf("GetUserInfoByWxId 0x%08X\n", (DWORD)GetUserInfoByWxId);
    printf("SendArticle 0x%08X\n", (DWORD)SendArticle);
    printf("SendCard 0x%08X\n", (DWORD)SendCard);
L
ljc545w 已提交
258 259 260 261 262
    void(__stdcall * check_friend_status)(wchar_t *) = CheckFriendStatus;
    printf("CheckFriendStatus 0x%08X\n", (DWORD)check_friend_status);
    BOOL(__stdcall * get_chatroom_members)
    (wchar_t *) = GetChatRoomMembers;
    printf("GetChatRoomMembers 0x%08X\n", (DWORD)get_chatroom_members);
L
ljc545w 已提交
263
    printf("ExecuteSql 0x%08X\n", (DWORD)ExecuteSQL);
264
    printf("BackupSQLiteDB 0x%08X\n", (DWORD)BackupSQLiteDB);
L
ljc545w 已提交
265 266 267
    printf("VerifyFriendApply 0x%08X\n", (DWORD)VerifyFriendApply);
    printf("AddFriendByV3 0x%08X\n", (DWORD)AddFriendByV3);
    printf("AddFriendByWxid 0x%08X\n", (DWORD)AddFriendByWxid);
L
ljc545w 已提交
268
    printf("AddBrandContact 0x%08X\n", (DWORD)AddBrandContact);
L
ljc545w 已提交
269 270
    void *(*select_data)(DWORD, const char *, void *) = SelectData;
    printf("SelectData 0x%08X\n", (DWORD)select_data);
L
ljc545w 已提交
271 272
    void *(__stdcall * search_contact_by_net)(wchar_t *) = SearchContactByNet;
    printf("SearchContactByNet 0x%08X\n", (DWORD)search_contact_by_net);
L
ljc545w 已提交
273 274 275 276 277
    printf("AddChatRoomMember 0x%08X\n", (DWORD)AddChatRoomMember);
    printf("DelChatRoomMember 0x%08X\n", (DWORD)DelChatRoomMember);
    printf("SetChatRoomAnnouncement 0x%08X\n", (DWORD)SetChatRoomAnnouncement);
    printf("SetChatRoomSelfNickname 0x%08X\n", (DWORD)SetChatRoomSelfNickname);
    printf("SetChatRoomName 0x%08X\n", (DWORD)SetChatRoomName);
L
ljc545w 已提交
278 279 280 281
    printf("OpenBrowser 0x%08X\n", (DWORD)OpenBrowser);
    BOOL(__stdcall * get_history_public_msg)
    (wchar_t *, wchar_t *) = GetHistoryPublicMsg;
    printf("GetHistoryPublicMsg 0x%08X\n", (DWORD)get_history_public_msg);
L
ljc545w 已提交
282 283 284
    BOOL(__stdcall * get_a8_key)
    (wchar_t *) = GetA8Key;
    printf("GetA8Key 0x%08X\n", (DWORD)get_a8_key);
L
ljc545w 已提交
285 286 287 288
}

BOOL ProcessIsWeChat()
{
L
ljc545w 已提交
289
    char szFileFullPath[MAX_PATH] = {0};
L
ljc545w 已提交
290 291
    GetModuleFileNameA(NULL, szFileFullPath, MAX_PATH);
    int length = ::strlen(szFileFullPath);
L
ljc545w 已提交
292 293 294 295
    string szFile(szFileFullPath);
    size_t pos = szFile.find_last_of('\\');
    string szProcessName = szFile.substr(pos + 1, szFile.length() - pos - 1);
    if (szProcessName == "WeChat.exe")
L
ljc545w 已提交
296 297 298
    {
        return TRUE;
    }
L
ljc545w 已提交
299
    return FALSE;
L
ljc545w 已提交
300 301
}

L
ljc545w 已提交
302 303
DWORD OffsetFromIdaAddr(DWORD idaAddr)
{
L
ljc545w 已提交
304
    return idaAddr - IDA_BASE;
L
ljc545w 已提交
305
}
L
ljc545w 已提交
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354

void SignalHandler(const char *data, size_t size)
{
#ifdef USE_SOCKET
    string dllname = "SWeChatRobot";
#else
    string dllname = "DWeChatRobot";
#endif // USE_SOCKET
    char szFileFullPath[MAX_PATH] = {0};
    HMODULE hd = GetModuleHandleA(dllname.c_str());
    GetModuleFileNameA(hd, szFileFullPath, MAX_PATH);
    string szFile(szFileFullPath);
    size_t pos = szFile.find_last_of('\\');
    string szFilePath = szFile.substr(0, pos + 1);
    std::string glog_file = szFilePath + "\\log\\error.log";
    std::ofstream fs(glog_file, std::ios::app);
    std::string str = std::string(data, size);
    fs << str;
    fs.close();
    LOG(INFO) << str;
    google::ShutdownGoogleLogging();
}

void gLogInit()
{
#ifdef USE_SOCKET
    string dllname = "SWeChatRobot";
#else
    string dllname = "DWeChatRobot";
#endif // USE_SOCKET
#ifdef _DEBUG
    FLAGS_colorlogtostderr = true; // log信息区分颜色
    FLAGS_logtostderr = 1;
#endif
    google::SetStderrLogging(google::GLOG_INFO);  // 输出log的最低等级是 INFO (可以设置为WARNING或者更高)
    google::InstallFailureSignalHandler();        // 配置安装程序崩溃失败信号处理器
    google::InstallFailureWriter(&SignalHandler); // 安装配置程序失败信号的信息打印过程,设置回调函数
    google::InitGoogleLogging(dllname.c_str());
#ifndef _DEBUG
    char szFileFullPath[MAX_PATH] = {0};
    HMODULE hd = GetModuleHandleA(dllname.c_str());
    GetModuleFileNameA(hd, szFileFullPath, MAX_PATH);
    string szFile(szFileFullPath);
    size_t pos = szFile.find_last_of('\\');
    string szFilePath = szFile.substr(0, pos + 1) + "log\\";
    FindOrCreateDirectory(gb2312_to_unicode(szFilePath.c_str()).c_str());
    google::SetLogDestination(google::GLOG_INFO, szFilePath.c_str());
#endif
}