mirror of
https://github.com/ttttupup/wxhelper.git
synced 2024-11-22 18:29:23 +08:00
commit
5088f5171b
@ -1681,3 +1681,60 @@ enableHttp=0时,使用ip,port的tcp服务回传消息。
|
||||
"msg": "success"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 34.发送小程序**
|
||||
###### 接口功能
|
||||
> 发送小程序(待完善,不稳定),相关参数可以参考示例的滴滴小程序的内容自行组装。
|
||||
|
||||
###### 接口地址
|
||||
> [/api/sendCustomEmotion](/api/sendApplet)
|
||||
|
||||
###### HTTP请求方式
|
||||
> POST JSON
|
||||
|
||||
###### 请求参数
|
||||
|参数|必选|类型|说明|
|
||||
|---|---|---|---|
|
||||
|wxid|string|接收人wxid|
|
||||
|waidConcat|string|app的wxid与回调信息之类绑定的拼接字符串,伪造的数据可以随意|
|
||||
|appletWxid|string|app的wxid|
|
||||
|jsonParam|string|相关参数|
|
||||
|headImgUrl|string|头像url|
|
||||
|mainImg|string|主图的本地路径,需要在小程序的临时目录下|
|
||||
|indexPage|string|小程序的跳转页面|
|
||||
|
||||
|
||||
|
||||
###### 返回字段
|
||||
|返回字段|字段类型|说明 |
|
||||
|---|---|---|
|
||||
|code|int|返回状态,大于0成功, -1失败|
|
||||
|msg|string|成功提示|
|
||||
|data|object|null|
|
||||
|
||||
###### 接口示例
|
||||
|
||||
入参:
|
||||
``` javascript
|
||||
|
||||
{
|
||||
"wxid":"filehelper",
|
||||
"waidConcat":"wxaf35009675aa0b2a_118",
|
||||
"waid":"wxaf35009675aa0b2a",
|
||||
"appletWxid":"gh_7a5c4141778f@app",
|
||||
"jsonParam":"{\"current_path\":\"home/pages/index.html\",\"current_title\":\"\",\"image_url\":\"https://ut-static.udache.com/webx/mini-pics/U7mDFxU2yh-2-r1BJ-J0X.png\",\"scene\":1001,\"scene_note\":\"\",\"sessionId\":\"SessionId@1672284921_1#1692848476899\"}",
|
||||
"headImgUrl":"http://mmbiz.qpic.cn/sz_mmbiz_png/9n47wQlh4dH8afD9dQ9uQicibRm5mYz3lawXCLMjmnzFicribH51qsFYxjzPEcTGHGmgX4lkAkQ3jznia8UDEtqsX1w/640?wx_fmt=png&wxfrom=200",
|
||||
"mainImg":"C:\\wxid_123123\\Applet\\wxaf35009675aa0b2a\\temp\\2.png",
|
||||
"indexPage":"pages/index/index.html"
|
||||
}
|
||||
|
||||
```
|
||||
响应:
|
||||
``` javascript
|
||||
{
|
||||
"code": 1,
|
||||
"data": {},
|
||||
"msg": "success"
|
||||
}
|
||||
```
|
@ -560,6 +560,31 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
|
||||
{"code", success}, {"msg", "success"}, {"data", {}}};
|
||||
ret = ret_data.dump();
|
||||
return ret;
|
||||
} else if (mg_http_match_uri(hm, "/api/sendApplet")) {
|
||||
std::wstring wxid = GetWStringParam(j_param, "wxid");
|
||||
std::wstring waid_concat = GetWStringParam(j_param, "waidConcat");
|
||||
std::string waid = GetStringParam(j_param, "waid");
|
||||
std::string app_wxid = GetStringParam(j_param, "appletWxid");
|
||||
std::string json_param = GetStringParam(j_param, "jsonParam");
|
||||
std::string head_url = GetStringParam(j_param, "headImgUrl");
|
||||
std::string main_img = GetStringParam(j_param, "mainImg");
|
||||
std::string index_page = GetStringParam(j_param, "indexPage");
|
||||
|
||||
std::wstring waid_w = wxhelper::Utils::UTF8ToWstring(waid);
|
||||
|
||||
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->SendApplet(
|
||||
wxid, waid_concat, waid_w, waid, app_wxid, json_param, head_url,
|
||||
main_img, index_page);
|
||||
nlohmann::json ret_data = {
|
||||
{"code", success}, {"msg", "success"}, {"data", {}}};
|
||||
ret = ret_data.dump();
|
||||
return ret;
|
||||
} else if (mg_http_match_uri(hm, "/api/test")) {
|
||||
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->Test();
|
||||
nlohmann::json ret_data = {
|
||||
{"code", success}, {"msg", "success"}, {"data", {}}};
|
||||
ret = ret_data.dump();
|
||||
return ret;
|
||||
} else {
|
||||
nlohmann::json ret_data = {
|
||||
{"code", 200}, {"data", {}}, {"msg", "not support url"}};
|
||||
|
134
src/manager.cc
134
src/manager.cc
@ -28,7 +28,19 @@ prototype::WeChatString * BuildWechatString(const std::wstring &ws){
|
||||
return p;
|
||||
}
|
||||
|
||||
Manager::Manager(UINT64 base) : base_addr_(base) {}
|
||||
prototype::WeChatStr * BuildWechatStr(const std::string &str){
|
||||
prototype::WeChatStr *p = Utils::WxHeapAlloc<prototype::WeChatStr>(
|
||||
sizeof(prototype::WeChatStr));
|
||||
char *p_chat_room_id = Utils::WxHeapAlloc<char>(str.size() + 1);
|
||||
memcpy(p_chat_room_id, str.c_str(), str.size() + 1);
|
||||
p->ptr = p_chat_room_id;
|
||||
p->len = static_cast<DWORD>(str.size());
|
||||
p->maxlen = static_cast<DWORD>(str.size());
|
||||
p->buf = NULL;
|
||||
return p;
|
||||
}
|
||||
|
||||
Manager::Manager(UINT64 base) : base_addr_(base),js_api_addr_(0) {}
|
||||
Manager::~Manager() {}
|
||||
INT64 Manager::CheckLogin() {
|
||||
INT64 success = -1;
|
||||
@ -1095,4 +1107,124 @@ INT64 Manager::SendCustomEmotion(const std::wstring &file_path,
|
||||
reinterpret_cast<UINT64>(temp));
|
||||
return success;
|
||||
}
|
||||
|
||||
INT64 Manager::SendApplet(const std::wstring &recv_wxid,
|
||||
const std::wstring &waid_suff,
|
||||
const std::wstring &waid_w, const std::string &waid_s,
|
||||
const std::string &wa_wxid,
|
||||
const std::string &json_param,
|
||||
const std::string &head_image,
|
||||
const std::string &big_image,
|
||||
const std::string &index_page) {
|
||||
INT64 success = -1;
|
||||
if (js_api_addr_ == 0) {
|
||||
auto vec2 = Utils::QWordScan(base_addr_ + 0x32D1318, 0x1000, 0x8);
|
||||
for (int i = 0; i < vec2.size(); i++) {
|
||||
INT64 ptr = vec2.at(i);
|
||||
if (*(INT64 *)ptr == base_addr_ + 0x32D1318) {
|
||||
js_api_addr_ = ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (js_api_addr_ == 0) {
|
||||
success = -2;
|
||||
return success;
|
||||
}
|
||||
|
||||
UINT64 share_app_msg_addr = base_addr_ + offset::kNewJsApiShareAppMessage;
|
||||
func::__JsApiShareAppMessage share_app_msg =
|
||||
(func::__JsApiShareAppMessage)share_app_msg_addr;
|
||||
|
||||
UINT64 init_addr = base_addr_ + offset::kInitJsConfig;
|
||||
func::__InitJsConfig init = (func::__InitJsConfig)init_addr;
|
||||
|
||||
UINT64 send_applet_addr = base_addr_ + offset::kSendApplet;
|
||||
func::__SendApplet send_applet = (func::__SendApplet)send_applet_addr;
|
||||
|
||||
UINT64 get_by_waid_addr = base_addr_ + offset::kGetAppInfoByWaid;
|
||||
func::__GetAppInfoByWaid get_app_info =
|
||||
(func::__GetAppInfoByWaid)get_by_waid_addr;
|
||||
|
||||
UINT64 copy_app_req_addr = base_addr_ + offset::kCopyShareAppMessageRequest;
|
||||
func::__CopyShareAppMessageRequest copy_app_req =
|
||||
(func::__CopyShareAppMessageRequest)copy_app_req_addr;
|
||||
|
||||
UINT64 new_wa_msg_addr = base_addr_ + offset::kNewWAUpdatableMsgInfo;
|
||||
func::__NewWAUpdatableMsgInfo new_wa_msg =
|
||||
(func::__NewWAUpdatableMsgInfo)new_wa_msg_addr;
|
||||
|
||||
UINT64 free_wa_msg_addr = base_addr_ + offset::kFreeWAUpdatableMsgInfo;
|
||||
func::__FreeWAUpdatableMsgInfo free_wa_msg =
|
||||
(func::__FreeWAUpdatableMsgInfo)free_wa_msg_addr;
|
||||
|
||||
std::vector<prototype::WeChatString> *temp =
|
||||
Utils::WxHeapAlloc<std::vector<prototype::WeChatString>>(0x20);
|
||||
// std::vector<prototype::WeChatString>* temp = new
|
||||
// std::vector<prototype::WeChatString>();
|
||||
common::VectorInner *list = (common::VectorInner *)temp;
|
||||
|
||||
prototype::WeChatString *member = BuildWechatString(recv_wxid);
|
||||
|
||||
list->head = reinterpret_cast<UINT64>(member);
|
||||
list->start = reinterpret_cast<UINT64>(member);
|
||||
list->finsh = reinterpret_cast<UINT64>(member) + 0x20;
|
||||
list->end = reinterpret_cast<UINT64>(member) + 0x20;
|
||||
|
||||
INT64 head = reinterpret_cast<UINT64>(&(list->start));
|
||||
|
||||
prototype::WeChatString *waid_cat = BuildWechatString(waid_suff);
|
||||
prototype::WeChatString *waid = BuildWechatString(waid_w);
|
||||
|
||||
prototype::WeChatString *waid_2 = BuildWechatString(waid_suff);
|
||||
|
||||
prototype::WeChatStr *waid_str = BuildWechatStr(waid_s);
|
||||
prototype::WeChatStr *app_wxid = BuildWechatStr(wa_wxid);
|
||||
prototype::WeChatStr *json_str = BuildWechatStr(json_param);
|
||||
prototype::WeChatStr *head_image_url = BuildWechatStr(head_image);
|
||||
prototype::WeChatStr *image = BuildWechatStr(big_image);
|
||||
prototype::WeChatStr *index = BuildWechatStr(index_page);
|
||||
|
||||
UINT64 app_msg = js_api_addr_;
|
||||
|
||||
UINT64 data = *(UINT64 *)(app_msg + 0x8);
|
||||
char *share_req = Utils::WxHeapAlloc<char>(0x2000);
|
||||
|
||||
char *mid_ptr = Utils::WxHeapAlloc<char>(0x18);
|
||||
memcpy(mid_ptr, &share_req, sizeof(INT64));
|
||||
memcpy(mid_ptr + 0x8, &share_req, sizeof(INT64));
|
||||
memcpy(mid_ptr + 0x10, &share_req, sizeof(INT64));
|
||||
|
||||
memcpy((void *)data, mid_ptr, 0x18);
|
||||
|
||||
memcpy(share_req, (void *)(app_msg + 0x8), sizeof(UINT64));
|
||||
memcpy(share_req + 0x8, (void *)(app_msg + 0x8), sizeof(UINT64));
|
||||
memcpy(share_req + 0x10, (void *)(app_msg + 0x8), sizeof(UINT64));
|
||||
memcpy(share_req + 0x20, waid_2, sizeof(prototype::WeChatString));
|
||||
memcpy(share_req + 0x48, waid_str, sizeof(prototype::WeChatStr));
|
||||
memcpy(share_req + 0x98, app_wxid, sizeof(prototype::WeChatStr));
|
||||
memcpy(share_req + 0xF8, json_str, sizeof(prototype::WeChatStr));
|
||||
memcpy(share_req + 0x178, head_image_url, sizeof(prototype::WeChatStr));
|
||||
memcpy(share_req + 0x198, image, sizeof(prototype::WeChatStr));
|
||||
memcpy(share_req + 0x1c0, index, sizeof(prototype::WeChatStr));
|
||||
|
||||
success = send_applet(app_msg, reinterpret_cast<UINT64>(waid_cat), head, 0);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
INT64 Manager::Test() {
|
||||
auto vec = Utils::QWordScan(base_addr_ + 0x32D1318, 0x1, L"WeChatWin.dll");
|
||||
for (int i = 0; i < vec.size(); i++) {
|
||||
INT64 re = vec.at(i);
|
||||
SPDLOG_INFO("scan result :{},{}", i, re);
|
||||
}
|
||||
|
||||
auto vec2 = Utils::QWordScan(base_addr_ + 0x32D1318, 0x1000, 0x8);
|
||||
for (int i = 0; i < vec2.size(); i++) {
|
||||
INT64 re = vec2.at(i);
|
||||
SPDLOG_INFO("scan2 result :{},{}", i, re);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
} // namespace wxhelper
|
@ -56,9 +56,16 @@ class Manager {
|
||||
INT64 GetVoiceByDB(ULONG64 msg_id, const std::wstring& dir);
|
||||
INT64 SendCustomEmotion(const std::wstring& file_path,
|
||||
const std::wstring& wxid);
|
||||
|
||||
INT64 Manager::SendApplet(
|
||||
const std::wstring& recv_wxid, const std::wstring& waid_suff,
|
||||
const std::wstring& waid_w, const std::string& waid_s,
|
||||
const std::string& wa_wxid, const std::string& json_param,
|
||||
const std::string& head_image, const std::string& big_image,
|
||||
const std::string& index_page);
|
||||
INT64 Test();
|
||||
private:
|
||||
UINT64 base_addr_;
|
||||
UINT64 js_api_addr_;
|
||||
};
|
||||
|
||||
} // namespace wxhelper
|
||||
|
59
src/utils.cc
59
src/utils.cc
@ -1,6 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "utils.h"
|
||||
#include <winternl.h>
|
||||
#include <Psapi.h>
|
||||
#define BUFSIZE 1024
|
||||
#define JPEG0 0xFF
|
||||
#define JPEG1 0xD8
|
||||
@ -398,4 +399,62 @@ INT64 Utils::DecodeImage(const wchar_t* file_path,const wchar_t* save_dir){
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<INT64> Utils::QWordScan(INT64 value, int align,
|
||||
const wchar_t *module) {
|
||||
MODULEINFO module_info;
|
||||
std::vector<INT64> result;
|
||||
if (GetModuleInformation(GetCurrentProcess(), GetModuleHandleW(module),
|
||||
&module_info, sizeof(module_info))) {
|
||||
auto start = static_cast<const char *>(module_info.lpBaseOfDll);
|
||||
const auto end = start + module_info.SizeOfImage - 0x8;
|
||||
|
||||
auto current_addr = start;
|
||||
while (current_addr < end) {
|
||||
if (*(INT64*)current_addr == value) {
|
||||
result.push_back(reinterpret_cast<INT64>(current_addr));
|
||||
}
|
||||
start += align;
|
||||
current_addr = start;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<INT64> Utils::QWordScan(INT64 value, INT64 start,int align) {
|
||||
SYSTEM_INFO sys_info;
|
||||
GetSystemInfo(&sys_info);
|
||||
std::vector<INT64> result;
|
||||
INT64 min_addr =
|
||||
reinterpret_cast<INT64>(sys_info.lpMinimumApplicationAddress);
|
||||
INT64 max_addr =
|
||||
reinterpret_cast<INT64>(sys_info.lpMaximumApplicationAddress);
|
||||
const INT64 page_size = sys_info.dwPageSize;
|
||||
min_addr = min_addr > start ? min_addr : start;
|
||||
|
||||
auto current_addr = min_addr;
|
||||
MEMORY_BASIC_INFORMATION mem_info = {};
|
||||
HANDLE handle = GetCurrentProcess();
|
||||
while (current_addr < max_addr) {
|
||||
VirtualQueryEx(handle, reinterpret_cast<LPVOID>(current_addr), &mem_info,
|
||||
sizeof(MEMORY_BASIC_INFORMATION));
|
||||
|
||||
if ((INT64)mem_info.RegionSize <= 0) {
|
||||
break;
|
||||
}
|
||||
INT64 region_size = mem_info.RegionSize;
|
||||
if ((mem_info.State & MEM_COMMIT) == MEM_COMMIT &&
|
||||
(mem_info.Protect & PAGE_GUARD) != PAGE_GUARD &&
|
||||
(mem_info.Protect & PAGE_NOACCESS) != PAGE_NOACCESS) {
|
||||
for (INT64 i = 0; i < region_size; i += align) {
|
||||
if (value == *(INT64 *)current_addr) {
|
||||
result.push_back(current_addr);
|
||||
}
|
||||
current_addr += align;
|
||||
}
|
||||
} else {
|
||||
current_addr += region_size;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace wxhelper
|
@ -60,6 +60,10 @@ class Utils {
|
||||
|
||||
static INT64 DecodeImage(const wchar_t* file_path,const wchar_t* save_dir);
|
||||
|
||||
static std::vector<INT64> QWordScan(INT64 value, int align,
|
||||
const wchar_t *module);
|
||||
|
||||
static std::vector<INT64> QWordScan(INT64 value, INT64 start,int align);
|
||||
template <typename T1, typename T2>
|
||||
static std::vector<T1> split(T1 str, T2 letter) {
|
||||
std::vector<T1> arr;
|
||||
|
@ -274,6 +274,14 @@ typedef UINT64 (*__GetPreDownLoadMgr)();
|
||||
typedef UINT64 (*__PushAttachTask)(UINT64,UINT64,UINT64,UINT64);
|
||||
typedef UINT64 (*__GetCustomSmileyMgr)();
|
||||
typedef UINT64 (*__SendCustomEmotion)(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
|
||||
typedef UINT64 (*__JsApiShareAppMessage)(UINT64);
|
||||
typedef UINT64 (*__InitJsConfig)(UINT64,UINT64);
|
||||
typedef UINT64 (*__SendApplet)(UINT64,UINT64,UINT64,UINT64);
|
||||
typedef UINT64 (*__SendAppletSecond)(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
|
||||
typedef UINT64 (*__GetAppInfoByWaid)(UINT64,UINT64);
|
||||
typedef UINT64 (*__CopyShareAppMessageRequest)(UINT64,UINT64);
|
||||
typedef UINT64 (*__NewWAUpdatableMsgInfo)(UINT64);
|
||||
typedef UINT64 (*__FreeWAUpdatableMsgInfo)(UINT64);
|
||||
|
||||
|
||||
} // namespace function
|
||||
@ -313,6 +321,26 @@ struct WeChatString {
|
||||
}
|
||||
};
|
||||
|
||||
struct WeChatStr{
|
||||
char * ptr;
|
||||
INT64 buf;
|
||||
INT64 len;
|
||||
INT64 maxlen;
|
||||
|
||||
WeChatStr(const char* p) {
|
||||
ptr = (char *)p;
|
||||
buf = 0;
|
||||
len = strlen(p);
|
||||
maxlen = len | 0xF;
|
||||
}
|
||||
WeChatStr() {
|
||||
ptr = NULL;
|
||||
buf = 0;
|
||||
len = 0;
|
||||
maxlen = 0xF;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace prototype
|
||||
namespace offset {
|
||||
const UINT64 kGetAccountServiceMgr = 0x8c1230;
|
||||
@ -404,6 +432,14 @@ const UINT64 kGetPreDownLoadMgr = 0x9996f0;
|
||||
const UINT64 kPushAttachTask = 0x9c0080;
|
||||
const UINT64 kGetCustomSmileyMgr = 0x915c00;
|
||||
const UINT64 kSendCustomEmotion = 0xec0a40;
|
||||
const UINT64 kNewJsApiShareAppMessage = 0x13be1a0;
|
||||
const UINT64 kInitJsConfig = 0x137bc00;
|
||||
const UINT64 kSendApplet = 0x13c0920;
|
||||
const UINT64 kSendAppletSecond = 0x13c1150;
|
||||
const UINT64 kGetAppInfoByWaid = 0x13c5790;
|
||||
const UINT64 kCopyShareAppMessageRequest = 0x13c0670;
|
||||
const UINT64 kNewWAUpdatableMsgInfo = 0x919ca0;
|
||||
const UINT64 kFreeWAUpdatableMsgInfo = 0x8fc230;
|
||||
|
||||
} // namespace offset
|
||||
} // namespace V3_9_5_81
|
||||
|
Loading…
Reference in New Issue
Block a user