Compare commits

...
Author SHA1 Message Date
hugy a777f05512 fix: add friend by wxid . close #148 2023-06-06 16:02:32 +08:00
hugy 926babbc66 test: add http server 2023-06-05 14:19:12 +08:00
hugy bf0018ae05 feat: hook消息增加http支持 2023-06-05 14:10:24 +08:00
hugy d6d650335f feat: hook消息增加http支持 2023-06-05 14:10:01 +08:00
hugy d22aa9de2d fix: sendAppMsg update free addr 2023-06-03 17:06:48 +08:00
10 changed files with 232 additions and 22 deletions
+7 -1
View File
@@ -284,7 +284,10 @@
#### 9.hook消息**
###### 接口功能
> hook接收文本消息,图片消息,群消息.该接口将hook的消息通过tcp回传给本地的端口
> hook接收文本消息,图片消息,群消息.该接口将hook的消息通过tcp回传给本地的端口。
enableHttp=1时,使用url,timeout参数配置服务端的接收地址。请求为post,Content-Type 为json。
enableHttp=0时,使用ip,port的tcp服务回传消息。
###### 接口地址
> [/api/?type=9](/api/?type=9)
@@ -297,6 +300,9 @@
|---|---|---|---|
|port |true |string| 本地服务端端口,用来接收消息内容 |
|ip |true |string| 服务端ip地址,用来接收消息内容,可以是任意ip,即tcp客户端连接的服务端的ip (3.8.1.26版本)|
|url |true |string| http的请求地址,enableHttp=1时,不能为空 |
|timeout |true |string| 超时时间,单位ms|
|enableHttp |true |number| 0/1 :1.启用http 0.不启用http|
###### 返回字段
|返回字段|字段类型|说明 |
+26
View File
@@ -0,0 +1,26 @@
from fastapi import FastAPI, Request
app = FastAPI()
# pip install fastapi
# run command :uvicorn test:app --reload
# 127.0.0.1:8000/api
@app.post("/api")
def create_item(request: Request):
print("recv msg")
return {"code": 0, "msg": "success"}
@app.middleware("http")
async def TestCustomMiddleware(request: Request, call_next):
the_headers = request.headers
the_body = await request.json()
print(the_headers)
print(the_body)
response = await call_next(request)
return response
+8 -4
View File
@@ -131,13 +131,17 @@ int ContactMgr::AddFriendByWxid(wchar_t *wxid,wchar_t* msg) {
WeChatString w_msg(msg);
DWORD instance =0;
Unkown null_obj={0,0,0,0,0,0xF};
// EDI,0xE ESI,0 all
// EDI,0xE ESI,8 only chat
// EDI,0xE ESI,1 no let look
// EDI,0xE ESI,2 no look
__asm{
PUSHAD
PUSHFD
CALL contact_mgr_addr
MOV dword ptr [instance],EAX
MOV EDI,0x6
MOV ESI,0
MOV EDI,0xE
MOV ESI,0x8
MOV EAX,0x2
SUB ESP,0x18
MOV EAX,ESP
@@ -150,8 +154,8 @@ int ContactMgr::AddFriendByWxid(wchar_t *wxid,wchar_t* msg) {
MOV ECX,ESP
PUSH EAX
CALL fn1_addr
PUSH 0x0
PUSH 0x6
PUSH ESI
PUSH EDI
MOV EAX,w_msg
SUB ESP,0x14
+45 -5
View File
@@ -5,8 +5,10 @@
#include <nlohmann/json.hpp>
#include "thread_pool.h"
#include "wechat_function.h"
#include "http_client.h"
using namespace nlohmann;
using namespace std;
namespace wxhelper {
namespace hooks {
static int server_port_ = 0;
@@ -43,6 +45,8 @@ static DWORD user_info_next_addr_ = 0;
UserInfo userinfo = {};
static bool enable_http_ = false;
VOID CALLBACK SendMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
PTP_WORK Work) {
InnerMessageStruct *msg = (InnerMessageStruct *)context;
@@ -107,6 +111,25 @@ clean:
return;
}
VOID CALLBACK SendHttpMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
PTP_WORK Work) {
InnerMessageStruct *msg = (InnerMessageStruct *)context;
if (msg == NULL) {
SPDLOG_INFO("http msg is null");
return;
}
unique_ptr<InnerMessageStruct> sms(msg);
json j_msg =
json::parse(msg->buffer, msg->buffer + msg->length, nullptr, false);
if (j_msg.is_discarded() == true) {
return;
}
string jstr = j_msg.dump() + "\n";
HttpClient::GetInstance().SendRequest(jstr);
}
void __cdecl OnRecvMsg(DWORD msg_addr) {
json j_msg;
unsigned long long msgid = *(unsigned long long *)(msg_addr + 0x30);
@@ -154,8 +177,14 @@ void __cdecl OnRecvMsg(DWORD msg_addr) {
inner_msg->buffer = new char[jstr.size() + 1];
memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1);
inner_msg->length = jstr.size();
bool add = ThreadPool::GetInstance().AddWork(SendMsgCallback,inner_msg);
SPDLOG_INFO("add msg work:{}",add);
if(enable_http_){
bool add = ThreadPool::GetInstance().AddWork(SendHttpMsgCallback,inner_msg);
SPDLOG_INFO("add http msg work:{}",add);
}else{
bool add = ThreadPool::GetInstance().AddWork(SendMsgCallback,inner_msg);
SPDLOG_INFO("add msg work:{}",add);
}
}
@@ -202,8 +231,13 @@ void __cdecl OnSnsTimeLineMsg(DWORD msg_addr) {
inner_msg->buffer = new char[jstr.size() + 1];
memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1);
inner_msg->length = jstr.size();
bool add = ThreadPool::GetInstance().AddWork(SendMsgCallback,inner_msg);
SPDLOG_INFO("add sns work:{}",add);
if(enable_http_){
bool add = ThreadPool::GetInstance().AddWork(SendHttpMsgCallback,inner_msg);
SPDLOG_INFO("add http msg work:{}",add);
}else{
bool add = ThreadPool::GetInstance().AddWork(SendMsgCallback,inner_msg);
SPDLOG_INFO("add msg work:{}",add);
}
}
/// @brief hook sns msg implement
@@ -221,7 +255,12 @@ _declspec(naked) void HandleSNSMsg() {
}
}
int HookRecvMsg(char *client_ip, int port) {
int HookRecvMsg(char *client_ip, int port,char* url,uint64_t timeout,bool enable) {
enable_http_ = enable;
if(enable_http_){
HttpClient::GetInstance().SetConfig(url,timeout);
}
server_port_ = port;
strcpy_s(server_ip_, client_ip);
DWORD base = Utils::GetWeChatWinBase();
@@ -253,6 +292,7 @@ int HookRecvMsg(char *client_ip, int port) {
int UnHookRecvMsg() {
server_port_ = 0;
enable_http_ = false;
if (!msg_hook_flag_) {
SPDLOG_INFO("recv msg hook already called");
return 2;
+1 -1
View File
@@ -7,7 +7,7 @@ namespace hooks {
extern UserInfo userinfo;
extern bool user_info_flag_ ;
int HookRecvMsg(char* client_ip, int port);
int HookRecvMsg(char* client_ip, int port,char* url,uint64_t timeout,bool enable);
int UnHookRecvMsg();
+65
View File
@@ -0,0 +1,65 @@
#include "pch.h"
#include "http_client.h"
namespace wxhelper {
void HttpClient::SendRequest(std::string content) {
struct mg_mgr mgr;
Data data ;
data.done = false;
data.post_data = content;
mg_mgr_init(&mgr);
mg_http_connect(&mgr, url_.c_str(), OnHttpEvent, &data);
while (!data.done){
mg_mgr_poll(&mgr, 500);
}
mg_mgr_free(&mgr);
}
void HttpClient::OnHttpEvent(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
const char * s_url = GetInstance().url_.c_str();
Data data = *(Data*)fn_data;
if (ev == MG_EV_OPEN) {
// Connection created. Store connect expiration time in c->data
*(uint64_t *) c->data = mg_millis() + GetInstance().timeout_;
} else if (ev == MG_EV_POLL) {
if (mg_millis() > *(uint64_t *) c->data &&
(c->is_connecting || c->is_resolving)) {
mg_error(c, "Connect timeout");
}
} else if (ev == MG_EV_CONNECT) {
struct mg_str host = mg_url_host(s_url);
if (mg_url_is_ssl(s_url)) {
// no implement
}
// Send request
int content_length = data.post_data.size();
mg_printf(c,
"POST %s HTTP/1.0\r\n"
"Host: %.*s\r\n"
"Content-Type: application/json\r\n"
"Content-Length: %d\r\n"
"\r\n",
mg_url_uri(s_url), (int) host.len,
host.ptr, content_length);
mg_send(c, data.post_data.c_str(), content_length);
} else if (ev == MG_EV_HTTP_MSG) {
// Response is received. Print it
#ifdef _DEBUG
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
printf("%.*s", (int) hm->message.len, hm->message.ptr);
#endif
c->is_closing = 1; // Tell mongoose to close this connection
data.done = true; // Tell event loop to stops
} else if (ev == MG_EV_ERROR) {
data.done = true; // Error, tell event loop to stop
}
}
void HttpClient::SetConfig(char* url,uint64_t timeout){
url_=url;
timeout_=timeout;
}
} // namespace wxhelper
+24
View File
@@ -0,0 +1,24 @@
#ifndef WXHELPER_HTTP_CLIENT_H_
#define WXHELPER_HTTP_CLIENT_H_
#include "mongoose.h"
#include "singleton.h"
namespace wxhelper {
struct Data {
bool done;
std::string post_data;
};
class HttpClient : public Singleton<HttpClient> {
public:
void SendRequest(std::string content);
void SetConfig(char* url,uint64_t timeout);
static void OnHttpEvent(struct mg_connection *c, int ev, void *ev_data,
void *fn_data);
private:
std::string url_;
uint64_t timeout_;
};
} // namespace wxhelper
#endif
+10 -1
View File
@@ -171,12 +171,21 @@ string Dispatch(struct mg_connection *c, struct mg_http_message *hm) {
break;
}
case WECHAT_MSG_START_HOOK: {
int port = GetIntParam(j_param, "port");
wstring ip = GetWStringParam(j_param, "ip");
string client_ip = Utils::WstringToUTF8(ip);
int enable = GetIntParam(j_param, "enableHttp");
string s_url ="";
int timeout = 0;
if(enable){
wstring url = GetWStringParam(j_param, "url");
timeout = GetIntParam(j_param, "timeout");
s_url = Utils::WstringToUTF8(url);
}
char ip_cstr[16];
strcpy_s(ip_cstr, client_ip.c_str());
int success = hooks::HookRecvMsg(ip_cstr, port);
int success = hooks::HookRecvMsg(ip_cstr, port,(char *)s_url.c_str(),timeout,enable);
json ret_data = {{"code", success}, {"result", "OK"}};
ret = ret_data.dump();
break;
+18 -9
View File
@@ -391,11 +391,16 @@ int SendMessageMgr::SendAppletMsg(wchar_t* wxid, wchar_t* appletid){
receiver_list.push_back(wwxid);
VectorInner* list = (VectorInner*)&receiver_list;
DWORD receiver_list_ptr = (DWORD)&list->start;
WeChatString wapplet(appletid);
char req[0x268]={0};
char req[0x268] = {0};
char temp[0x4] = {0};
char buff[0x88]={0};
char buff[0x88] = {0};
DWORD flag = 0xF;
DWORD zero = 0;
WeChatStr clean;
WeChatStr app_id(c_applet_id);
__asm{
PUSHAD
PUSHFD
@@ -406,7 +411,8 @@ int SendMessageMgr::SendAppletMsg(wchar_t* wxid, wchar_t* appletid){
}
// 0x40 gh
// 0xE8 img
memcpy(&req[0x4], &c_applet_id, sizeof(c_applet_id));
memcpy(&req[0x4], &app_id, sizeof(app_id));
__asm{
PUSHAD
PUSHFD
@@ -442,15 +448,18 @@ int SendMessageMgr::SendAppletMsg(wchar_t* wxid, wchar_t* appletid){
POPAD
}
__asm{
// no need for WeChat to release memory
memcpy(&req[0x4], &clean, sizeof(clean));
memcpy(&req[0xC8], &zero, sizeof(zero));
memcpy(&req[0xCC], &flag, sizeof(flag));
__asm {
PUSHAD
PUSHFD
LEA ECX,req
PUSH 0x0
CALL free_share_app_msg_req_addr
POPFD
POPAD
}
return success;
}
} // namespace wxhelper
return success;
}
} // namespace wxhelperg
+28 -1
View File
@@ -200,7 +200,8 @@
// send app msg
#define NEW_SHARE_APP_MSG_REQ_OFFSET 0xfbae50
#define FREE_SHARE_APP_MSG_REQ_OFFSET 0xfbc0d0
// #define FREE_SHARE_APP_MSG_REQ_OFFSET 0xfbc0d0
#define FREE_SHARE_APP_MSG_REQ_OFFSET 0xfbc100
#define NEW_WA_UPDATABLE_MSG_INFO_OFFSET 0x7b3d30
#define FREE_WA_UPDATABLE_MSG_INFO_OFFSET 0x79d4c0
#define SEND_APP_MSG_OFFSET 0xfe8e40
@@ -808,4 +809,30 @@ struct ContactProfile{
std::wstring nickname;
std::wstring head_image;
};
struct WeChatStr{
char * ptr;
DWORD field1;
DWORD field2;
DWORD field3;
DWORD len;
DWORD maxlen;
WeChatStr(const char* p) {
ptr = (char *)p;
field1 = 0;
field2 = 0;
field3 = 0;
len = strlen(p);
maxlen = len | 0xF;
}
WeChatStr() {
ptr = NULL;
field1 = 0;
field2 = 0;
field3 = 0;
len = 0;
maxlen = 0xF;
}
};
#endif