未验证 提交 8ccdac23 编写于 作者: J Jack Li 提交者: GitHub

Merge pull request #86 from ljc545w/add/http_support

完善http接口
......@@ -11,10 +11,10 @@
vector<DbInfoStruct> dbs;
/*
* 根据数据库名从`dbs`中检索数据库句柄
* dbname:数据库名
* return:DWORD,如果检索成功,返回数据库句柄,否则返回`0`
*/
* 根据数据库名从`dbs`中检索数据库句柄
* dbname:数据库名
* return:DWORD,如果检索成功,返回数据库句柄,否则返回`0`
*/
DWORD GetDbHandleByDbName(wchar_t *dbname)
{
if (dbs.size() == 0)
......@@ -28,9 +28,9 @@ DWORD GetDbHandleByDbName(wchar_t *dbname)
}
/*
* 供外部调用的获取数据库信息接口
* return:DWORD,`dbs`首个成员地址
*/
* 供外部调用的获取数据库信息接口
* return:DWORD,`dbs`首个成员地址
*/
#ifndef USE_SOCKET
DWORD GetDbHandlesRemote()
{
......@@ -41,9 +41,9 @@ DWORD GetDbHandlesRemote()
#endif
/*
* 获取数据库信息的具体实现
* return:void
*/
* 获取数据库信息的具体实现
* return:void
*/
vector<void *> GetDbHandles()
{
dbs.clear();
......@@ -134,7 +134,7 @@ vector<void *> GetDbHandles()
}
#endif
vector<void *> ret_array;
for (auto it : dbs)
ret_array.push_back(&it);
for (unsigned int i = 0; i < dbs.size() - 1; i++)
ret_array.push_back(&dbs[i]);
return ret_array;
}
......@@ -9,54 +9,58 @@ static DWORD WeChatWinBase = GetWeChatWinBase();
static DWORD HookImageMsgAddr = WeChatWinBase + HookImageMsgAddrOffset;
static DWORD HookImageMsgNextCall = WeChatWinBase + HookImageMsgNextCallOffset;
static DWORD HookImageMsgJmpBackAddr = HookImageMsgAddr + 0x5;
static char ImageMsgOldAsm[5] = { 0 };
static char ImageMsgOldAsm[5] = {0};
static wstring savepath = L"";
void SaveImageMsg(unsigned char* buffer, int length, DWORD msgHandle) {
int l_datpath = *(int*)(msgHandle + 0x4) + 1;
wchar_t* datpath = new wchar_t[l_datpath];
memcpy(datpath, (void*)(*(DWORD*)msgHandle), l_datpath * 2);
wstring wdatpath(datpath);
delete[] datpath;
datpath = NULL;
if (wdatpath.find(L"_t.dat") != wstring::npos) {
return;
}
int pos_begin = wdatpath.find_last_of(L"\\") + 1;
int pos_end = wdatpath.find_last_of(L".");
wstring filename = wdatpath.substr(pos_begin, pos_end - pos_begin);
void SaveImageMsg(unsigned char *buffer, int length, DWORD msgHandle)
{
int l_datpath = *(int *)(msgHandle + 0x4) + 1;
wchar_t *datpath = new wchar_t[l_datpath];
memcpy(datpath, (void *)(*(DWORD *)msgHandle), l_datpath * 2);
wstring wdatpath(datpath);
delete[] datpath;
datpath = NULL;
if (wdatpath.find(L"_t.dat") != wstring::npos)
{
return;
}
int pos_begin = wdatpath.find_last_of(L"\\") + 1;
int pos_end = wdatpath.find_last_of(L".");
wstring filename = wdatpath.substr(pos_begin, pos_end - pos_begin);
unsigned char magic_head[4] = { 0 };
wchar_t postfix[5] = { 0 };
memcpy(magic_head, buffer, 3);
if (magic_head[0] == 137 && magic_head[1] == 80 && magic_head[2] == 78)
{
lstrcpy(postfix,L".png");
}
else if (magic_head[0] == 71 && magic_head[1] == 73 && magic_head[2] == 70)
{
lstrcpy(postfix, L".gif");
}
else if (magic_head[0] == 255 && magic_head[1] == 216 && magic_head[2] == 255)
{
lstrcpy(postfix, L".jpg");
}
else {
lstrcpy(postfix, L"");
}
wstring filepath = savepath + filename + postfix;
HANDLE hFile = CreateFile(filepath.c_str(), GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return;
}
DWORD dwWrite = 0;
WriteFile(hFile, (LPCVOID)buffer, length, &dwWrite, 0);
CloseHandle(hFile);
unsigned char magic_head[4] = {0};
wchar_t postfix[5] = {0};
memcpy(magic_head, buffer, 3);
if (magic_head[0] == 137 && magic_head[1] == 80 && magic_head[2] == 78)
{
lstrcpy(postfix, L".png");
}
else if (magic_head[0] == 71 && magic_head[1] == 73 && magic_head[2] == 70)
{
lstrcpy(postfix, L".gif");
}
else if (magic_head[0] == 255 && magic_head[1] == 216 && magic_head[2] == 255)
{
lstrcpy(postfix, L".jpg");
}
else
{
lstrcpy(postfix, L"");
}
wstring filepath = savepath + filename + postfix;
HANDLE hFile = CreateFile(filepath.c_str(), GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return;
}
DWORD dwWrite = 0;
WriteFile(hFile, (LPCVOID)buffer, length, &dwWrite, 0);
CloseHandle(hFile);
}
__declspec(naked) void dealImageMsg() {
__asm {
__declspec(naked) void dealImageMsg()
{
__asm {
pushad;
pushfd;
push esi;
......@@ -68,41 +72,61 @@ __declspec(naked) void dealImageMsg() {
popad;
call HookImageMsgNextCall;
jmp HookImageMsgJmpBackAddr;
}
}
}
void __stdcall HookImageMsg() {
WeChatWinBase = GetWeChatWinBase();
if (ImageMsgHooked || !WeChatWinBase)
return;
HookImageMsgAddr = WeChatWinBase + HookImageMsgAddrOffset;
HookImageMsgNextCall = WeChatWinBase + HookImageMsgNextCallOffset;
HookImageMsgJmpBackAddr = HookImageMsgAddr + 0x5;
HookAnyAddress(HookImageMsgAddr, dealImageMsg, ImageMsgOldAsm);
char settime[] = "00:00-00:00";
DWORD AutoDownloadTimeSettingAddr = GetWeChatWinBase() + AutoDownloadTimeSettingOffset;
WriteProcessMemory(GetCurrentProcess(), (LPVOID)AutoDownloadTimeSettingAddr, settime, strlen(settime) + 1, 0);
ImageMsgHooked = true;
void __stdcall HookImageMsg()
{
WeChatWinBase = GetWeChatWinBase();
if (ImageMsgHooked || !WeChatWinBase)
return;
HookImageMsgAddr = WeChatWinBase + HookImageMsgAddrOffset;
HookImageMsgNextCall = WeChatWinBase + HookImageMsgNextCallOffset;
HookImageMsgJmpBackAddr = HookImageMsgAddr + 0x5;
HookAnyAddress(HookImageMsgAddr, dealImageMsg, ImageMsgOldAsm);
char settime[] = "00:00-00:00";
DWORD AutoDownloadTimeSettingAddr = GetWeChatWinBase() + AutoDownloadTimeSettingOffset;
WriteProcessMemory(GetCurrentProcess(), (LPVOID)AutoDownloadTimeSettingAddr, settime, strlen(settime) + 1, 0);
ImageMsgHooked = true;
}
void UnHookImageMsg() {
if (!ImageMsgHooked)
return;
UnHookAnyAddress(HookImageMsgAddr, ImageMsgOldAsm);
ImageMsgHooked = false;
void UnHookImageMsg()
{
if (!ImageMsgHooked)
return;
UnHookAnyAddress(HookImageMsgAddr, ImageMsgOldAsm);
ImageMsgHooked = false;
}
#ifndef USE_SOCKET
BOOL HookImageMsgRemote(LPVOID lpParameter) {
savepath = (wstring)(wchar_t*)lpParameter;
if (savepath.back() != '\\') {
savepath += L"\\";
}
wstring createpath = savepath.substr(0, savepath.length() - 1);
if (!FindOrCreateDirectory(createpath.c_str())) {
return false;
}
HookImageMsg();
return true;
BOOL HookImageMsgRemote(LPVOID lpParameter)
{
savepath = (wstring)(wchar_t *)lpParameter;
if (savepath.back() != '\\')
{
savepath += L"\\";
}
wstring createpath = savepath.substr(0, savepath.length() - 1);
if (!FindOrCreateDirectory(createpath.c_str()))
{
return false;
}
HookImageMsg();
return true;
}
#endif
\ No newline at end of file
#else
BOOL __stdcall HookImageMsg(wstring savepath)
{
if (savepath.back() != '\\')
{
savepath += L"\\";
}
wstring createpath = savepath.substr(0, savepath.length() - 1);
if (!FindOrCreateDirectory(createpath.c_str()))
{
return false;
}
HookImageMsg();
return true;
}
#endif
......@@ -8,40 +8,42 @@ static DWORD WeChatWinBase = GetWeChatWinBase();
static DWORD HookVoiceMsgAddr = WeChatWinBase + HookVoiceMsgAddrOffset;
static DWORD HookVoiceMsgNextCall = WeChatWinBase + HookVoiceMsgNextCallOffset;
static DWORD HookVoiceMsgJmpBackAddr = HookVoiceMsgAddr + 0x5;
static char VoiceMsgOldAsm[5] = { 0 };
static char VoiceMsgOldAsm[5] = {0};
static wstring savepath = L"";
void SaveVoiceMsg(unsigned char* buffer, int length, DWORD msgHandle) {
/*time_t curtime = time(0);
wchar_t timestamp[32] = { 0 };
_itow_s((int)curtime, timestamp, 10);*/
wchar_t* temp;
int wxid_length = *(DWORD*)(msgHandle + 0x174);
temp = new wchar_t[wxid_length + 1];
memcpy(temp, (void*)(*(DWORD*)(msgHandle + 0x170)), (wxid_length + 1) * 2);
wstring sender(temp);
delete[] temp;
temp = NULL;
int clientmsg_length = *(DWORD*)(msgHandle + 0x188);
temp = new wchar_t[clientmsg_length + 1];
memcpy(temp, (void*)(*(DWORD*)(msgHandle + 0x184)), (clientmsg_length + 1) * 2);
wstring clientmsgid(temp);
delete[] temp;
temp = NULL;
wstring filename = savepath + sender + L"-" + clientmsgid + L".amr";
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return;
}
DWORD dwWrite = 0;
WriteFile(hFile, (LPCVOID)buffer, length, &dwWrite, 0);
CloseHandle(hFile);
void SaveVoiceMsg(unsigned char *buffer, int length, DWORD msgHandle)
{
/*time_t curtime = time(0);
wchar_t timestamp[32] = { 0 };
_itow_s((int)curtime, timestamp, 10);*/
wchar_t *temp;
int wxid_length = *(DWORD *)(msgHandle + 0x174);
temp = new wchar_t[wxid_length + 1];
memcpy(temp, (void *)(*(DWORD *)(msgHandle + 0x170)), (wxid_length + 1) * 2);
wstring sender(temp);
delete[] temp;
temp = NULL;
int clientmsg_length = *(DWORD *)(msgHandle + 0x188);
temp = new wchar_t[clientmsg_length + 1];
memcpy(temp, (void *)(*(DWORD *)(msgHandle + 0x184)), (clientmsg_length + 1) * 2);
wstring clientmsgid(temp);
delete[] temp;
temp = NULL;
wstring filename = savepath + sender + L"-" + clientmsgid + L".amr";
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return;
}
DWORD dwWrite = 0;
WriteFile(hFile, (LPCVOID)buffer, length, &dwWrite, 0);
CloseHandle(hFile);
}
__declspec(naked) void dealVoiceMsg() {
__asm {
__declspec(naked) void dealVoiceMsg()
{
__asm {
pushad;
pushfd;
push edi;
......@@ -53,38 +55,58 @@ __declspec(naked) void dealVoiceMsg() {
popad;
call HookVoiceMsgNextCall;
jmp HookVoiceMsgJmpBackAddr;
}
}
}
void __stdcall HookVoiceMsg() {
WeChatWinBase = GetWeChatWinBase();
if (VoiceMsgHooked || !WeChatWinBase)
return;
HookVoiceMsgAddr = WeChatWinBase + HookVoiceMsgAddrOffset;
HookVoiceMsgNextCall = WeChatWinBase + HookVoiceMsgNextCallOffset;
HookVoiceMsgJmpBackAddr = HookVoiceMsgAddr + 0x5;
HookAnyAddress(HookVoiceMsgAddr, dealVoiceMsg, VoiceMsgOldAsm);
VoiceMsgHooked = true;
void __stdcall HookVoiceMsg()
{
WeChatWinBase = GetWeChatWinBase();
if (VoiceMsgHooked || !WeChatWinBase)
return;
HookVoiceMsgAddr = WeChatWinBase + HookVoiceMsgAddrOffset;
HookVoiceMsgNextCall = WeChatWinBase + HookVoiceMsgNextCallOffset;
HookVoiceMsgJmpBackAddr = HookVoiceMsgAddr + 0x5;
HookAnyAddress(HookVoiceMsgAddr, dealVoiceMsg, VoiceMsgOldAsm);
VoiceMsgHooked = true;
}
void UnHookVoiceMsg() {
if (!VoiceMsgHooked)
return;
UnHookAnyAddress(HookVoiceMsgAddr, VoiceMsgOldAsm);
VoiceMsgHooked = false;
void UnHookVoiceMsg()
{
if (!VoiceMsgHooked)
return;
UnHookAnyAddress(HookVoiceMsgAddr, VoiceMsgOldAsm);
VoiceMsgHooked = false;
}
#ifndef USE_SOCKET
BOOL HookVoiceMsgRemote(LPVOID lpParameter) {
savepath = (wstring)(wchar_t*)lpParameter;
if (savepath.back() != '\\') {
savepath += L"\\";
}
wstring createpath = savepath.substr(0, savepath.length() - 1);
if (!FindOrCreateDirectory(createpath.c_str())) {
return false;
}
HookVoiceMsg();
return true;
BOOL HookVoiceMsgRemote(LPVOID lpParameter)
{
savepath = (wstring)(wchar_t *)lpParameter;
if (savepath.back() != '\\')
{
savepath += L"\\";
}
wstring createpath = savepath.substr(0, savepath.length() - 1);
if (!FindOrCreateDirectory(createpath.c_str()))
{
return false;
}
HookVoiceMsg();
return true;
}
#else
BOOL __stdcall HookVoiceMsg(wstring savepath)
{
if (savepath.back() != '\\')
{
savepath += L"\\";
}
wstring createpath = savepath.substr(0, savepath.length() - 1);
if (!FindOrCreateDirectory(createpath.c_str()))
{
return false;
}
HookVoiceMsg();
return true;
}
#endif
\ No newline at end of file
#endif
#pragma once
#include<windows.h>
#include <windows.h>
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) VOID HookReceiveMessage(int port);
extern "C" __declspec(dllexport) VOID UnHookReceiveMessage();
......@@ -12,7 +12,9 @@ VOID HookReceiveMessage(int port);
VOID UnHookReceiveMessage();
void UnHookImageMsg();
void UnHookVoiceMsg();
BOOL __stdcall HookVoiceMsg(wstring savepath);
BOOL __stdcall HookImageMsg(wstring savepath);
#endif
void __stdcall HookVoiceMsg();
void __stdcall HookImageMsg();
\ No newline at end of file
void __stdcall HookImageMsg();
......@@ -6,12 +6,12 @@
#define DeleteAtTextCacheCallOffset 0x78757780 - 0x786A0000
/*
* 外部调用时传递的参数结构
* chatroomid:群聊ID的保存地址
* wxidlist:艾特列表的保存地址,真实类型应当是`wchar_t**`
* wxmsg:发送的内容保存地址
* length:艾特的人数量,用于指示wxidlist长度
*/
* 外部调用时传递的参数结构
* chatroomid:群聊ID的保存地址
* wxidlist:艾特列表的保存地址,真实类型应当是`wchar_t**`
* wxmsg:发送的内容保存地址
* length:艾特的人数量,用于指示wxidlist长度
*/
#ifndef USE_SOCKET
struct SendAtTextStruct
{
......@@ -24,13 +24,13 @@ struct SendAtTextStruct
#endif
/*
* 内存中使用的参数结构
* 构造与Release版本vector动态数组相仿
* 成员类型:`WxString`
* AtUser:类似`vector`的`data`方法,保存数组首个成员的地址
* addr_end1:数组尾地址
* addr_end2:数组尾地址
*/
* 内存中使用的参数结构
* 构造与Release版本vector动态数组相仿
* 成员类型:`WxString`
* AtUser:类似`vector`的`data`方法,保存数组首个成员的地址
* addr_end1:数组尾地址
* addr_end2:数组尾地址
*/
struct AtStruct
{
DWORD AtUser;
......@@ -39,10 +39,10 @@ struct AtStruct
};
/*
* 供外部调用的发送艾特消息接口
* lpParameter:SendAtTextStruct类型结构体指针
* return:void
*/
* 供外部调用的发送艾特消息接口
* lpParameter:SendAtTextStruct类型结构体指针
* return:void
*/
#ifndef USE_SOCKET
void SendAtTextRemote(LPVOID lpParameter)
{
......@@ -59,15 +59,15 @@ void SendAtTextRemote(LPVOID lpParameter)
#endif
/*
* 发送艾特消息的具体实现
* wsChatRoomId:群聊ID
* wsWxId:艾特的人列表
* wsTextMsg:发送的消息内容
* length:艾特的人数量
* AutoNickName:是否自动填充被艾特人昵称
* return:void
*/
void __stdcall SendAtText(wchar_t *wsChatRoomId, DWORD wsWxId[], wchar_t *wsTextMsg, int length, BOOL AutoNickName)
* 发送艾特消息的具体实现
* wsChatRoomId:群聊ID
* wsWxId:艾特的人列表
* wsTextMsg:发送的消息内容
* length:艾特的人数量
* AutoNickName:是否自动填充被艾特人昵称
* return:BOOL,发送成功返回`1`,发送失败返回`0`
*/
BOOL __stdcall SendAtText(wchar_t *wsChatRoomId, DWORD wsWxId[], wchar_t *wsTextMsg, int length, BOOL AutoNickName)
{
// +1的作用是补充一个空结构体,将`AtStruct`尾地址设定为空结构的首地址即可
WxString *AtUsers = new WxString[length + 1];
......@@ -97,7 +97,7 @@ void __stdcall SendAtText(wchar_t *wsChatRoomId, DWORD wsWxId[], wchar_t *wsText
}
AtMessage += wsTextMsg;
if (!querySuccess)
return;
return FALSE;
WxString wxChatRoomId(wsChatRoomId);
WxString wxTextMsg((wchar_t *)AtMessage.c_str());
AtStruct at = {0};
......@@ -111,7 +111,7 @@ void __stdcall SendAtText(wchar_t *wsChatRoomId, DWORD wsWxId[], wchar_t *wsText
DWORD dllBaseAddress = GetWeChatWinBase();
DWORD callAddress = dllBaseAddress + SendAtTextCallOffset;
DWORD DeleteTextCacheCall = dllBaseAddress + DeleteAtTextCacheCallOffset;
int isSuccess = 0;
__asm {
lea eax, at;
push 0x1;
......@@ -121,10 +121,12 @@ void __stdcall SendAtText(wchar_t *wsChatRoomId, DWORD wsWxId[], wchar_t *wsText
lea edx, wxChatRoomId;
lea ecx, buffer;
call callAddress;
mov isSuccess,eax;
add esp, 0xC;
lea ecx, buffer;
call DeleteTextCacheCall;
}
delete[] AtUsers;
AtUsers = NULL;
return isSuccess == 1;
}
#pragma once
#include<windows.h>
#include <windows.h>
void __stdcall SendAtText(wchar_t* wsChatRoomId, DWORD wsWxId[], wchar_t* wsTextMsg, int length, BOOL AutoNickName);
BOOL __stdcall SendAtText(wchar_t *wsChatRoomId, DWORD wsWxId[], wchar_t *wsTextMsg, int length, BOOL AutoNickName);
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) void SendAtTextRemote(LPVOID lpParameter);
#endif
\ No newline at end of file
#endif
......@@ -6,11 +6,11 @@
#define DeleteCardCacheCallOffset 0x78757780 - 0x786A0000
/*
* 外部调用时提供的参数结构
* receiver:名片消息接收人wxid保存地址
* sharedwxid:被推荐人的wxid保存地址
* nickname:名片显示的昵称保存地址
*/
* 外部调用时提供的参数结构
* receiver:名片消息接收人wxid保存地址
* sharedwxid:被推荐人的wxid保存地址
* nickname:名片显示的昵称保存地址
*/
#ifndef USE_SOCKET
struct SendCardStruct
{
......@@ -21,10 +21,10 @@ struct SendCardStruct
#endif
/*
* 供外部调用的发送名片接口
* lparameter:SendCardStruct类型结构体指针
* return:void
*/
* 供外部调用的发送名片接口
* lparameter:SendCardStruct类型结构体指针
* return:void
*/
#ifndef USE_SOCKET
VOID SendCardRemote(LPVOID lparameter)
{
......@@ -37,12 +37,12 @@ VOID SendCardRemote(LPVOID lparameter)
#endif
/*
* 发送名片消息的具体实现
* receiver:消息接收人wxid
* sharedwxid:被推荐人wxid
* nickname:名片显示的昵称
* return:BOOL,发送成功返回`0`,发送失败返回`1`
*/
* 发送名片消息的具体实现
* receiver:消息接收人wxid
* sharedwxid:被推荐人wxid
* nickname:名片显示的昵称
* return:BOOL,发送成功返回`1`,发送失败返回`0`
*/
BOOL __stdcall SendCard(wchar_t *receiver, wchar_t *sharedwxid, wchar_t *nickname)
{
DWORD WeChatWinBase = GetWeChatWinBase();
......@@ -69,10 +69,10 @@ BOOL __stdcall SendCard(wchar_t *receiver, wchar_t *sharedwxid, wchar_t *nicknam
add esp, 0xC;
lea ecx, buffer;
call DeleteCardCacheCall;
mov isSuccess, eax;
mov isSuccess, eax;
popad;
}
delete[] xml;
xml = NULL;
return isSuccess;
return isSuccess == 0;
}
......@@ -10,10 +10,10 @@
#define DeleteSendFileCacheCallOffset (0x78757780 - 0x786A0000)
/*
* 外部调用时传递的参数结构
* wxid:wxid的保存地址
* filepath:文件绝对路径的保存地址
*/
* 外部调用时传递的参数结构
* wxid:wxid的保存地址
* filepath:文件绝对路径的保存地址
*/
#ifndef USE_SOCKET
struct FileParamStruct
{
......@@ -23,14 +23,14 @@ struct FileParamStruct
#endif
/*
* 内存中使用的参数结构
* type:消息类型,文件消息为3
* buffer:文件绝对路径
* length:绝对路径字符数
* maxLength:绝对路径最大字节数
* fill:占位用空缓冲区
* WxFileStruct:默认构造函数
*/
* 内存中使用的参数结构
* type:消息类型,文件消息为3
* buffer:文件绝对路径
* length:绝对路径字符数
* maxLength:绝对路径最大字节数
* fill:占位用空缓冲区
* WxFileStruct:默认构造函数
*/
struct WxFileStruct
{
int type = 3;
......@@ -48,10 +48,10 @@ struct WxFileStruct
};
/*
* 供外部调用的发送文件消息接口
* lpParamStruct:FileParamStruct类型结构体指针
* return:void
*/
* 供外部调用的发送文件消息接口
* lpParamStruct:FileParamStruct类型结构体指针
* return:void
*/
#ifndef USE_SOCKET
void SendFileRemote(LPVOID lpParamStruct)
{
......@@ -61,12 +61,12 @@ void SendFileRemote(LPVOID lpParamStruct)
#endif
/*
* 发送文件消息的具体实现
* receiver:接收人wxid
* FilePath:文件绝对路径
* return:void
*/
void __stdcall SendFile(wchar_t *receiver, wchar_t *FilePath)
* 发送文件消息的具体实现
* receiver:接收人wxid
* FilePath:文件绝对路径
* return:BOOL,发送成功返回`1`,发送失败返回`0`
*/
BOOL __stdcall SendFile(wchar_t *receiver, wchar_t *FilePath)
{
WxString pReceiver(receiver);
WxString pFilePath(FilePath);
......@@ -85,7 +85,7 @@ void __stdcall SendFile(wchar_t *receiver, wchar_t *FilePath)
DWORD edi_ = pReceiver.length;
DWORD ptrReceiver = (DWORD)pReceiver.buffer;
int isSuccess = 0;
__asm {
pushad;
pushfd;
......@@ -118,9 +118,11 @@ void __stdcall SendFile(wchar_t *receiver, wchar_t *FilePath)
lea eax, buffer;
push eax;
call WxSendFileCall3;
mov isSuccess,eax;
lea ecx, buffer;
call DeleteSendFileCacheCall;
popfd;
popad;
}
return isSuccess == 1;
}
#pragma once
#include<windows.h>
#include <windows.h>
void __stdcall SendFile(wchar_t* receiver, wchar_t* FilePath);
BOOL __stdcall SendFile(wchar_t *receiver, wchar_t *FilePath);
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) void SendFileRemote(LPVOID lpParamStruct);
#endif
\ No newline at end of file
#endif
......@@ -10,10 +10,10 @@
#define DeleteSendImageCacheCallOffset (0x78757780 - 0x786A0000)
/*
* 外部调用时传递的参数结构
* wxid:保存wxid的地址
* imagepath:保存图片绝对路径的地址
*/
* 外部调用时传递的参数结构
* wxid:保存wxid的地址
* imagepath:保存图片绝对路径的地址
*/
#ifndef USE_SOCKET
struct ImageParamStruct
{
......@@ -23,10 +23,10 @@ struct ImageParamStruct
#endif
/*
* 供外部调用的发送图片消息接口
* lpParamStruct:ImageParamStruct类型结构体指针
* return:void
*/
* 供外部调用的发送图片消息接口
* lpParamStruct:ImageParamStruct类型结构体指针
* return:void
*/
#ifndef USE_SOCKET
void SendImageRemote(LPVOID lpParamStruct)
{
......@@ -36,12 +36,12 @@ void SendImageRemote(LPVOID lpParamStruct)
#endif
/*
* 发送图片消息的具体实现
* receiver:接收人wxid
* ImagePath:图片绝对路径
* return:void
*/
void __stdcall SendImage(wchar_t *receiver, wchar_t *ImagePath)
* 发送图片消息的具体实现
* receiver:接收人wxid
* ImagePath:图片绝对路径
* return:BOOL,发送成功返回`1`,发送失败返回`0`
*/
BOOL __stdcall SendImage(wchar_t *receiver, wchar_t *ImagePath)
{
DWORD WeChatWinBase = GetWeChatWinBase();
DWORD SendImageCall1 = WeChatWinBase + SendImageCall1Offset;
......@@ -54,7 +54,7 @@ void __stdcall SendImage(wchar_t *receiver, wchar_t *ImagePath)
WxString pImagePath(ImagePath);
WxString nullStruct = {0};
DWORD tempeax = 0;
int isSuccess = 0;
__asm {
pushad;
call SendImageCall1;
......@@ -72,8 +72,10 @@ void __stdcall SendImage(wchar_t *receiver, wchar_t *ImagePath)
lea eax, buffer;
push eax;
call SendImageCall3;
mov isSuccess,eax;
lea ecx, buffer;
call DeleteSendImageCacheCall;
popad;
}
return isSuccess == 1;
}
#pragma once
#include<windows.h>
#include <windows.h>
void __stdcall SendImage(wchar_t* receiver, wchar_t* ImagePath);
BOOL __stdcall SendImage(wchar_t *receiver, wchar_t *ImagePath);
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) void SendImageRemote(LPVOID lpParamStruct);
#endif
\ No newline at end of file
#endif
......@@ -6,10 +6,10 @@
#define DeleteTextCacheCallOffset 0x78757780 - 0x786A0000
/*
* 外部调用时传递的参数结构
* wxid:wxid保存地址
* wxmsg:发送的内容保存地址
*/
* 外部调用时传递的参数结构
* wxid:wxid保存地址
* wxmsg:发送的内容保存地址
*/
#ifndef USE_SOCKET
struct SendTextStruct
{
......@@ -19,10 +19,10 @@ struct SendTextStruct
#endif
/*
* 供外部调用的发送文本消息接口
* lpParameter:SendTextStruct类型结构体指针
* return:void
*/
* 供外部调用的发送文本消息接口
* lpParameter:SendTextStruct类型结构体指针
* return:void
*/
#ifndef USE_SOCKET
void SendTextRemote(LPVOID lpParameter)
{
......@@ -34,12 +34,12 @@ void SendTextRemote(LPVOID lpParameter)
#endif
/*
* 发送文本消息的具体实现
* wsWxId:接收人wxid
* wsTextMsg:发送的消息内容
* return:void
*/
void __stdcall SendText(wchar_t *wsWxId, wchar_t *wsTextMsg)
* 发送文本消息的具体实现
* wsWxId:接收人wxid
* wsTextMsg:发送的消息内容
* return:BOOL,发送成功返回`1`,发送失败返回`0`
*/
BOOL __stdcall SendText(wchar_t *wsWxId, wchar_t *wsTextMsg)
{
WxString wxWxid(wsWxId);
WxString wxTextMsg(wsTextMsg);
......@@ -50,7 +50,7 @@ void __stdcall SendText(wchar_t *wsWxId, wchar_t *wsTextMsg)
DWORD dllBaseAddress = GetWeChatWinBase();
DWORD callAddress = dllBaseAddress + SendTextCallOffset;
DWORD DeleteTextCacheCall = dllBaseAddress + DeleteTextCacheCallOffset;
int isSuccess = 0;
__asm {
pushad;
lea eax, wxNull;
......@@ -61,9 +61,11 @@ void __stdcall SendText(wchar_t *wsWxId, wchar_t *wsTextMsg)
lea edx, wxWxid;
lea ecx, buffer;
call callAddress;
mov isSuccess,eax;
add esp, 0xC;
lea ecx, buffer;
call DeleteTextCacheCall;
popad;
}
return isSuccess == 1;
}
#pragma once
#include<windows.h>
#include <windows.h>
void __stdcall SendText(wchar_t* wsWxId, wchar_t* wsTextMsg);
BOOL __stdcall SendText(wchar_t *wsWxId, wchar_t *wsTextMsg);
#ifndef USE_SOCKET
extern "C" __declspec(dllexport) void SendTextRemote(LPVOID lpParameter);
#endif
\ No newline at end of file
#endif
......@@ -4,16 +4,16 @@
#ifdef USE_SOCKET
#define WS2LW(wstr) (LPWSTR) wstr.c_str()
void __stdcall SendText(wstring wxid, wstring msg)
BOOL __stdcall SendText(wstring wxid, wstring msg)
{
return SendText(WS2LW(wxid), WS2LW(msg));
}
void __stdcall SendAtText(wstring wsChatRoomId, vector<wstring> wxids, wstring wsTextMsg, BOOL AutoNickName)
BOOL __stdcall SendAtText(wstring wsChatRoomId, vector<wstring> wxids, wstring wsTextMsg, BOOL AutoNickName)
{
vector<DWORD> wxid_list;
for (auto wxid : wxids)
wxid_list.push_back((DWORD)wxid.c_str());
for (unsigned int i = 0; i < wxids.size(); i++)
wxid_list.push_back((DWORD)wxids[i].c_str());
return SendAtText(WS2LW(wsChatRoomId), wxid_list.data(), WS2LW(wsTextMsg), wxid_list.size(), AutoNickName);
}
......@@ -22,12 +22,12 @@ BOOL __stdcall SendCard(wstring receiver, wstring sharedwxid, wstring nickname)
return SendCard(WS2LW(receiver), WS2LW(sharedwxid), WS2LW(nickname));
}
void __stdcall SendImage(wstring receiver, wstring ImagePath)
BOOL __stdcall SendImage(wstring receiver, wstring ImagePath)
{
return SendImage(WS2LW(receiver), WS2LW(ImagePath));
}
void __stdcall SendFile(wstring receiver, wstring FilePath)
BOOL __stdcall SendFile(wstring receiver, wstring FilePath)
{
return SendFile(WS2LW(receiver), WS2LW(FilePath));
}
......@@ -90,16 +90,16 @@ wstring __stdcall GetChatRoomMemberNickname(wstring chatroomid, wstring wxid)
BOOL __stdcall DelChatRoomMember(wstring chatroomid, vector<wstring> wxids)
{
vector<wchar_t *> wxid_list;
for (auto wxid : wxids)
wxid_list.push_back((wchar_t *)wxid.c_str());
for (unsigned int i = 0; i < wxids.size(); i++)
wxid_list.push_back(WS2LW(wxids[i]));
return DelChatRoomMember(WS2LW(chatroomid), wxid_list.data(), wxid_list.size());
}
BOOL __stdcall AddChatRoomMember(wstring chatroomid, vector<wstring> wxids)
{
vector<wchar_t *> wxid_list;
for (auto wxid : wxids)
wxid_list.push_back((wchar_t *)wxid.c_str());
for (unsigned int i = 0; i < wxids.size(); i++)
wxid_list.push_back(WS2LW(wxids[i]));
return AddChatRoomMember(WS2LW(chatroomid), wxid_list.data(), wxid_list.size());
}
......@@ -123,9 +123,9 @@ BOOL __stdcall ChangeWeChatVersion(wstring verStr)
return ChangeWeChatVer(WS2LW(verStr));
}
int __stdcall BackupSQLiteDB(DWORD DbHandle, wstring BackupFile)
BOOL __stdcall BackupSQLiteDB(DWORD DbHandle, wstring BackupFile)
{
string filepath = unicode_to_utf8(WS2LW(BackupFile));
return BackupSQLiteDB(DbHandle, filepath.c_str());
return BackupSQLiteDB(DbHandle, filepath.c_str()) == SQLITE_OK;
}
#endif
// pch.cpp: 与预编译标头对应的源文件
#include "pch.h"
#include <functional>
// 当使用预编译的头时,需要使用此源文件,编译才能成功。
/*
* 创建一个控制台窗口
* return:BOOL,成功返回`0`,失败返回`1`
*/
* 创建一个控制台窗口
* return:BOOL,成功返回`0`,失败返回`1`
*/
BOOL CreateConsole(void)
{
if (AllocConsole())
......@@ -26,9 +27,9 @@ BOOL CreateConsole(void)
}
/*
* 获取`WeChatWin.dll`基址
* return:DWORD,`WeChatWin.dll`模块基址
*/
* 获取`WeChatWin.dll`基址
* return:DWORD,`WeChatWin.dll`模块基址
*/
DWORD GetWeChatWinBase()
{
return (DWORD)GetModuleHandleA("WeChatWin.dll");
......@@ -52,8 +53,8 @@ BOOL FindOrCreateDirectory(const wchar_t *pszPath)
}
/*
* 将宽字节字符串转换成`std::string`
*/
* 将宽字节字符串转换成`std::string`
*/
string unicode_to_gb2312(wchar_t *wchar)
{
wchar_t *wText = wchar;
......@@ -67,8 +68,8 @@ string unicode_to_gb2312(wchar_t *wchar)
}
/*
* 将UTF8编码数据转换为GBK编码
*/
* 将UTF8编码数据转换为GBK编码
*/
string utf8_to_gb2312(const char *strUTF8)
{
int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8, -1, NULL, 0);
......@@ -87,8 +88,8 @@ string utf8_to_gb2312(const char *strUTF8)
}
/*
* 将UTF8编码数据转换为GBK编码
*/
* 将UTF8编码数据转换为GBK编码
*/
wstring utf8_to_unicode(const char *buffer)
{
int c_size = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, 0, 0);
......@@ -114,12 +115,12 @@ string unicode_to_utf8(wchar_t *wstr)
}
/*
* 对任意地址添加HOOK
* dwHookAddr:HOOK的目标地址
* dwJmpAddress:跳转到的地址
* originalRecieveCode:保存旧指令的数组
* return:void
*/
* 对任意地址添加HOOK
* dwHookAddr:HOOK的目标地址
* dwJmpAddress:跳转到的地址
* originalRecieveCode:保存旧指令的数组
* return:void
*/
void HookAnyAddress(DWORD dwHookAddr, LPVOID dwJmpAddress, char *originalRecieveCode)
{
//组装跳转数据
......@@ -144,11 +145,11 @@ void HookAnyAddress(DWORD dwHookAddr, LPVOID dwJmpAddress, char *originalRecieve
}
/*
* 对任意地址取消HOOK
* dwHookAddr:HOOK的目标地址
* originalRecieveCode:保存旧指令的数组
* return:void
*/
* 对任意地址取消HOOK
* dwHookAddr:HOOK的目标地址
* originalRecieveCode:保存旧指令的数组
* return:void
*/
void UnHookAnyAddress(DWORD dwHookAddr, char *originalRecieveCode)
{
DWORD OldProtext = 0;
......@@ -158,9 +159,9 @@ void UnHookAnyAddress(DWORD dwHookAddr, char *originalRecieveCode)
}
/*
* 取消所有HOOK
* return:void
*/
* 取消所有HOOK
* return:void
*/
void UnHookAll()
{
UnHookLogMsgInfo();
......@@ -173,12 +174,12 @@ void UnHookAll()
}
/*
* 将单字符替换为指定的字符串
* source:源字符串
* replaced:被替换的单字符
* replaceto:替换成的字符串
* return:std::wstring,替换后的字符串
*/
* 将单字符替换为指定的字符串
* source:源字符串
* replaced:被替换的单字符
* replaceto:替换成的字符串
* return:std::wstring,替换后的字符串
*/
wstring wreplace(wstring source, wchar_t replaced, wstring replaceto)
{
wstring temp = L"";
......@@ -196,8 +197,8 @@ wstring wreplace(wstring source, wchar_t replaced, wstring replaceto)
}
/*
* 获取当前时间
*/
* 获取当前时间
*/
wstring GetTimeW(long long timestamp)
{
wchar_t *wstr = new wchar_t[20];
......@@ -217,7 +218,6 @@ void PrintProcAddr()
{
CreateConsole();
printf("WeChatVersion %s\n", GetWeChatVerStr().c_str());
#ifndef USE_SOCKET
printf("SendImage 0x%08X\n", (DWORD)SendImage);
printf("SendText 0x%08X\n", (DWORD)SendText);
printf("SendFile 0x%08X\n", (DWORD)SendFile);
......@@ -226,8 +226,11 @@ void PrintProcAddr()
printf("GetUserInfoByWxId 0x%08X\n", (DWORD)GetUserInfoByWxId);
printf("SendArticle 0x%08X\n", (DWORD)SendArticle);
printf("SendCard 0x%08X\n", (DWORD)SendCard);
printf("CheckFriendStatus 0x%08X\n", (DWORD)CheckFriendStatus);
printf("GetChatRoomMembers 0x%08X\n", (DWORD)GetChatRoomMembers);
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);
printf("ExecuteSql 0x%08X\n", (DWORD)ExecuteSQL);
printf("BackupSQLiteDB 0x%08X\n", (DWORD)BackupSQLiteDB);
printf("VerifyFriendApply 0x%08X\n", (DWORD)VerifyFriendApply);
......@@ -235,13 +238,13 @@ void PrintProcAddr()
printf("AddFriendByWxid 0x%08X\n", (DWORD)AddFriendByWxid);
printf("AddBrandContact 0x%08X\n", (DWORD)AddBrandContact);
printf("SelectData 0x%08X\n", (DWORD)SelectData);
printf("SearchContactByNet 0x%08X\n", (DWORD)SearchContactByNet);
void *(__stdcall * search_contact_by_net)(wchar_t *) = SearchContactByNet;
printf("SearchContactByNet 0x%08X\n", (DWORD)search_contact_by_net);
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);
#endif
}
BOOL ProcessIsWeChat()
......
......@@ -92,7 +92,14 @@ static int get_http_param_int(mg_http_message *hm, json jData, string key, int m
}
case HTTP_METHOD_POST:
{
result = STOI_S((string)jData[key]);
try
{
result = jData[key];
}
catch (json::exception)
{
result = STOI_S((string)jData[key]);
}
break;
}
default:
......@@ -122,21 +129,42 @@ static vector<wstring> get_http_param_array(mg_http_message *hm, json jData, str
return result;
}
void request_event(mg_http_message *hm)
void request_event(mg_http_message *hm, string &ret)
{
int method = I_METHOD(getMgStrA(hm->method));
// 第四个参数设置为false,不抛出异常
json jData = json::parse(hm->body.ptr, hm->body.ptr + hm->body.len, nullptr, false);
if (jData.is_discarded() == true && method == HTTP_METHOD_POST)
{
json ret_data = {{"result", "ERROR"},
{"err_msg", "json string is invalid."}};
ret = ret_data.dump();
return;
int num = STOI_S(getMgVarA(hm, "type"));
switch (num)
}
int api_number = STOI_S(getMgVarA(hm, "type"));
switch (api_number)
{
case WECHAT_IS_LOGIN:
{
BOOL logined = isWxLogin();
json ret_data = {{"is_login", logined}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_GET_SELF_INFO:
{
wstring self_info = GetSelfInfo();
json ret_data = {{"self_info", unicode_to_utf8(WS2LW(self_info))}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_SEND_TEXT:
{
wstring wxid = get_http_param_str(hm, jData, "wxid", method);
wstring msg = get_http_param_str(hm, jData, "msg", method);
SendText(wxid, msg);
BOOL status = SendText(wxid, msg);
json ret_data = {{"msg", 1}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_SEND_AT:
......@@ -145,7 +173,9 @@ void request_event(mg_http_message *hm)
vector<wstring> wxids = get_http_param_array(hm, jData, "wxids", method);
wstring msg = get_http_param_str(hm, jData, "msg", method);
int auto_nickname = get_http_param_int(hm, jData, "auto_nickname", method);
SendAtText(chatroom, wxids, msg, auto_nickname);
BOOL status = SendAtText(chatroom, wxids, msg, auto_nickname);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_SEND_CARD:
......@@ -153,21 +183,27 @@ void request_event(mg_http_message *hm)
wstring receiver = get_http_param_str(hm, jData, "receiver", method);
wstring shared_wxid = get_http_param_str(hm, jData, "shared_wxid", method);
wstring nickname = get_http_param_str(hm, jData, "nickname", method);
SendCard(receiver, shared_wxid, nickname);
BOOL status = SendCard(receiver, shared_wxid, nickname);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_SEND_IMAGE:
{
wstring receiver = get_http_param_str(hm, jData, "receiver", method);
wstring img_path = get_http_param_str(hm, jData, "img_path", method);
SendImage(receiver, img_path);
BOOL status = SendImage(receiver, img_path);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_SEND_FILE:
{
wstring receiver = get_http_param_str(hm, jData, "receiver", method);
wstring file_path = get_http_param_str(hm, jData, "file_path", method);
SendFile(receiver, file_path);
BOOL status = SendFile(receiver, file_path);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_SEND_ARTICLE:
......@@ -177,14 +213,287 @@ void request_event(mg_http_message *hm)
wstring abstract = get_http_param_str(hm, jData, "abstract", method);
wstring url = get_http_param_str(hm, jData, "url", method);
wstring img_path = get_http_param_str(hm, jData, "img_path", method);
SendArticle(wxid, title, abstract, url, img_path);
BOOL status = SendArticle(wxid, title, abstract, url, img_path);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_SEND_APP:
{
wstring wxid = get_http_param_str(hm, jData, "wxid", method);
wstring appid = get_http_param_str(hm, jData, "appid", method);
SendAppMsg(wxid, appid);
BOOL status = SendAppMsg(wxid, appid);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_START_HOOK:
{
int port = get_http_param_int(hm, jData, "port", method);
HookReceiveMessage(port);
break;
}
case WECHAT_MSG_STOP_HOOK:
{
UnHookReceiveMessage();
break;
}
case WECHAT_MSG_START_IMAGE_HOOK:
{
wstring savepath = get_http_param_str(hm, jData, "save_path", method);
BOOL status = HookImageMsg(savepath);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_STOP_IMAGE_HOOK:
{
UnHookImageMsg();
break;
}
case WECHAT_MSG_START_VOICE_HOOK:
{
wstring savepath = get_http_param_str(hm, jData, "save_path", method);
BOOL status = HookVoiceMsg(savepath);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_MSG_STOP_VOICE_HOOK:
{
UnHookVoiceMsg();
break;
}
case WECHAT_CONTACT_GET_LIST:
{
vector<WxFriendStruct> friend_list = GetWxContact();
json ret_data = {{"data", json::array()}, {"result", "OK"}};
for (unsigned int i = 0; i < friend_list.size() - 1; i++)
{
json f_j;
WxFriendStruct f = friend_list[i];
DWORD buffer_addr = *(DWORD *)f.wxIdAddr;
wstring wxid = buffer_addr != 0 ? wstring((wchar_t *)buffer_addr) : L"";
buffer_addr = *(DWORD *)f.wxNumberAddr;
wstring wxNumber = buffer_addr != 0 ? wstring((wchar_t *)buffer_addr) : L"";
buffer_addr = *(DWORD *)f.wxNickNameAddr;
wstring wxNickName = buffer_addr != 0 ? wstring((wchar_t *)buffer_addr) : L"";
buffer_addr = *(DWORD *)f.wxRemarkAddr;
wstring wxRemark = buffer_addr != 0 ? wstring((wchar_t *)buffer_addr) : L"";
f_j["wxid"] = unicode_to_utf8(WS2LW(wxid));
f_j["wxNumber"] = unicode_to_utf8(WS2LW(wxNumber));
f_j["wxNickName"] = unicode_to_utf8(WS2LW(wxNickName));
f_j["wxRemark"] = unicode_to_utf8(WS2LW(wxRemark));
ret_data["data"].push_back(f_j);
}
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_CHECK_STATUS:
{
wstring wxid = get_http_param_str(hm, jData, "wxid", method);
int status_code = CheckFriendStatus(wxid);
json ret_data = {{"status", status_code}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_DEL:
{
wstring wxid = get_http_param_str(hm, jData, "wxid", method);
BOOL status = DeleteUser(wxid);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_SEARCH_BY_CACHE:
{
wstring wxid = get_http_param_str(hm, jData, "wxid", method);
wstring userinfo = GetUserInfoByWxId(wxid);
json ret_data = {{"userinfo", unicode_to_utf8(WS2LW(userinfo))}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_SEARCH_BY_NET:
{
wstring keyword = get_http_param_str(hm, jData, "keyword", method);
map<wstring, wstring> userinfo = SearchContactByNet(keyword);
json ret_data;
for (auto it : userinfo)
{
string key = unicode_to_utf8(WS2LW(it.first));
ret_data[key] = unicode_to_utf8(WS2LW(it.second));
}
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_ADD_BY_WXID:
{
wstring wxid = get_http_param_str(hm, jData, "wxid", method);
wstring msg = get_http_param_str(hm, jData, "msg", method);
BOOL status = AddFriendByWxid(wxid, msg);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_ADD_BY_V3:
{
wstring v3 = get_http_param_str(hm, jData, "v3", method);
wstring msg = get_http_param_str(hm, jData, "msg", method);
int add_type = get_http_param_int(hm, jData, "add_type", method);
BOOL status = AddFriendByV3(v3, msg, add_type);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_ADD_BY_PUBLIC_ID:
{
wstring public_id = get_http_param_str(hm, jData, "public_id", method);
BOOL status = AddBrandContact(public_id);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_VERIFY_APPLY:
{
wstring v3 = get_http_param_str(hm, jData, "v3", method);
wstring v4 = get_http_param_str(hm, jData, "v4", method);
BOOL status = VerifyFriendApply(v3, v4);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CONTACT_EDIT_REMARK:
{
wstring wxid = get_http_param_str(hm, jData, "wxid", method);
wstring remark = get_http_param_str(hm, jData, "remark", method);
BOOL status = EditRemark(wxid, remark);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CHATROOM_GET_MEMBER_LIST:
{
wstring chatroom_id = get_http_param_str(hm, jData, "chatroom_id", method);
wstring members = GetChatRoomMembers(chatroom_id);
json ret_data = {{"members", unicode_to_utf8(WS2LW(members))}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CHATROOM_GET_MEMBER_NICKNAME:
{
wstring chatroom_id = get_http_param_str(hm, jData, "chatroom_id", method);
wstring wxid = get_http_param_str(hm, jData, "wxid", method);
wstring nickname = GetChatRoomMemberNickname(chatroom_id, wxid);
json ret_data = {{"nickname", unicode_to_utf8(WS2LW(nickname))}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CHATROOM_DEL_MEMBER:
{
wstring chatroom_id = get_http_param_str(hm, jData, "chatroom_id", method);
vector<wstring> wxids = get_http_param_array(hm, jData, "wxids", method);
BOOL status = DelChatRoomMember(chatroom_id, wxids);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CHATROOM_ADD_MEMBER:
{
wstring chatroom_id = get_http_param_str(hm, jData, "chatroom_id", method);
vector<wstring> wxids = get_http_param_array(hm, jData, "wxids", method);
BOOL status = AddChatRoomMember(chatroom_id, wxids);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CHATROOM_SET_ANNOUNCEMENT:
{
wstring chatroom_id = get_http_param_str(hm, jData, "chatroom_id", method);
wstring announcement = get_http_param_str(hm, jData, "announcement", method);
BOOL status = SetChatRoomAnnouncement(chatroom_id, announcement);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CHATROOM_SET_CHATROOM_NAME:
{
wstring chatroom_id = get_http_param_str(hm, jData, "chatroom_id", method);
wstring new_name = get_http_param_str(hm, jData, "chatroom_name", method);
BOOL status = SetChatRoomName(chatroom_id, new_name);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_CHATROOM_SET_SELF_NICKNAME:
{
wstring chatroom_id = get_http_param_str(hm, jData, "chatroom_id", method);
wstring nickname = get_http_param_str(hm, jData, "nickname", method);
BOOL status = SetChatRoomSelfNickname(chatroom_id, nickname);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_DATABASE_GET_HANDLES:
{
vector<void *> v_ptr = GetDbHandles();
json ret_data = {{"data", json::array()}, {"result", "OK"}};
for (unsigned int i = 0; i < v_ptr.size(); i++)
{
json db_info;
db_info["tables"] = json::array();
DbInfoStruct *db = reinterpret_cast<DbInfoStruct *>(v_ptr[i]);
db_info["handle"] = db->handle;
db_info["db_name"] = unicode_to_utf8(db->dbname);
for (auto table : db->tables)
{
json table_info = {{"name", table.name}, {"tbl_name", table.tbl_name}, {"sql", table.sql}, {"rootpage", table.rootpage}};
db_info["tables"].push_back(table_info);
}
ret_data["data"].push_back(db_info);
}
ret = ret_data.dump();
break;
}
case WECHAT_DATABASE_BACKUP:
{
DWORD db_handle = get_http_param_int(hm, jData, "db_handle", method);
wstring savepath = get_http_param_str(hm, jData, "save_path", method);
BOOL status = BackupSQLiteDB(db_handle, savepath);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_DATABASE_QUERY:
{
DWORD db_handle = get_http_param_int(hm, jData, "db_handle", method);
wstring sql = get_http_param_str(hm, jData, "sql", method);
string a_sql = unicode_to_utf8(WS2LW(sql));
// TODO: 数据库查询目前不可用
// SelectData(db_handle, a_sql.c_str(), NULL);
break;
}
case WECHAT_SET_VERSION:
{
wstring versionStr = get_http_param_str(hm, jData, "version", method);
BOOL status = ChangeWeChatVersion(versionStr);
json ret_data = {{"msg", status}, {"result", "OK"}};
ret = ret_data.dump();
break;
}
case WECHAT_LOG_START_HOOK:
{
#ifndef _DEBUG
CreateConsole();
#endif
HookLogMsgInfo();
break;
}
case WECHAT_LOG_STOP_HOOK:
{
#ifndef _DEBUG
FreeConsole();
#endif
UnHookLogMsgInfo();
break;
}
default:
......@@ -197,7 +506,9 @@ void request_event(mg_http_message *hm)
// Simply serve static files from `s_root_dir`
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data)
{
#ifdef _DEBUG
wcout.imbue(locale("chs"));
#endif
switch (ev)
{
case MG_EV_HTTP_MSG:
......@@ -213,17 +524,19 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data)
(int)hm->uri.len, hm->uri.ptr, (int)tmp.uri.len, tmp.uri.ptr,
(int)cl->len, cl->ptr));
#endif
string ret = R"({"result":"OK"})";
if (mg_http_match_uri(hm, "/api/"))
{
try
{
request_event(hm);
mg_http_reply(c, 200, "", "{\"result\": \"OK\"}", 0, 0);
request_event(hm, ret);
}
catch (json::exception)
catch (json::exception &e)
{
mg_http_reply(c, 200, "", "{\"result\": \"ERROR\"}", 0, 0);
json res = {{"result", "ERROR"}, {"err_msg", e.what()}};
ret = res.dump();
}
mg_http_reply(c, 200, "", ret.c_str(), 0, 0);
}
else if (mg_http_match_uri(hm, "/api/f2/*"))
{
......
......@@ -20,7 +20,10 @@ typedef enum HTTP_METHODSTag
typedef enum WECHAT_HTTP_APISTag
{
WECHAT_GET_SELF_INFO = 1,
// login check
WECHAT_IS_LOGIN = 0,
// self info
WECHAT_GET_SELF_INFO,
// send message
WECHAT_MSG_SEND_TEXT,
WECHAT_MSG_SEND_AT,
......
......@@ -62,7 +62,7 @@ class ReceiveMsgBaseServer(socketserver.BaseRequestHandler):
_fields_ = [("pid", ctypes.wintypes.DWORD),
("type", ctypes.wintypes.DWORD),
("isSendMsg", ctypes.wintypes.DWORD),
("msgid",ctypes.c_ulonglong),
("msgid", ctypes.c_ulonglong),
("sender", ctypes.c_wchar * 80),
("wxid", ctypes.c_wchar * 80),
("message", ctypes.c_wchar * 0x1000B),
......@@ -102,10 +102,10 @@ class ReceiveMsgBaseServer(socketserver.BaseRequestHandler):
@staticmethod
def msg_callback(data):
# 主线程中已经注入,此处禁止调用StartService和StopService
msg = {'pid': data.pid, 'time': data.time, 'type': data.type,
msg = {'pid': data.pid, 'time': data.time, 'type': data.type,
'isSendMsg': data.isSendMsg, 'msgid': data.msgid,
'wxid': data.wxid,
'sendto' if data.isSendMsg else 'from': data.sender,
'sendto' if data.isSendMsg else 'from': data.sender,
'message': data.message}
robot = comtypes.client.CreateObject("WeChatRobot.CWeChatRobot")
event = comtypes.client.CreateObject("WeChatRobot.RobotEvent")
......@@ -1047,7 +1047,7 @@ def get_wechat_pid_list() -> list:
if psutil.Process(pid).name() == 'WeChat.exe':
pid_list.append(pid)
except psutil.NoSuchProcess:
pass
pass
return pid_list
......@@ -1108,10 +1108,10 @@ def start_socket_server(port: int = 10808,
----------
port : int
socket的监听端口号.
request_handler : ReceiveMsgBaseServer
用于处理消息的类,需要继承自socketserver.BaseRequestHandler或ReceiveMsgBaseServer
main_thread : bool
是否在主线程中启动server
......
import ctypes
import json
import copy
import requests
if ctypes.sizeof(ctypes.c_void_p) == ctypes.sizeof(ctypes.c_ulonglong):
driver = ctypes.cdll.LoadLibrary('./wxDriver64.dll')
else:
driver = ctypes.cdll.LoadLibrary('./wxDriver.dll')
new_wechat = driver.new_wechat
new_wechat.argtypes = None
new_wechat.restype = ctypes.c_bool
start_listen = driver.start_listen
start_listen.argtypes = [ctypes.c_int,ctypes.c_int]
start_listen.restype = ctypes.c_int
stop_listen = driver.stop_listen
stop_listen.argtypes = [ctypes.c_int]
stop_listen.restype = ctypes.c_int
class WECHAT_HTTP_APIS:
# login check
WECHAT_IS_LOGIN = 0 # 登录检查
# self info
WECHAT_GET_SELF_INFO = 1 # 获取个人信息
# send message
WECHAT_MSG_SEND_TEXT = 2 # 发送文本
WECHAT_MSG_SEND_AT = 3 # 发送群艾特
WECHAT_MSG_SEND_CARD = 4 # 分享好友名片
WECHAT_MSG_SEND_IMAGE = 5 # 发送图片
WECHAT_MSG_SEND_FILE = 6 # 发送文件
WECHAT_MSG_SEND_ARTICLE = 7 # 发送xml文章
WECHAT_MSG_SEND_APP = 8 # 发送小程序
# receive message
WECHAT_MSG_START_HOOK = 9 # 开启接收消息HOOK,只支持socket监听
WECHAT_MSG_STOP_HOOK = 10 # 关闭接收消息HOOK
WECHAT_MSG_START_IMAGE_HOOK = 11 # 开启图片消息HOOK
WECHAT_MSG_STOP_IMAGE_HOOK = 12 # 关闭图片消息HOOK
WECHAT_MSG_START_VOICE_HOOK = 13 # 开启语音消息HOOK
WECHAT_MSG_STOP_VOICE_HOOK = 14 # 关闭语音消息HOOK
# contact
WECHAT_CONTACT_GET_LIST = 15 # 获取联系人列表
WECHAT_CONTACT_CHECK_STATUS = 16 # 检查是否被好友删除
WECHAT_CONTACT_DEL = 17 # 删除好友
WECHAT_CONTACT_SEARCH_BY_CACHE = 18 # 从内存中获取好友信息
WECHAT_CONTACT_SEARCH_BY_NET = 19 # 网络搜索用户信息
WECHAT_CONTACT_ADD_BY_WXID = 20 # wxid加好友
WECHAT_CONTACT_ADD_BY_V3 = 21 # v3数据加好友
WECHAT_CONTACT_ADD_BY_PUBLIC_ID = 22 # 关注公众号
WECHAT_CONTACT_VERIFY_APPLY = 23 # 通过好友请求
WECHAT_CONTACT_EDIT_REMARK = 24 # 修改备注
# chatroom
WECHAT_CHATROOM_GET_MEMBER_LIST = 25 # 获取群成员列表
WECHAT_CHATROOM_GET_MEMBER_NICKNAME = 26 # 获取指定群成员昵称
WECHAT_CHATROOM_DEL_MEMBER = 27 # 删除群成员
WECHAT_CHATROOM_ADD_MEMBER = 28 # 添加群成员
WECHAT_CHATROOM_SET_ANNOUNCEMENT = 29 # 设置群公告
WECHAT_CHATROOM_SET_CHATROOM_NAME = 30 # 设置群聊名称
WECHAT_CHATROOM_SET_SELF_NICKNAME = 31 # 设置群内个人昵称
# database
WECHAT_DATABASE_GET_HANDLES = 32 # 获取数据库句柄
WECHAT_DATABASE_BACKUP = 33 # 备份数据库
# TODO: 数据库查询目前不可用
WECHAT_DATABASE_QUERY = 34 # 数据库查询
# version
WECHAT_SET_VERSION = 35 # 修改微信版本号
# log
WECHAT_LOG_START_HOOK = 36 # 开启日志信息HOOK
WECHAT_LOG_STOP_HOOK = 37 # 关闭日志信息HOOK
APIS = WECHAT_HTTP_APIS
# http api 参数模板
class WECHAT_HTTP_API_PARAM_TEMPLATES:
__HTTP_API_PARAM_TEMPLATE = {
# login check
APIS.WECHAT_IS_LOGIN: {},
# self info
APIS.WECHAT_GET_SELF_INFO: {},
# send message
APIS.WECHAT_MSG_SEND_TEXT: {"wxid": "",
"msg": ""},
# wxids需要以`,`分隔,例如`wxid1,wxid2,wxid3`
APIS.WECHAT_MSG_SEND_AT: {"chatroom_id":"",
"wxids": "",
"msg": "",
"auto_nickname": 1},
APIS.WECHAT_MSG_SEND_CARD: {"receiver":'',
"shared_wxid":"",
"nickname":""},
APIS.WECHAT_MSG_SEND_IMAGE: {"receiver":"",
"img_path":""},
APIS.WECHAT_MSG_SEND_FILE: {"receiver":"",
"file_path":""},
APIS.WECHAT_MSG_SEND_ARTICLE: {"wxid":"",
"title":"",
"abstract":"",
"url":"",
"img_path":""},
APIS.WECHAT_MSG_SEND_APP: {"wxid":"",
"appid":""},
# receive message
APIS.WECHAT_MSG_START_HOOK: {"port": 10808},
APIS.WECHAT_MSG_STOP_HOOK: {},
APIS.WECHAT_MSG_START_IMAGE_HOOK: {"save_path":""},
APIS.WECHAT_MSG_STOP_IMAGE_HOOK: {},
APIS.WECHAT_MSG_START_VOICE_HOOK: {"save_path":""},
APIS.WECHAT_MSG_STOP_VOICE_HOOK: {},
# contact
APIS.WECHAT_CONTACT_GET_LIST: {},
APIS.WECHAT_CONTACT_CHECK_STATUS: {"wxid":""},
APIS.WECHAT_CONTACT_DEL: {"wxid":""},
APIS.WECHAT_CONTACT_SEARCH_BY_CACHE: {"wxid":""},
APIS.WECHAT_CONTACT_SEARCH_BY_NET: {"keyword":""},
APIS.WECHAT_CONTACT_ADD_BY_WXID: {"wxid":"",
"msg":""},
APIS.WECHAT_CONTACT_ADD_BY_V3: {"v3":"",
"msg":"",
"add_type": 0x6},
APIS.WECHAT_CONTACT_ADD_BY_PUBLIC_ID: {"public_id":""},
APIS.WECHAT_CONTACT_VERIFY_APPLY: {"v3":"",
"v4":""},
APIS.WECHAT_CONTACT_EDIT_REMARK: {"wxid":"",
"remark":""},
# chatroom
APIS.WECHAT_CHATROOM_GET_MEMBER_LIST: {"chatroom_id":""},
APIS.WECHAT_CHATROOM_GET_MEMBER_NICKNAME: {"chatroom_id":"",
"wxid":""},
# wxids需要以`,`分隔,例如`wxid1,wxid2,wxid3`
APIS.WECHAT_CHATROOM_DEL_MEMBER: {"chatroom_id":"",
"wxids":""},
# wxids需要以`,`分隔,例如`wxid1,wxid2,wxid3`
APIS.WECHAT_CHATROOM_ADD_MEMBER: {"chatroom_id":"",
"wxids":""},
APIS.WECHAT_CHATROOM_SET_ANNOUNCEMENT: {"chatroom_id":"",
"announcement":""},
APIS.WECHAT_CHATROOM_SET_CHATROOM_NAME: {"chatroom_id":"",
"chatroom_name":""},
APIS.WECHAT_CHATROOM_SET_SELF_NICKNAME: {"chatroom_id":"",
"nickname":""},
# database
APIS.WECHAT_DATABASE_GET_HANDLES: {},
APIS.WECHAT_DATABASE_BACKUP: {"db_handle":0,
"save_path":""},
APIS.WECHAT_DATABASE_QUERY: {"db_handle":0,
"sql":""},
# version
APIS.WECHAT_SET_VERSION: {"version": "3.7.0.30"},
# log
APIS.WECHAT_LOG_START_HOOK: {},
APIS.WECHAT_LOG_STOP_HOOK: {},
}
def get_http_template(self, api_number):
try:
return copy.deepcopy(self.__HTTP_API_PARAM_TEMPLATE[api_number])
except KeyError:
raise ValueError("There is no interface numbered %s." % api_number)
get_http_template = WECHAT_HTTP_API_PARAM_TEMPLATES().get_http_template
def post_wechat_http_api(api,port,data = {}):
url = "http://127.0.0.1:{}/api/?type={}".format(port,api)
resp = requests.post(url = url,data = json.dumps(data))
return resp.json()
def get_wechat_http_api(api,port,data = {}):
url = "http://127.0.0.1:{}/api/?type={}".format(port,api)
resp = requests.get(url = url,params = data)
return resp.json()
def get_wechat_pid_list() -> list:
import psutil
pid_list = []
process_list = psutil.pids()
for pid in process_list:
try:
if psutil.Process(pid).name() == 'WeChat.exe':
pid_list.append(pid)
except psutil.NoSuchProcess:
pass
return pid_list
def test():
test_port = 8000
pids = get_wechat_pid_list()
if len(pids) == 0:
pids.append(new_wechat())
start_listen(pids[0],test_port)
if post_wechat_http_api(APIS.WECHAT_IS_LOGIN,port = test_port)["is_login"] == 1:
print(post_wechat_http_api(APIS.WECHAT_GET_SELF_INFO,port = test_port))
data = {"wxid":"filehelper","msg":"hello http"}
post_wechat_http_api(APIS.WECHAT_MSG_SEND_TEXT,data = data,port = test_port)
data = {"receiver":'filehelper',"shared_wxid":"filehelper","nickname":"文件传输助手"}
post_wechat_http_api(APIS.WECHAT_MSG_SEND_CARD,data = data,port = test_port)
data = {"receiver":'filehelper',"img_path":r"D:\VS2019C++\MyWeChatRobot\test\测试图片.png"}
post_wechat_http_api(APIS.WECHAT_MSG_SEND_IMAGE,data = data,port = test_port)
data = {"receiver":'filehelper',"file_path":r"D:\VS2019C++\MyWeChatRobot\test\测试文件"}
post_wechat_http_api(APIS.WECHAT_MSG_SEND_FILE,data = data,port = test_port)
data = {"wxid":'filehelper',
"title":"百度",
"abstract":"百度一下,你就知道",
"url":"https://www.baidu.com/",
"img_path":""}
post_wechat_http_api(APIS.WECHAT_MSG_SEND_ARTICLE,data = data,port = test_port)
print(post_wechat_http_api(APIS.WECHAT_CONTACT_GET_LIST,port = test_port))
data = {"wxid":"filehelper"}
print(post_wechat_http_api(APIS.WECHAT_CONTACT_CHECK_STATUS,data = data,port = test_port))
stop_listen(pids[0])
if __name__ == '__main__':
test()
import ctypes
import json
import requests
PORT = 8000
def call_http_api(api,data,port = PORT):
url = "http://127.0.0.1:{}/api/?type={}".format(port,api)
resp = requests.post(url = url,data = json.dumps(data))
print("POST",resp.json())
def get_wechat_pid_list() -> list:
import psutil
pid_list = []
process_list = psutil.pids()
for pid in process_list:
try:
if psutil.Process(pid).name() == 'WeChat.exe':
pid_list.append(pid)
except psutil.NoSuchProcess:
pass
return pid_list
def test():
data = {"wxid":"filehelper","msg":"hello http"}
call_http_api(2,data)
data = {"receiver":'filehelper',"shared_wxid":"filehelper","nickname":"文件传输助手"}
call_http_api(4,data)
data = {"receiver":'filehelper',"img_path":r"D:\C++\ComWeChatRobot\test\测试图片.png"}
call_http_api(5,data)
data = {"receiver":'filehelper',"file_path":r"D:\C++\ComWeChatRobot\test\测试文件"}
call_http_api(6,data)
data = {"wxid":'filehelper',
"title":"百度",
"abstract":"百度一下,你就知道",
"url":"https://www.baidu.com/",
"img_path":""}
call_http_api(7,data)
wx = ctypes.cdll.LoadLibrary('./wxDriver64.dll')
pids = get_wechat_pid_list()
if len(pids) == 0:
pids.append(wx.new_wechat())
wx.start_listen(pids[0],PORT)
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册