Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
822e076a82 | ||
|
|
3ed52a7dbc | ||
|
|
9e5dce93f0 |
@@ -103,7 +103,7 @@ vcpkg
|
||||
|
||||
2023-02-13 : 新增查询联系人昵称功能。
|
||||
|
||||
2023-02-17 : 新增通过wxid添加好友。
|
||||
2023-02-17 : 新增通过wxid添加好友和查找微信。
|
||||
|
||||
#### 功能预览:
|
||||
0.检查是否登录
|
||||
@@ -116,6 +116,7 @@ vcpkg
|
||||
11.hook图片
|
||||
12.取消hook图片
|
||||
17.删除好友
|
||||
19.通过手机或qq查找微信
|
||||
20.通过wxid添加好友
|
||||
25.获取群成员
|
||||
26.获取群成员昵称
|
||||
@@ -508,6 +509,65 @@ vcpkg
|
||||
{"code":0,"result":"OK"}
|
||||
```
|
||||
|
||||
#### 19.通过手机或qq查找微信**
|
||||
###### 接口功能
|
||||
> 通过手机或qq查找微信
|
||||
|
||||
###### 接口地址
|
||||
> [/api/?type=19](/api/?type=19)
|
||||
|
||||
###### HTTP请求方式
|
||||
> POST JSON
|
||||
|
||||
###### 请求参数
|
||||
|参数|必选|类型|说明|
|
||||
|---|---|---|---|
|
||||
|keyword |true |string| 手机或qq |
|
||||
|
||||
|
||||
###### 返回字段
|
||||
|返回字段|字段类型|说明 |
|
||||
|---|---|---|
|
||||
|code|int|返回状态,1成功, -1失败|
|
||||
|result|string|成功提示|
|
||||
|userInfo|object|用户信息|
|
||||
|  bigImage|string|大头像|
|
||||
|  smallImage|string|小头像|
|
||||
|  city|string|城市|
|
||||
|  nation|string|民族|
|
||||
|  nickname|string|昵称|
|
||||
|  province|string|省|
|
||||
|  sex|number|性别|
|
||||
|  signature|string|签名|
|
||||
|  v2|string|v2|
|
||||
|  v3|string|v3|
|
||||
|
||||
###### 接口示例
|
||||
入参:
|
||||
``` javascript
|
||||
{
|
||||
"keyword":"131111111"
|
||||
}
|
||||
```
|
||||
响应:
|
||||
``` javascript
|
||||
{
|
||||
"code": 1,
|
||||
"result": "OK",
|
||||
"userInfo": {
|
||||
"bigImage": "http://wx.qlogo.cn/mmhead/ver_1/7NIHQAyXeaAPa7Vd7p122mKxgETJwoAiaERdk1sSyOyfnLLQOfElw4G9I32QkZzh7bGfZr2lg0OIQE1Az3cUwtWaLUM79Q/0",
|
||||
"city": "",
|
||||
"nation": "",
|
||||
"nickname": "昵称",
|
||||
"province": "",
|
||||
"sex": 0,
|
||||
"signature": "",
|
||||
"smallImage": "http://wx.qlogo.cn/mmhead/ver_1/7NIHQAyXeaAPa7Vd7p4KR3vxiasmKxgETJwoAiaER23QE6G5mLBcdBQkZzh7bGfZr2lg0OIQE1Az3cUwtWaLUM79Q/132",
|
||||
"v2": "wxid_12333",
|
||||
"v3": "v3_020b3826fd0301000000000098ca23832239a3dba12f95f6b60a0536a1adb6b40fc4086288f46c0b89e6c4eb70c34f118c7b4b6a6845144843b088f0077e406507f821068571289b36c4158a8ac47ec41ae47bee65e9@stranger"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
+37
@@ -22,6 +22,7 @@
|
||||
#include "pat.h"
|
||||
#include "confirm_receipt.h"
|
||||
#include "sns.h"
|
||||
#include "search_contact.h"
|
||||
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
using namespace std;
|
||||
@@ -321,6 +322,26 @@ void api_handle(mg_http_message *hm, struct mg_connection *c, string &ret) {
|
||||
break;
|
||||
}
|
||||
case WECHAT_CONTACT_SEARCH_BY_NET: {
|
||||
wstring keyword = get_http_req_param(hm, j_param, "keyword", is_post);
|
||||
UserInfo *user = nullptr;
|
||||
int success = SearchContactNetScene(WS2LW(keyword), &user);
|
||||
json ret_data = {{"code", success}, {"result", "OK"}};
|
||||
if (user) {
|
||||
json info = {
|
||||
{"bigImage", unicode_to_utf8(user->big_image)},
|
||||
{"smallImage", unicode_to_utf8(user->small_image)},
|
||||
{"city", unicode_to_utf8(user->city)},
|
||||
{"nation", unicode_to_utf8(user->nation)},
|
||||
{"nickname", unicode_to_utf8(user->nickname)},
|
||||
{"province", unicode_to_utf8(user->province)},
|
||||
{"sex", user->sex},
|
||||
{"signature", unicode_to_utf8(user->signature)},
|
||||
{"v2", unicode_to_utf8(user->v2)},
|
||||
{"v3", unicode_to_utf8(user->v3)},
|
||||
};
|
||||
ret_data["userInfo"] = info;
|
||||
}
|
||||
ret = ret_data.dump();
|
||||
break;
|
||||
}
|
||||
case WECHAT_CONTACT_ADD_BY_WXID: {
|
||||
@@ -682,4 +703,20 @@ int http_start(int port) {
|
||||
kHttpThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)http_server,
|
||||
(LPVOID)port, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int http_close() {
|
||||
if (!kHttpRuning) {
|
||||
return 1;
|
||||
}
|
||||
kHttpRuning = false;
|
||||
if (kHttpThread) {
|
||||
WaitForSingleObject(kHttpThread, -1);
|
||||
CloseHandle(kHttpThread);
|
||||
kHttpThread = NULL;
|
||||
}
|
||||
UnHookRecvMsg();
|
||||
UnHookImg();
|
||||
UnHookSearchContact();
|
||||
return 0;
|
||||
}
|
||||
@@ -74,5 +74,6 @@ typedef enum WECHAT_HTTP_APISTag
|
||||
*PWECHAT_HTTP_APIS;
|
||||
|
||||
|
||||
int http_start(int port);
|
||||
extern "C" __declspec(dllexport) int http_start(int port);
|
||||
extern "C" __declspec(dllexport) int http_close();
|
||||
#endif
|
||||
@@ -16,6 +16,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
|
||||
break;
|
||||
}
|
||||
case DLL_PROCESS_DETACH: {
|
||||
http_close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
#include "pch.h"
|
||||
#include "search_contact.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "wechat_data.h"
|
||||
|
||||
#define WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSeT 0xd94d1e
|
||||
#define WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSeT 0xed13a0
|
||||
#define WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSeT 0xa2a260
|
||||
#define WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSeT 0xa2a4c0
|
||||
|
||||
|
||||
#define WX_SEARCH_CONTACT_OFFSeT 0xc5bb00
|
||||
#define WX_SEARCH_CONTACT_MGR_OFFSeT 0xa0d550
|
||||
|
||||
|
||||
|
||||
static BOOL kSearchContactHooked = false;
|
||||
static char kHookSearchContactErrcodeOldAsm[5] = {0};
|
||||
static char kHookUserInfoOldAsm[5] = {0};
|
||||
static DWORD kWeChatWinBase = GetWeChatWinBase();
|
||||
|
||||
static DWORD kHookSearchContactErrcodeNextAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSeT;
|
||||
static DWORD kHookSearchContactErrcodeAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSeT;
|
||||
static DWORD kHookSearchContactErrcodeJmpBackAddr =
|
||||
kHookSearchContactErrcodeAddr + 0x5;
|
||||
|
||||
static DWORD kHookUserInfoNextAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSeT;
|
||||
static DWORD kHookUserInfoAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSeT;
|
||||
static DWORD kHookUserInfoJmpBackAddr = kHookUserInfoAddr + 0x5;
|
||||
|
||||
static UserInfo userinfo;
|
||||
|
||||
void SetErrorCode(int code) { userinfo.error_code = code; }
|
||||
|
||||
void SetUserInfoDetail(DWORD address) {
|
||||
DWORD length = *(DWORD *)(address + 0x8);
|
||||
userinfo.keyword = new wchar_t[length + 1];
|
||||
userinfo.keyword_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.keyword, (wchar_t *)(*(DWORD *)(address + 0x4)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.keyword, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x1C);
|
||||
userinfo.v3 = new wchar_t[length + 1];
|
||||
userinfo.v3_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.v3, (wchar_t *)(*(DWORD *)(address + 0x18)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
}else {
|
||||
ZeroMemory(userinfo.v3, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x30);
|
||||
userinfo.big_image = new wchar_t[length + 1];
|
||||
userinfo.big_image_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.big_image, (wchar_t *)(*(DWORD *)(address + 0x2C)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.big_image, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0xC8);
|
||||
userinfo.nickname = new wchar_t[length + 1];
|
||||
userinfo.nickname_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.nickname, (wchar_t *)(*(DWORD *)(address + 0xC4)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
}else {
|
||||
ZeroMemory(userinfo.nickname, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x108);
|
||||
userinfo.v2 = new wchar_t[length + 1];
|
||||
userinfo.v2_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.v2, (wchar_t *)(*(DWORD *)(address + 0x104)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
}else {
|
||||
ZeroMemory(userinfo.v2, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x16C);
|
||||
userinfo.small_image = new wchar_t[length + 1];
|
||||
userinfo.small_image_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.small_image, (wchar_t *)(*(DWORD *)(address + 0x168)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
}else {
|
||||
ZeroMemory(userinfo.small_image, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x1F8);
|
||||
userinfo.signature = new wchar_t[length + 1];
|
||||
userinfo.signature_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.signature, (wchar_t *)(*(DWORD *)(address + 0x1F4)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.signature, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x20C);
|
||||
userinfo.nation = new wchar_t[length + 1];
|
||||
userinfo.nation_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.nation, (wchar_t *)(*(DWORD *)(address + 0x208)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.nation, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x220);
|
||||
userinfo.province = new wchar_t[length + 1];
|
||||
userinfo.province_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.province, (wchar_t *)(*(DWORD *)(address + 0x21C)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.province, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
length = *(DWORD *)(address + 0x234);
|
||||
userinfo.city = new wchar_t[length + 1];
|
||||
userinfo.city_len = length;
|
||||
if (length) {
|
||||
memcpy(userinfo.city, (wchar_t *)(*(DWORD *)(address + 0x230)),
|
||||
(length + 1) * sizeof(wchar_t));
|
||||
} else {
|
||||
ZeroMemory(userinfo.city, (length + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
userinfo.sex = *(DWORD *)(address + 0x1BC);
|
||||
userinfo.over = true;
|
||||
}
|
||||
|
||||
static void DeleteUserInfoCache() {
|
||||
if (userinfo.keyword) {
|
||||
delete userinfo.keyword;
|
||||
}
|
||||
if (userinfo.v2) {
|
||||
delete userinfo.v2;
|
||||
}
|
||||
if (userinfo.v3) {
|
||||
delete userinfo.v3;
|
||||
}
|
||||
if (userinfo.nickname) {
|
||||
delete userinfo.nickname;
|
||||
}
|
||||
if (userinfo.nation) {
|
||||
delete userinfo.nation;
|
||||
}
|
||||
if (userinfo.province) {
|
||||
delete userinfo.province;
|
||||
}
|
||||
if (userinfo.city) {
|
||||
delete userinfo.city;
|
||||
}
|
||||
if (userinfo.signature) {
|
||||
delete userinfo.signature;
|
||||
}
|
||||
if (userinfo.small_image) {
|
||||
delete userinfo.small_image;
|
||||
}
|
||||
if (userinfo.big_image) {
|
||||
delete userinfo.big_image;
|
||||
}
|
||||
ZeroMemory(&userinfo, sizeof(UserInfo));
|
||||
userinfo.error_code = 1;
|
||||
}
|
||||
|
||||
__declspec(naked) void HandleErrorCode() {
|
||||
__asm {
|
||||
pushad;
|
||||
pushfd;
|
||||
push edi;
|
||||
call SetErrorCode;
|
||||
add esp, 0x4;
|
||||
popfd;
|
||||
popad;
|
||||
call kHookSearchContactErrcodeNextAddr;
|
||||
jmp kHookSearchContactErrcodeJmpBackAddr;
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void HandleUserInfoDetail() {
|
||||
__asm {
|
||||
pushad;
|
||||
pushfd;
|
||||
push dword ptr [ebp + 0x14];
|
||||
call SetUserInfoDetail;
|
||||
add esp, 0x4;
|
||||
popfd;
|
||||
popad;
|
||||
call kHookUserInfoNextAddr;
|
||||
jmp kHookUserInfoJmpBackAddr;
|
||||
}
|
||||
}
|
||||
|
||||
int SearchContactNetScene(wchar_t *keyword,UserInfo ** user) {
|
||||
int success = -1;
|
||||
HookSearchContact();
|
||||
DeleteUserInfoCache();
|
||||
DWORD base = GetWeChatWinBase();
|
||||
DWORD search_contact_mgr_addr = base + WX_SEARCH_CONTACT_MGR_OFFSeT;
|
||||
DWORD search_contact_addr = base + WX_SEARCH_CONTACT_OFFSeT;
|
||||
WeChatString key(keyword);
|
||||
|
||||
__asm {
|
||||
pushad;
|
||||
pushfd;
|
||||
call search_contact_mgr_addr;
|
||||
lea ebx, key;
|
||||
push ebx;
|
||||
mov ecx, eax;
|
||||
call search_contact_addr;
|
||||
popfd;
|
||||
popad;
|
||||
}
|
||||
success = 1;
|
||||
while (userinfo.error_code == 1 && kSearchContactHooked) {
|
||||
Sleep(20);
|
||||
}
|
||||
if (userinfo.error_code == 0) {
|
||||
while (userinfo.over == false && kSearchContactHooked) {
|
||||
Sleep(20);
|
||||
}
|
||||
}
|
||||
*user= &userinfo;
|
||||
return success;
|
||||
}
|
||||
|
||||
int HookSearchContact() {
|
||||
kWeChatWinBase = GetWeChatWinBase();
|
||||
if (!kWeChatWinBase) {
|
||||
return -1;
|
||||
}
|
||||
if (kSearchContactHooked) {
|
||||
return 2;
|
||||
}
|
||||
kHookSearchContactErrcodeNextAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_NEXT_OFFSeT;
|
||||
kHookSearchContactErrcodeAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_ERROR_CODE_HOOK_OFFSeT;
|
||||
kHookSearchContactErrcodeJmpBackAddr = kHookSearchContactErrcodeAddr + 0x5;
|
||||
|
||||
kHookUserInfoNextAddr =
|
||||
kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_NEXT_OFFSeT;
|
||||
kHookUserInfoAddr = kWeChatWinBase + WX_SEARCH_CONTACT_DETAIL_HOOK_OFFSeT;
|
||||
kHookUserInfoJmpBackAddr = kHookUserInfoAddr + 0x5;
|
||||
HookAnyAddress(kHookSearchContactErrcodeAddr,
|
||||
(LPVOID)HandleErrorCode,
|
||||
kHookSearchContactErrcodeOldAsm);
|
||||
HookAnyAddress(kHookUserInfoAddr, (LPVOID)HandleUserInfoDetail, kHookUserInfoOldAsm);
|
||||
kSearchContactHooked = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int UnHookSearchContact() {
|
||||
if (!kSearchContactHooked) return 2;
|
||||
UnHookAnyAddress(kHookSearchContactErrcodeAddr,
|
||||
kHookSearchContactErrcodeOldAsm);
|
||||
UnHookAnyAddress(kHookUserInfoAddr, kHookUserInfoOldAsm);
|
||||
kSearchContactHooked = false;
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef SEARCH_CONTACT_H_
|
||||
#define SEARCH_CONTACT_H_
|
||||
#include "wechat_data.h"
|
||||
int SearchContactNetScene(wchar_t *keyword,UserInfo ** user);
|
||||
|
||||
int HookSearchContact();
|
||||
int UnHookSearchContact();
|
||||
#endif
|
||||
@@ -155,4 +155,30 @@ struct SelfInfoInner{
|
||||
std::string data_save_path;
|
||||
std::string current_data_path;
|
||||
};
|
||||
|
||||
struct UserInfo {
|
||||
int error_code;
|
||||
wchar_t *keyword;
|
||||
int keyword_len;
|
||||
wchar_t *v3;
|
||||
int v3_len;
|
||||
wchar_t *nickname;
|
||||
int nickname_len;
|
||||
wchar_t *signature;
|
||||
int signature_len;
|
||||
wchar_t *v2;
|
||||
int v2_len;
|
||||
wchar_t *nation;
|
||||
int nation_len;
|
||||
wchar_t *province;
|
||||
int province_len;
|
||||
wchar_t *city;
|
||||
int city_len;
|
||||
wchar_t *big_image;
|
||||
int big_image_len;
|
||||
wchar_t *small_image;
|
||||
int small_image_len;
|
||||
DWORD sex;
|
||||
BOOL over;
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user