微信群里的人多了后,总会有些人发广告、发图片、链接什么的,管理员又无法时时盯着群,怎么办呢。自己动手写个吧。谁在群里发指定禁止内容,就警告他或直接踢出群,这样就能很好的管理广告现象了。
1、首页我们要将PC端微信里的消息取出来,以便判断消息里是否有禁止的消息类型和内容。
通过逆向或参考鬼手的资料获取到了接受消息的CALL。
#define ReciveMessage 0x325378
#define ReciveMessageParam 0x13971B8
//计算需要HOOK的地址
DWORD dwHookReciveMsgAddr = (DWORD)GetModuleHandle(L"WeChatWin.dll") + WxReciveMessage;
//返回地址
DWORD RetkReciveMsgAddr = dwHookReciveMsgAddr + 5;
//被覆盖的call的地址
DWORD OverReciveMsgCallAddr = (DWORD)GetModuleHandle(L"WeChatWin.dll") + WxReciveMessageCall;
BYTE bBackCodeRecod[5] = { 0 };
void HookChatRecord()
{
//备份原入口
if (ReadProcessMemory(GetCurrentProcess(), (LPVOID)dwHookReciveMsgAddr, bBackCodeRecod, 5, NULL) == 0) {
MessageBox(NULL, L"hook地址的数据读取失败", L"读取失败", MB_OK);
return;
}
//组装数据
BYTE bJmpCode[5] = { 0xE9 };
*(DWORD*)&bJmpCode[1] = (DWORD)RecieveWxMesage - dwHookReciveMsgAddr - 5;
WriteProcessMemory(GetCurrentProcess(), (LPVOID)dwHookReciveMsgAddr, bJmpCode, 5, 0);
}
__declspec(naked) void RecieveWxMesage()
{
//保存现场
__asm
{
pushad;
push eax;
call SendWxMessage;
popad;
//调用被覆盖的call
call OverReciveMsgCallAddr;
//跳转到返回地址
jmp RetkReciveMsgAddr;
}
}
通过inline hook将目标接收消息的函数跳到自己的方法,以便获取消息内容并发送到我们客户端工具上。
2、本程序使用Sendmessage发送COPYDATASTRUCT消息的通讯方式,将数据传递给客户端。以便数据的进一步处理。
COPYDATASTRUCT chatmsg;
chatmsg.dwData = WM_ShowChatRecord;//保存一个数值, 可以用来作标志等
chatmsg.cbData = sizeof(Message);// strlen(szSendBuf);//待发送的数据的长
chatmsg.lpData = msg.get();// szSendBuf;//待发送的数据的起始地址(可以为NULL)
SendMessage(g_hWndCaller, WM_COPYDATA, (WPARAM)g_hWndCaller, (LPARAM)&chatmsg);
g_hWndCaller:为目标接收信息的窗口句柄。
3、数据处理,数据一般有发文字的、有发图片的、有发图文类信息的(XML)、有发小程序等等几种。除了这几类是我们要处理的,其他的暂时不处理。
//不是相关信息的过滤掉
if (wcscmp(_T("文字"), msg->type) != 0
&& wcscmp(_T("共享实时位置、文件、转账、链接"), msg->type) != 0
&& wcscmp(_T("名片"), msg->type) != 0
)
{
return;
}
根据消息类型分别处理:
if (wcscmp(_T("文字"), msg->type) == 0)
{
if (func_kick_wordover->GetCheck())
{
FuncKickWordOver(msg);//踢掉发内容字数超过100个的
}
if (func_kick_keyword->GetCheck())
{
KickKeyWord(msg);//踢掉 含有 指定 关键词 的
}
}
else if (wcscmp(_T("共享实时位置、文件、转账、链接"), msg->type) == 0)//处理链接
{
if (func_kick_link->GetCheck() || func_kick_smallprogram->GetCheck())
{
FuncKickLinkCheck(msg);//踢掉 发链接 的
}
}
else if (wcscmp(_T("名片"), msg->type) == 0)//踢发名片
{
if (func_kick_mingpian->GetCheck())
{
FuncKickMingpianCheck(msg); //踢掉发片名的
}
}
踢字符数量过大的:
void CFunctionWnd::FuncKickWordOver(Message * msg)
{
//获取微信传进的消息结构体
CDuiString strContent(msg->content);
//获取设置的最大字符数据
CEditUI* pEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("func_kick_wordmax")));
CString strValue = pEdit->GetText().GetData();
int iMax = _ttoi(strValue);
//如果小于指定大小,就不处理了
if (strContent.GetLength() < iMax)
{
return;
}
DelGroupMember(msg->wxid, msg->msgSender);//踢指定当前群的指定人,msgSender就是发消息的人wxid
}
踢人:
void CFunctionWnd::DelGroupMember(CString wxid, CString msgSender)
{
Message user;
wcscpy_s(user.wxid, wxid);
wcscpy_s(user.msgSender, msgSender);
::SendMessage(m_parent, WM_DELETE_USERINFO_BY_USERID, 0, (LPARAM)&user);
}
可以轻松一下啦!上界面图上看看成果吧。