提交 c4d8afe5 编写于 作者: L ljc545w

修复部分已知BUG

上级 d89225dd
......@@ -2,6 +2,7 @@
#define HookImageMsgAddrOffset 0x61211FF6 - 0x60AE0000
#define HookImageMsgNextCallOffset 0x61211430 - 0x60AE0000
#define AutoDownloadTimeSettingOffset 0x239BC50
BOOL ImageMsgHooked = false;
static DWORD WeChatWinBase = GetWeChatWinBase();
......@@ -74,6 +75,9 @@ void __stdcall HookImageMsg() {
if (ImageMsgHooked)
return;
HookAnyAddress(HookImageMsgAddr, dealImageMsg, ImageMsgOldAsm);
char settime[] = "00:00-23:59";
DWORD AutoDownloadTimeSettingAddr = GetWeChatWinBase() + AutoDownloadTimeSettingOffset;
WriteProcessMemory(GetCurrentProcess(), (LPVOID)AutoDownloadTimeSettingAddr, settime, strlen(settime) + 1, 0);
ImageMsgHooked = true;
}
......
......@@ -28,7 +28,7 @@ struct ScoketMsgStruct {
wchar_t wxid[80];
wchar_t message[0x1000B];
wchar_t filepath[MAX_PATH];
wchar_t time[20];
wchar_t time[30];
};
// 是否开启接收消息HOOK标志
......@@ -52,6 +52,10 @@ DWORD SendMessageJmpBackAddress = SendMessageHookAddress + 0x5;
// 通过socket将消息发送给服务端
BOOL SendSocketMessage(ReceiveMsgStruct* ms)
{
if (SRVPORT == 0) {
delete ms;
return false;
}
SOCKET clientsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientsocket < 0)
{
......@@ -85,6 +89,7 @@ BOOL SendSocketMessage(ReceiveMsgStruct* ms)
memcpy(sms->message, ms->message, ms->l_message * 2);
memcpy(sms->filepath, ms->filepath, ms->l_filepath * 2);
memcpy(sms->time, ms->time, ms->l_time * 2);
wcout << sms->time << endl;
int ret = send(clientsocket, (char*)sms, sizeof(ScoketMsgStruct), 0);
if (ret == -1 || ret == 0)
{
......@@ -147,28 +152,21 @@ static SAFEARRAY* CreateMessageArray(ReceiveMsgStruct* ms) {
}
#endif
/*
* 消息处理函数,根据消息缓冲区组装结构并存入容器
* messageAddr:保存消息的缓冲区地址
* return:void
*/
VOID ReceiveMessage(DWORD messageAddr) {
// 此处用于区别是发送的还是接收的消息
static void dealMessage(DWORD messageAddr) {
BOOL isSendMessage = *(BOOL*)(messageAddr + 0x3C);
ReceiveMsgStruct* message = new ReceiveMsgStruct;
ZeroMemory(message, sizeof(ReceiveMsgStruct));
message->isSendMessage = isSendMessage;
message->time = GetTimeW();
message->time = GetTimeW(*(DWORD*)(messageAddr + 0x44));
message->l_time = wcslen(message->time);
message->messagetype = *(DWORD*)(messageAddr + 0x38);
DWORD length = *(DWORD*)(messageAddr + 0x48 + 0x4);
message->sender = new wchar_t[length + 1];
ZeroMemory(message->sender, (length + 1) * 2);
memcpy(message->sender,(wchar_t*)(*(DWORD*)(messageAddr + 0x48)),length * 2);
memcpy(message->sender, (wchar_t*)(*(DWORD*)(messageAddr + 0x48)), length * 2);
message->l_sender = length;
length = *(DWORD*)(messageAddr + 0x170 + 0x4);
if (length == 0) {
message->wxid = new wchar_t[message->l_sender + 1];
......@@ -182,7 +180,7 @@ VOID ReceiveMessage(DWORD messageAddr) {
memcpy(message->wxid, (wchar_t*)(*(DWORD*)(messageAddr + 0x170)), length * 2);
message->l_wxid = length;
}
length = *(DWORD*)(messageAddr + 0x70 + 0x4);
message->message = new wchar_t[length + 1];
ZeroMemory(message->message, (length + 1) * 2);
......@@ -202,12 +200,25 @@ VOID ReceiveMessage(DWORD messageAddr) {
V_ARRAY(&vsaValue) = psaValue;
PostComMessage(&vsaValue);
#endif
HANDLE hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendSocketMessage,message,NULL,0);
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendSocketMessage, message, NULL, 0);
if (hThread) {
CloseHandle(hThread);
}
}
/*
* 消息处理函数,根据消息缓冲区组装结构并存入容器
* messageAddr:保存消息的缓冲区地址
* return:void
*/
VOID ReceiveMessage(DWORD messagesAddr) {
// 此处用于区别是发送的还是接收的消息
DWORD* messages = (DWORD*)messagesAddr;
for (DWORD messageAddr = messages[0]; messageAddr < messages[1]; messageAddr += 0x298) {
dealMessage(messageAddr);
}
}
/*
* HOOK的具体实现,接收到消息后调用处理函数
......@@ -216,8 +227,8 @@ _declspec(naked) void dealReceiveMessage() {
__asm {
pushad;
pushfd;
mov eax, [edi];
push eax;
// mov eax, [edi];
push edi;
call ReceiveMessage;
add esp, 0x4;
popfd;
......@@ -235,7 +246,7 @@ _declspec(naked) void dealSendMessage() {
pushad;
pushfd;
push edi;
call ReceiveMessage;
call dealMessage;
add esp, 0x4;
popfd;
popad;
......
......@@ -162,12 +162,12 @@ wstring wreplace(wstring source, wchar_t replaced, wstring replaceto) {
/*
* 获取当前时间
*/
wchar_t* GetTimeW() {
wchar_t* GetTimeW(long long timestamp) {
wchar_t* wstr = new wchar_t[20];
memset(wstr, 0, 20 * 2);
time_t cTime = time(NULL);
// time_t cTime = time(NULL);
tm tm_out;
localtime_s(&tm_out, &cTime);
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);
......
......@@ -37,6 +37,6 @@ void UnHookAnyAddress(DWORD dwHookAddr, char* originalRecieveCode);
DLLEXPORT void UnHookAll();
wstring wreplace(wstring source, wchar_t replaced, wstring replaceto);
void PrintProcAddr();
wchar_t* GetTimeW();
wchar_t* GetTimeW(long long timestamp);
BOOL ProcessIsWeChat();
BOOL FindOrCreateDirectory(const wchar_t* pszPath);
\ No newline at end of file
......@@ -16,8 +16,11 @@ static void fn(struct mg_connection* c, int ev, void* ev_data, void* fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message* hm = (struct mg_http_message*)ev_data, tmp = { 0 };
if (mg_http_match_uri(hm, "/api/test/")) {
mg_http_reply(c, 200, "", "{\"result\": \"OK\"}", 0, 0);
// cout << hm->method.ptr << endl;
char* wxid = mg_json_get_str(hm->body, "$.wxid");
char* msg = mg_json_get_str(hm->body, "$.msg");
SendText((wchar_t*)L"filehelper", (wchar_t*)L"Ϣ");
mg_http_reply(c, 200, "", "{\"result\": \"OK\"}\n", 0, 0);
}
else if (mg_http_match_uri(hm, "/api/f2/*")) {
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
......@@ -34,6 +37,7 @@ static void fn(struct mg_connection* c, int ev, void* ev_data, void* fn_data) {
}
void HttpStart() {
CreateConsole();
mg_log_set("2");
mg_mgr_init(&mgr);
mg_http_listen(&mgr, s_http_addr, fn, NULL);
......
......@@ -15,7 +15,8 @@ import socketserver
import threading
from comtypes.client import GetEvents
from comtypes.client import PumpEvents
class WeChatEventSink():
"""
接收消息的默认回调,可以自定义,并将实例化对象作为StartReceiveMsgByEvent参数
......@@ -23,8 +24,7 @@ class WeChatEventSink():
"""
def OnGetMessageEvent(self,msg,*args,**kwargs):
print(msg)
class ReceviveMsgBaseServer(socketserver.BaseRequestHandler):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
......@@ -36,7 +36,7 @@ class ReceviveMsgBaseServer(socketserver.BaseRequestHandler):
("wxid",comtypes.c_wchar * 80),
("message",comtypes.c_wchar * 0x1000B),
("filepath",comtypes.c_wchar * 260),
("time",comtypes.c_wchar * 20),
("time",comtypes.c_wchar * 30)
]
def handle(self):
......@@ -44,10 +44,18 @@ class ReceviveMsgBaseServer(socketserver.BaseRequestHandler):
comtypes.CoInitialize()
while True:
try:
ptrdata = conn.recv(comtypes.sizeof(self.ReceiveMsgStruct))
if ptrdata == 'bye'.encode():
break
elif ptrdata:
ptrdata = conn.recv(1024)
try:
if ptrdata.decode() == 'bye':
break
except:
pass
while len(ptrdata) < comtypes.sizeof(self.ReceiveMsgStruct):
data = conn.recv(1024)
if len(data) == 0:
break
ptrdata += data
if ptrdata:
pReceiveMsgStruct = comtypes.cast(ptrdata,comtypes.POINTER(self.ReceiveMsgStruct))
self.msgcallback(pReceiveMsgStruct.contents)
response = "200 OK"
......@@ -72,7 +80,6 @@ class ReceviveMsgBaseServer(socketserver.BaseRequestHandler):
userinfo = robot.GetWxUserInfo(data.sender)
msg['nickname'] = userinfo['wxNickName']
msg['alias'] = userinfo['wxNumber']
print(msg)
# TODO: ...
......@@ -572,7 +579,7 @@ class WeChatRobot():
.
"""
if self.robot.CStartReceiveMessage() != 0:
if self.robot.CStartReceiveMessage(0) != 0:
return
if self.event is not None:
sink = EventSink or WeChatEventSink()
......
......@@ -21,24 +21,6 @@ PC微信机器人,实现以下功能:
微信电脑版**3.7.0.26**
主分支对应微信3.7.0.26版本,其他版本请查看对应分支。
# 写给大家
大家好,最近大家报了好多issue,有的是BUG,有的是问新功能,有的是问如何实现某种功能,看到并且有空的时候就会回复,不过作者没有三头六臂,如果回复不及时还请见谅。
最近填了之前的一些坑,比如数据库无法查询BLOB类型,冗余的接口、缺少的注释,甚至是某个单词拼写错误。。
一些老哥提的需求,也尽可能的往上加了,功能比3.6.0.18又丰富了一些,别的功能,短期是不会添加了,优先解决一些接口导致的崩溃(主要是接收消息),新功能就留到下个微信版本吧。
这几天也一直在着手解决接收消息的bug,不得不说,又学会了一些奇奇怪怪的东西,比如COM的连接点,个人感觉这东西还挺好用的,但COM毕竟是不怎么火的技术,大家想用别的语言实现连接点,资料可能都找不到。
也实现了64位程序注入DLL到32位进程,还有如何使用汇编在内存中构造一个函数。各种花里胡哨。
要是最开始就解决了64位注入32位,可能就根本不会使用COM了。
本来还想在不引入第三方库的情况下,完成http通信,不过想了想,重复发明轮子太耗费脑细胞,等做好说不定微信4.0都出来了。
现在http只有一个测试接口,暂时还不能使用。后面会加上所有功能接口。
一个人搞这个真的很累,有些老哥做了C#、易语言的SDK,感谢你们,有空我会把资源整理一下,写在这里。
也感谢提交BUG的各位,是你们让此项目变得更健壮。
# 编译环境
**Visual Studio 2019**(平台配置:win32(x86))
# 原理
......@@ -66,11 +48,12 @@ CWeChatRobot.exe /unregserver
**Python:**
参考[wxRobot.py](/Python/wxRobot.py)
**C#:**
参考[Program.cs](/wxRobot/Program.cs)
参考[ComWechatRobotCsharp](https://github.com/RingoStudio/ComWechatRobotCsharp),感谢@RingoStudio 的贡献
**ESDK**
参考[ESDK](/ESDK),感谢@lovezm 的贡献
# 更多功能
后续计划功能:
1. 修改好友备注
2. 优化语音和图片Hook
有空的时候会按照上述顺序进行开发,不过嘛,计划只是计划,如果未实现也请见谅
**也欢迎您提交PR**
......@@ -116,7 +99,11 @@ CWeChatRobot.exe /unregserver
## 2022.06.18
1. 修复了多个BUG
2. 整理代码结构,方便后续开发基于websocket的接口
3. 添加64位程序注入DLL到32位程序的driver
3. 添加64位程序注入DLL到32位程序的driver
## 2022.06.24
1. 解决Python脚本中,socket接收数据可能不完整的问题
2. 解决心跳时如果同步了同一个人的多条消息,只会返回一条的问题
3. 感谢@shangdev 提供的思路,现在开启hook图片的时会修改自动下载图片时段为"00:00-23:59"
# 打赏作者
请给作者一个star,感谢感谢
# 免责声明
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册