Merge pull request #269 from ttttupup/dev-3.9.5.81

feat: 发送小程序(待完善)
This commit is contained in:
ttttupup 2023-08-29 13:33:09 +08:00 committed by GitHub
commit 5088f5171b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 323 additions and 3 deletions

View File

@ -1672,6 +1672,63 @@ enableHttp=0时使用ipport的tcp服务回传消息。
"filePath":"C:\\wechatDir\\WeChat Files\\wxid_123\\FileStorage\\CustomEmotion\\8F\\8F6423BC2E69188DCAC797E279C81DE9"
}
```
响应:
``` javascript
{
"code": 1,
"data": {},
"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

View File

@ -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"}};

View File

@ -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;
}
} // namespace wxhelper
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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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