Compare commits

...
15 Commits
Author SHA1 Message Date
hugy bf52de1560 fix: hook http功能 2023-07-14 22:25:55 +08:00
hugy 2ed409e7b0 feat: 群功能相关 2023-07-14 22:25:11 +08:00
ttttupupandGitHub 6f97a499b8 Merge pull request #207 from ttttupup/dev-3.9.5.81
feat: 群功能
2023-07-10 20:27:26 +08:00
hugy d33df9391e feat: 群功能 2023-07-10 20:26:25 +08:00
hugy 23fc28d011 doc: 更新文档 2023-07-08 17:13:38 +08:00
hugy e373b2f063 chore: spdlog module 2023-07-07 15:13:23 +08:00
hugy 7e0b877d99 doc: update doc 2023-07-07 14:57:14 +08:00
hugy 2ee16e36bf chore: add submodules 2023-07-07 14:39:00 +08:00
hugy 91bd8f5977 Merge remote-tracking branch 'origin/dev-3.9.5.81' 2023-07-07 14:03:40 +08:00
hugy a9029e4a3d doc: 发送文件 2023-07-06 21:20:14 +08:00
hugy 53a7938335 fix: free heap bug 2023-07-06 21:15:56 +08:00
ttttupupandGitHub ce72262d58 Merge pull request #202 from terry-tt/main
注入工具
2023-07-06 17:08:36 +08:00
terry-ttandGitHub bdf19fe4e4 Merge branch 'ttttupup:main' into main 2023-07-06 13:58:20 +08:00
terry-ttandGitHub 44623e5b2e Merge pull request #1 from terry-tt/terry-tt-patch-1
注入工具
2023-07-06 13:57:34 +08:00
terry-ttandGitHub 1824d6507c 注入工具 2023-07-06 13:47:56 +08:00
16 changed files with 751 additions and 163 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "spdlog"]
path = spdlog
url = https://github.com/gabime/spdlog
+6 -2
View File
@@ -4,7 +4,7 @@ wechat hook 。PC端微信逆向学习。支持3.8.0.41,3.8.1.26, 3.9.0.28, 3.
本仓库发布的内容,仅用于学习研究,请勿用于非法用途和商业用途!如因此产生任何法律纠纷,均与作者无关!
#### 项目说明:
本项目是个人学习学习逆向的项目,参考 https://github.com/ljc545w/ComWeChatRobot ,在此基础上实现了微信的的其它版本的部分内容。
<font color= "#dd0000">本项目是逆向练习项目,可能会造成封号等后果。请自行承担风险。仅用于学习研究,请勿于非法用途。</font>
#### 实现原理:
逆向分析PC端微信客户端,定位相关功能关键Call,编写dll调用关键Call。然后将该dll文件注入到微信进程。
@@ -19,7 +19,7 @@ dll在注入成功时,创建了一个默认端口为19088的http服务端,
```
#### 使用说明:
支持的版本3.8.0.41、3.8.1.26、3.9.0.28、3.9.2.23、3.9.2.26 。
支持的版本3.8.0.41、3.8.1.26、3.9.0.28、3.9.2.23、3.9.2.26 、3.9.5.81。
源码和主要实现在相应的分支内。
src:主要的dll代码
tool:简单的注入工具,一个是控制台,一个是图形界面。
@@ -62,7 +62,9 @@ cmake
vcpkg
#### 编译构建
先准备好编译环境。
#### <font color= "#dd0000"> 以下是x86环境构建,3.9.5.81是x64环境,具体参考对应分支。</font>
```
cd wxhelper
mkdir build
@@ -179,6 +181,8 @@ port=19099
2023-06-05 :3.9.2.26版本更新
2023-07-07 :3.9.5.81版本更新
#### 功能预览:
0.检查是否登录
1.获取登录微信信息
+263 -1
View File
@@ -164,7 +164,8 @@ data: 接口返回的数据
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,不为0成功, 0失败|
|result|string|成功提示|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
@@ -474,4 +475,265 @@ enableHttp=0时,使用ip,port的tcp服务回传消息。
],
"msg": "success"
}
```
#### 8.发送文件消息**
###### 接口功能
> 发送文件消息
###### 接口地址
> [/api/sendFileMsg](/api/sendFileMsg)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid |true |string| 接收人wxid |
|filePath|true |string|文件绝对路径|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,不为0成功, 0失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"wxid": "filehelper",
"filePath": "c:\\test.zip"
}
```
响应:
``` javascript
{"code":345686720,"msg":"success","data":null}
```
#### 9.获取群详情**
###### 接口功能
> 获取群详情
###### 接口地址
> [/api/getChatRoomDetailInfo](/api/getChatRoomDetailInfo)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|群详细内容|
|&#8194;&#8194;chatRoomId|string|群id|
|&#8194;&#8194;notice|string|公告通知|
|&#8194;&#8194;admin|string|群管理|
|&#8194;&#8194;xml|string|xml信息|
###### 接口示例
入参:
``` javascript
{
"chatRoomId": "12222@chatroom"
}
```
响应:
``` javascript
{"code":345686720,"msg":"success","data":{
"chatRoomId":"12222@chatroom",
"notice":"test",
"admin":"wxid_122333",
"xml":"",
}}
```
#### 10.添加群成员**
###### 接口功能
> 获取群详情
###### 接口地址
> [/api/addMemberToChatRoom](/api/addMemberToChatRoom)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
|memberIds |true |string| 成员id,多个用,分隔 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功,负数失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"21363231004@chatroom",
"memberIds":"wxid_oyb662qhop4422"
}
```
响应:
``` javascript
{"code":1,"msg":"success","data":null}
```
#### 11.修改群昵称**
###### 接口功能
> 修改群昵称
###### 接口地址
> [/api/modifyNickname](/api/modifyNickname)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
|wxid |true |string| 自己的wxid |
|nickName |true |string| 昵称 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"31004@chatroom",
"wxid":"wxid_2721221512",
"nickName":"1221"
}
```
响应:
``` javascript
{"code":1,"msg":"success","data":null}
```
#### 12.删除群成员**
###### 接口功能
> 删除群成员
###### 接口地址
> [/api/delMemberFromChatRoom](/api/delMemberFromChatRoom)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
|memberIds |true |string| 成员id,用,分隔 |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"1234@chatroom",
"memberIds":"wxid_123"
}
```
响应:
``` javascript
{"code":1,"msg":"success","data":null}
```
#### 13.获取群成员**
###### 接口功能
> 获取群成员
###### 接口地址
> [/api/getMemberFromChatRoom](/api/getMemberFromChatRoom)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId |true |string| 群id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
|&#8194;&#8194;chatRoomId|string|群id|
|&#8194;&#8194;members|string|成员id|
|&#8194;&#8194;memberNickname|string|成员昵称|
|&#8194;&#8194;admin|string|群管理|
|&#8194;&#8194;adminNickname|string|管理昵称|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"1234@chatroom"
}
```
响应:
``` javascript
{
"code": 1,
"data": {
"admin": "wxid_2222",
"adminNickname": "123",
"chatRoomId": "22224@chatroom",
"memberNickname": "^G123^G^G",
"members": "wxid_2222^Gwxid_333"
},
"msg": "success"
}
```
-51
View File
@@ -1,51 +0,0 @@
import ctypes
import hashlib
import hmac
# pip install pycryptodome
from Crypto.Cipher import AES
def decrypt(password, input_file, out_file):
password = bytes.fromhex(password.replace(' ', ''))
with open(input_file, 'rb') as (f):
blist = f.read()
print(len(blist))
salt = blist[:16]
key = hashlib.pbkdf2_hmac('sha1', password, salt, DEFAULT_ITER, KEY_SIZE)
first = blist[16:DEFAULT_PAGESIZE]
mac_salt = bytes([x ^ 58 for x in salt])
mac_key = hashlib.pbkdf2_hmac('sha1', key, mac_salt, 2, KEY_SIZE)
hash_mac = hmac.new(mac_key, digestmod='sha1')
hash_mac.update(first[:-32])
hash_mac.update(bytes(ctypes.c_int(1)))
if hash_mac.digest() == first[-32:-12]:
print('decrypt success')
else:
print('password error')
return
blist = [blist[i:i + DEFAULT_PAGESIZE] for i in range(DEFAULT_PAGESIZE, len(blist), DEFAULT_PAGESIZE)]
with open(out_file, 'wb') as (f):
f.write(SQLITE_FILE_HEADER)
t = AES.new(key, AES.MODE_CBC, first[-48:-32])
f.write(t.decrypt(first[:-48]))
f.write(first[-48:])
for i in blist:
t = AES.new(key, AES.MODE_CBC, i[-48:-32])
f.write(t.decrypt(i[:-48]))
f.write(i[-48:])
def main():
password = '565735E30E474DA09250CB5AA047E3940FFA1C6F767C4263B13ABB512933DA49'
input_file = 'C:/var/Applet.db'
out_file = 'c:/var/out/Applet.db'
decrypt(password, input_file, out_file)
if __name__ == '__main__':
SQLITE_FILE_HEADER = bytes('SQLite format 3', encoding='ASCII') + bytes(1)
KEY_SIZE = 32
DEFAULT_PAGESIZE = 4096
DEFAULT_ITER = 64000
main()
+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
+10
View File
@@ -0,0 +1,10 @@
### 常用的一些工具
client.py : 快速测试dll的http接口。
decrpt.py : 微信数据库解密工具。password 为dll个人信息里返回的dbkey。
http_server.py : 一个简单的http server,用来接收hook的消息。
tcpserver.py: 一个简单的tcp server,用来接收hook的消息。
Submodule
+1
Submodule spdlog added at ad0e89cbfb
+1 -1
View File
@@ -101,7 +101,7 @@ VOID CALLBACK SendHttpMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
return;
}
std::string jstr = j_msg.dump() + "\n";
// HttpClient::GetInstance().SendRequest(jstr);
HttpClient::GetInstance().SendRequest(jstr);
}
void HandleSyncMsg(INT64 param1, INT64 param2, INT64 param3) {
+158 -65
View File
@@ -29,6 +29,14 @@ std::wstring GetWStringParam(nlohmann::json data, std::string key) {
return wxhelper::Utils::UTF8ToWstring(data[key].get<std::string>());
}
std::vector<std::wstring> GetArrayParam(nlohmann::json data, std::string key) {
std::vector<std::wstring> result;
std::wstring param = GetWStringParam(data, key);
result = wxhelper::Utils::split(param, L',');
return result;
}
void StartHttpServer(wxhelper::HttpServer *server) {
int port = server->GetPort();
std::string lsten_addr = "http://0.0.0.0:" + std::to_string(port);
@@ -123,7 +131,8 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
return ret;
} else if (mg_http_match_uri(hm, "/api/userInfo")) {
common::SelfInfoInner self_info;
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->GetSelfInfo(self_info);
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetSelfInfo(self_info);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
if (success) {
@@ -148,39 +157,44 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
} else if (mg_http_match_uri(hm, "/api/sendTextMsg")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring msg = GetWStringParam(j_param, "msg");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->SendTextMsg(wxid, msg);
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->SendTextMsg(wxid, msg);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/hookSyncMsg")) {
INT64 success = wxhelper::hooks::HookSyncMsg("127.0.0.1",19099,"",3000,false);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
return ret;
INT64 success =
wxhelper::hooks::HookSyncMsg("127.0.0.1", 19099, "", 3000, false);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/sendImagesMsg")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring path = GetWStringParam(j_param, "imagePath");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->SendImageMsg(wxid, path);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/sendFileMsg")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring path = GetWStringParam(j_param, "filePath");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->SendFileMsg(wxid, path);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getContactList")) {
std::vector<common::ContactInner> vec;
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->GetContacts(vec);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
for (unsigned int i = 0; i < vec.size(); i++) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring path = GetWStringParam(j_param, "imagePath");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->SendImageMsg(wxid, path);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/sendFileMsg")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring path = GetWStringParam(j_param, "filePath");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->SendFileMsg(wxid, path);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getContactList")) {
std::vector<common::ContactInner> vec;
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetContacts(vec);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
for (unsigned int i = 0; i < vec.size(); i++) {
nlohmann::json item = {
{"customAccount", vec[i].custom_account},
{"encryptName", vec[i].encrypt_name},
@@ -194,19 +208,19 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
{"reserved2", vec[i].reserved2},
};
ret_data["data"].push_back(item);
}
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/unhookSyncMsg")) {
INT64 success = wxhelper::hooks::UnHookSyncMsg();
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getDBInfo")) {
std::vector<void *> v_ptr = wxhelper::DB::GetInstance().GetDbHandles();
nlohmann::json ret_data = {{"data", nlohmann::json::array()}};
for (unsigned int i = 0; i < v_ptr.size(); i++) {
}
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/unhookSyncMsg")) {
INT64 success = wxhelper::hooks::UnHookSyncMsg();
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getDBInfo")) {
std::vector<void *> v_ptr = wxhelper::DB::GetInstance().GetDbHandles();
nlohmann::json ret_data = {{"data", nlohmann::json::array()}};
for (unsigned int i = 0; i < v_ptr.size(); i++) {
nlohmann::json db_info;
db_info["tables"] = nlohmann::json::array();
common::DatabaseInfo *db =
@@ -222,38 +236,117 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
db_info["tables"].push_back(table_info);
}
ret_data["data"].push_back(db_info);
}
ret_data["code"] = 1;
ret_data["msg"] = "success";
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/execSql")) {
UINT64 db_handle = GetINT64Param(j_param, "dbHandle");
std::string sql = GetStringParam(j_param, "sql");
std::vector<std::vector<std::string>> items;
int success = wxhelper::DB::GetInstance().Select(db_handle, sql.c_str(), items);
nlohmann::json ret_data = {
{"data", nlohmann::json::array()}, {"code", success}, {"msg", "success"}};
if (success == 0) {
}
ret_data["code"] = 1;
ret_data["msg"] = "success";
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/execSql")) {
UINT64 db_handle = GetINT64Param(j_param, "dbHandle");
std::string sql = GetStringParam(j_param, "sql");
std::vector<std::vector<std::string>> items;
int success =
wxhelper::DB::GetInstance().Select(db_handle, sql.c_str(), items);
nlohmann::json ret_data = {{"data", nlohmann::json::array()},
{"code", success},
{"msg", "success"}};
if (success == 0) {
ret_data["msg"] = "no data";
ret = ret_data.dump();
return ret;
}
for (auto it : items) {
}
for (auto it : items) {
nlohmann::json temp_arr = nlohmann::json::array();
for (size_t i = 0; i < it.size(); i++) {
temp_arr.push_back(it[i]);
}
ret_data["data"].push_back(temp_arr);
}
ret = ret_data.dump();
return ret;
} else {
nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "not support url"}};
ret = ret_data.dump();
return ret;
}
}
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getChatRoomDetailInfo")) {
std::wstring chat_room_id = GetWStringParam(j_param, "chatRoomId");
common::ChatRoomInfoInner chat_room_detail;
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetChatRoomDetailInfo(
chat_room_id, chat_room_detail);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
nlohmann::json detail = {
{"chatRoomId", chat_room_detail.chat_room_id},
{"notice", chat_room_detail.notice},
{"admin", chat_room_detail.admin},
{"xml", chat_room_detail.xml},
};
ret_data["data"] = detail;
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/addMemberToChatRoom")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
std::vector<std::wstring> wxids = GetArrayParam(j_param, "memberIds");
std::vector<std::wstring> wxid_list;
for (unsigned int i = 0; i < wxids.size(); i++) {
wxid_list.push_back(wxids[i]);
}
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->AddMemberToChatRoom(
room_id, wxid_list);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/modifyNickname")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring nickName = GetWStringParam(j_param, "nickName");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->ModChatRoomMemberNickName(
room_id, wxid, nickName);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/delMemberFromChatRoom")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
std::vector<std::wstring> wxids = GetArrayParam(j_param, "memberIds");
std::vector<std::wstring> wxid_list;
for (unsigned int i = 0; i < wxids.size(); i++) {
wxid_list.push_back(wxids[i]);
}
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->DelMemberFromChatRoom(
room_id, wxid_list);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getMemberFromChatRoom")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
common::ChatRoomMemberInner member;
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetMemberFromChatRoom(
room_id, member);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
if (success >= 0) {
nlohmann::json member_info = {
{"admin", member.admin},
{"chatRoomId", member.chat_room_id},
{"members", member.member},
{"adminNickname", member.admin_nickname},
{"memberNickname", member.member_nickname},
};
ret_data["data"] = member_info;
}
ret = ret_data.dump();
return ret;
} else {
nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "not support url"}};
ret = ret_data.dump();
return ret;
}
nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "unreachable code."}};
ret = ret_data.dump();
+172 -25
View File
@@ -10,6 +10,20 @@ namespace func = wxhelper::V3_9_5_81::function;
namespace wxhelper {
prototype::WeChatString * BuildWechatString(const std::wstring &ws){
prototype::WeChatString *p = Utils::WxHeapAlloc<prototype::WeChatString>(
sizeof(prototype::WeChatString));
wchar_t *p_chat_room_id = Utils::WxHeapAlloc<wchar_t>((ws.size() + 1) * 2);
wmemcpy(p_chat_room_id, ws.c_str(), ws.size() + 1);
p->ptr = p_chat_room_id;
p->length = static_cast<DWORD>(ws.size());
p->max_length = static_cast<DWORD>(ws.size());
p->c_len = 0;
p->c_ptr = 0;
return p;
}
Manager::Manager(UINT64 base) : base_addr_(base) {}
Manager::~Manager() {}
INT64 Manager::CheckLogin() {
@@ -251,25 +265,25 @@ INT64 Manager::SendImageMsg(const std::wstring& wxid, const std::wstring& image_
return success;
}
// todo bug 9/10
INT64 Manager::SendFileMsg(const std::wstring& wxid, const std::wstring& file_path){
INT64 success = -1;
prototype::WeChatString* to_user= (prototype::WeChatString*)HeapAlloc(GetProcessHeap(),0,sizeof(prototype::WeChatString));
wchar_t * ptr_wxid = (wchar_t*)HeapAlloc(GetProcessHeap(),0,wxid.length()+1);
wchar_t * ptr_wxid = (wchar_t*)HeapAlloc(GetProcessHeap(),0,(wxid.length()+1)*2);
wmemcpy(ptr_wxid,wxid.c_str(),wxid.length()+1);
to_user->ptr = ptr_wxid;
to_user->length = static_cast<DWORD>(wxid.length());
to_user->max_length = static_cast<DWORD>(wxid.length());
to_user->c_len=0;
to_user->c_ptr=0;
prototype::WeChatString* image_full_path= (prototype::WeChatString*)HeapAlloc(GetProcessHeap(),0,sizeof(prototype::WeChatString));
wchar_t * ptr_path = (wchar_t*)HeapAlloc(GetProcessHeap(),0,file_path.length()+1);
prototype::WeChatString* file_full_path= (prototype::WeChatString*)HeapAlloc(GetProcessHeap(),0,sizeof(prototype::WeChatString));
wchar_t * ptr_path = (wchar_t*)HeapAlloc(GetProcessHeap(),0,(file_path.length()+1)*2);
wmemcpy(ptr_path,file_path.c_str(),file_path.length()+1);
image_full_path->ptr = ptr_path;
image_full_path->length = static_cast<DWORD>(file_path.length());
image_full_path->max_length = static_cast<DWORD>(file_path.length());
image_full_path->c_len = 0;
image_full_path->c_ptr = 0;
file_full_path->ptr = ptr_path;
file_full_path->length = static_cast<DWORD>(file_path.length());
file_full_path->max_length = static_cast<DWORD>(file_path.length());
file_full_path->c_len = 0;
file_full_path->c_ptr = 0;
UINT64 get_app_msg_mgr_addr = base_addr_ + offset::kGetAppMsgMgr;
UINT64 send_file_addr = base_addr_ + offset::kSendFileMsg;
@@ -293,26 +307,15 @@ INT64 Manager::SendFileMsg(const std::wstring& wxid, const std::wstring& file_pa
ZeroMemory(temp3,sizeof(UINT64)*4);
ZeroMemory(temp4,sizeof(UINT64)*4);
*temp4=0x1F;
UINT64 temp5 = 0xC;
UINT64 app_mgr = get_app_mgr();
// UINT64 p_chat_msg = new_chat_msg(reinterpret_cast<UINT64>(chat_msg));
// send_file(app_mgr, p_chat_msg, reinterpret_cast<UINT64>(to_user),
// reinterpret_cast<UINT64>(image_full_path), 1,
// reinterpret_cast<UINT64>(temp1), 0x300,
// reinterpret_cast<UINT64>(temp2), 0,
// reinterpret_cast<UINT64>(temp3),
// reinterpret_cast<UINT64>(temp4),
// temp5);
send_file(app_mgr, reinterpret_cast<UINT64>(chat_msg),
reinterpret_cast<UINT64>(to_user),
reinterpret_cast<UINT64>(image_full_path), 1,
reinterpret_cast<UINT64>(file_full_path), 1,
reinterpret_cast<UINT64>(temp1), 0, reinterpret_cast<UINT64>(temp2),
0, reinterpret_cast<UINT64>(temp3), 0, 0x0);
0, reinterpret_cast<UINT64>(temp3), 0, 0);
free(reinterpret_cast<UINT64>(chat_msg));
HeapFree(GetProcessHeap(),0,to_user);
HeapFree(GetProcessHeap(),0,file_full_path);
HeapFree(GetProcessHeap(),0,temp1);
HeapFree(GetProcessHeap(),0,temp2);
HeapFree(GetProcessHeap(),0,temp3);
@@ -353,4 +356,148 @@ INT64 Manager::GetContacts(std::vector<common::ContactInner> &vec) {
}
return success;
}
} // namespace wxhelper`
INT64 Manager::GetChatRoomDetailInfo(const std::wstring &room_id,
common::ChatRoomInfoInner &room_info) {
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 get_chat_room_detail_addr =
base_addr_ + offset::kGetChatRoomDetailInfo;
UINT64 new_chat_room_info_addr = base_addr_ + offset::kNewChatRoomInfo;
UINT64 free_chat_room_info_addr = base_addr_ + offset::kFreeChatRoomInfo;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__GetChatRoomDetailInfo get_chat_room_detail =
(func::__GetChatRoomDetailInfo)get_chat_room_detail_addr;
func::__NewChatRoomInfo new_chat_room_info =
(func::__NewChatRoomInfo)new_chat_room_info_addr;
func::__FreeChatRoomInfo free_chat_room_info =
(func::__FreeChatRoomInfo)free_chat_room_info_addr;
prototype::WeChatString chat_room_id(room_id);
char chat_room_info[0x148] = {0};
UINT64 p_chat_room_info =
new_chat_room_info(reinterpret_cast<UINT64>(&chat_room_info));
UINT64 mgr = get_chat_room_mgr();
success = get_chat_room_detail(mgr, reinterpret_cast<UINT64>(&chat_room_id),
p_chat_room_info, 1);
room_info.admin = Utils::ReadWstringThenConvert(p_chat_room_info + 0x48);
room_info.chat_room_id =
Utils::ReadWstringThenConvert(p_chat_room_info + 0x8);
room_info.notice = Utils::ReadWstringThenConvert(p_chat_room_info + 0x28);
room_info.xml = Utils::ReadWstringThenConvert(p_chat_room_info + 0x78);
free_chat_room_info(p_chat_room_info);
return success;
}
INT64 Manager::AddMemberToChatRoom(const std::wstring &room_id,
const std::vector<std::wstring> &members) {
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 add_members_addr = base_addr_ + offset::kDoAddMemberToChatRoom;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__DoAddMemberToChatRoom add_members =
(func::__DoAddMemberToChatRoom)add_members_addr;
prototype::WeChatString *chat_room_id = (prototype::WeChatString *)HeapAlloc(
GetProcessHeap(), 0, sizeof(prototype::WeChatString));
wchar_t *p_chat_room_id =
(wchar_t *)HeapAlloc(GetProcessHeap(), 0, (room_id.size() + 1) * 2);
wmemcpy(p_chat_room_id, room_id.c_str(), room_id.size() + 1);
chat_room_id->ptr = p_chat_room_id;
chat_room_id->length = static_cast<DWORD>(room_id.size());
chat_room_id->max_length = static_cast<DWORD>(room_id.size());
chat_room_id->c_len = 0;
chat_room_id->c_ptr = 0;
std::vector<prototype::WeChatString> member_list;
UINT64 temp[2] = {0};
common::VectorInner *list = (common::VectorInner *)&member_list;
INT64 members_ptr = (INT64)&list->start;
for (int i = 0; i < members.size(); i++) {
prototype::WeChatString member(members[i]);
member_list.push_back(member);
}
UINT64 mgr = get_chat_room_mgr();
success =
add_members(mgr, members_ptr, reinterpret_cast<UINT64>(chat_room_id),
reinterpret_cast<UINT64>(&temp));
return success;
}
INT64 Manager::ModChatRoomMemberNickName(const std::wstring &room_id,
const std::wstring &wxid,
const std::wstring &nickname) {
INT64 success = -1;
UINT64 mod_addr = base_addr_ + offset::kDoModChatRoomMemberNickName;
func::__DoModChatRoomMemberNickName modify =
(func::__DoModChatRoomMemberNickName)mod_addr;
const wchar_t *p = room_id.c_str();
prototype::WeChatString *chat_room_id = BuildWechatString(room_id);
prototype::WeChatString *self_id = BuildWechatString(wxid);
prototype::WeChatString *name = BuildWechatString(nickname);
success = modify(
reinterpret_cast<UINT64>(p), reinterpret_cast<UINT64>(chat_room_id),
reinterpret_cast<UINT64>(self_id), reinterpret_cast<UINT64>(name));
return success;
}
INT64 Manager::DelMemberFromChatRoom(const std::wstring &room_id,
const std::vector<std::wstring> &members) {
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 del_members_addr = base_addr_ + offset::kDelMemberFromChatRoom;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__DoDelMemberFromChatRoom del_members =
(func::__DoDelMemberFromChatRoom)del_members_addr;
prototype::WeChatString *chat_room_id = BuildWechatString(room_id);
std::vector<prototype::WeChatString> member_list;
UINT64 temp[2] = {0};
common::VectorInner *list = (common::VectorInner *)&member_list;
INT64 members_ptr = (INT64)&list->start;
for (int i = 0; i < members.size(); i++) {
prototype::WeChatString member(members[i]);
member_list.push_back(member);
}
UINT64 mgr = get_chat_room_mgr();
success =
del_members(mgr, members_ptr, reinterpret_cast<UINT64>(chat_room_id));
return success;
}
INT64 Manager::GetMemberFromChatRoom(const std::wstring &room_id,
common::ChatRoomMemberInner &member) {
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 get_members_addr = base_addr_ + offset::kGetMemberFromChatRoom;
UINT64 new_chat_room_addr = base_addr_ + offset::kNewChatRoom;
UINT64 free_chat_room_addr = base_addr_ + offset::kFreeChatRoom;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__GetMemberFromChatRoom get_members =
(func::__GetMemberFromChatRoom)get_members_addr;
func::__NewChatRoom new_chat_room = (func::__NewChatRoom)new_chat_room_addr;
func::__FreeChatRoom free_chat_room =
(func::__FreeChatRoom)free_chat_room_addr;
prototype::WeChatString chat_room_id(room_id);
char chat_room_info[0x2E0] = {0};
UINT64 addr = reinterpret_cast<UINT64>(&chat_room_info);
new_chat_room(addr);
UINT64 mgr = get_chat_room_mgr();
success = get_members(mgr, reinterpret_cast<UINT64>(&chat_room_id), addr);
member.chat_room_id = Utils::ReadWstringThenConvert(addr + 0x10);
member.admin = Utils::ReadWstringThenConvert(addr + 0x78);
member.member_nickname = Utils::ReadWstringThenConvert(addr + 0x50);
member.admin_nickname = Utils::ReadWstringThenConvert(addr + 0xA0);
member.member = Utils::ReadWeChatStr(addr + 0x30);
free_chat_room(addr);
return success;
}
} // namespace wxhelper
+13
View File
@@ -13,6 +13,19 @@ class Manager {
INT64 SendImageMsg(const std::wstring& wxid, const std::wstring& image_path);
INT64 SendFileMsg(const std::wstring& wxid, const std::wstring& file_path);
INT64 GetContacts(std::vector<common::ContactInner> &vec);
INT64 GetChatRoomDetailInfo(const std::wstring& room_id,
common::ChatRoomInfoInner& room_info);
INT64 AddMemberToChatRoom(const std::wstring& room_id,
const std::vector<std::wstring>& members);
INT64 ModChatRoomMemberNickName(const std::wstring& room_id,
const std::wstring& wxid,
const std::wstring& nickname);
INT64 DelMemberFromChatRoom(const std::wstring& room_id,
const std::vector<std::wstring>& members);
INT64 GetMemberFromChatRoom(const std::wstring& room_id,
common::ChatRoomMemberInner& member);
private:
UINT64 base_addr_;
};
+11 -4
View File
@@ -46,9 +46,9 @@ class Utils {
static std::string WCharToUTF8(wchar_t *wstr);
static bool IsTextUtf8(const char * str,INT64 length) ;
static bool IsTextUtf8(const char *str, INT64 length);
static void Hide(HMODULE module);
static void Hide(HMODULE module);
static std::string ReadSKBuiltinString(INT64 addr);
static std::string ReadSKBuiltinBuffer(INT64 addr);
@@ -57,8 +57,9 @@ class Utils {
static std::string ImageXor(std::string buf);
static std::wstring ReadWstring(INT64 addr);
static std::string ReadWstringThenConvert(INT64 addr);
template <typename T1, typename T2>
static std::vector<T1> split(T1 str, T2 letter) {
static std::vector<T1> split(T1 str, T2 letter) {
std::vector<T1> arr;
size_t pos;
while ((pos = str.find_first_of(letter)) != T1::npos) {
@@ -71,7 +72,7 @@ class Utils {
}
template <typename T1, typename T2>
static T1 replace(T1 source, T2 replaced, T1 replaceto) {
static T1 replace(T1 source, T2 replaced, T1 replaceto) {
std::vector<T1> v_arr = split(source, replaced);
if (v_arr.size() < 2) return source;
T1 temp;
@@ -82,6 +83,12 @@ class Utils {
temp += v_arr[v_arr.size() - 1];
return temp;
}
template <typename T>
static T *WxHeapAlloc(size_t n) {
return (T *)HeapAlloc(GetProcessHeap(), 0, n);
}
};
} // namespace wxhelper
#endif
+74 -14
View File
@@ -161,6 +161,43 @@ struct ContactInner {
}
};
struct ChatRoomInfoInner {
std::string chat_room_id;
std::string notice;
std::string admin;
std::string xml;
ChatRoomInfoInner(){
chat_room_id = "";
notice = "";
admin = "";
xml = "";
}
};
struct VectorInner {
#ifdef _DEBUG
INT64 head;
#endif
INT64 start;
INT64 finsh;
INT64 end;
};
struct ChatRoomMemberInner {
std::string chat_room_id;
std::string admin;
std::string admin_nickname;
std::string member_nickname;
std::string member;
ChatRoomMemberInner()
: chat_room_id(""),
admin(""),
admin_nickname(""),
member_nickname(""),
member("") {}
};
} // namespace common
namespace V3_9_5_81 {
namespace function {
@@ -184,6 +221,19 @@ typedef UINT64(*__Free)();
typedef UINT64 (*__GetContactMgr)();
typedef UINT64 (*__GetContactList)(UINT64,UINT64);
typedef UINT64 (*__GetChatRoomMgr)();
typedef UINT64 (*__NewChatRoomInfo)(UINT64);
typedef UINT64 (*__FreeChatRoomInfo)(UINT64);
typedef UINT64 (*__GetChatRoomDetailInfo)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__DoAddMemberToChatRoom)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__DoModChatRoomMemberNickName)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__DoDelMemberFromChatRoom)(UINT64,UINT64,UINT64);
typedef UINT64 (*__GetMemberFromChatRoom)(UINT64,UINT64,UINT64);
typedef UINT64 (*__NewChatRoom)(UINT64);
typedef UINT64 (*__FreeChatRoom)(UINT64);
} // namespace function
namespace prototype {
@@ -254,21 +304,31 @@ const UINT64 k_sqlite3_column_blob = 0x24f2ba0;
const UINT64 k_sqlite3_column_bytes = 0x24f2c90;
const UINT64 k_sqlite3_finalize = 0x24f1400;
const UINT64 kGPInstance = 0x3a6f908;
const UINT64 kMicroMsgDB= 0xb8;
const UINT64 kChatMsgDB = 0x2c8;
const UINT64 kMiscDB = 0x5f0;
const UINT64 kEmotionDB = 0x838;
const UINT64 kMediaDB = 0xef8;
const UINT64 kBizchatMsgDB = 0x1a70;
const UINT64 kFunctionMsgDB = 0x1b48;
const UINT64 kDBName = 0x28;
const UINT64 kStorageStart = 0x0;
const UINT64 kStorageEnd= 0x0;
const UINT64 kMultiDBMgr= 0x3acfb68;
const UINT64 kPublicMsgMgr= 0x3acc268;
const UINT64 kFavoriteStorageMgr= 0x3acf0d0;
const UINT64 kGPInstance = 0x3a6f908;
const UINT64 kMicroMsgDB = 0xb8;
const UINT64 kChatMsgDB = 0x2c8;
const UINT64 kMiscDB = 0x5f0;
const UINT64 kEmotionDB = 0x838;
const UINT64 kMediaDB = 0xef8;
const UINT64 kBizchatMsgDB = 0x1a70;
const UINT64 kFunctionMsgDB = 0x1b48;
const UINT64 kDBName = 0x28;
const UINT64 kStorageStart = 0x0;
const UINT64 kStorageEnd = 0x0;
const UINT64 kMultiDBMgr = 0x3acfb68;
const UINT64 kPublicMsgMgr = 0x3acc268;
const UINT64 kFavoriteStorageMgr = 0x3acf0d0;
const UINT64 kChatRoomMgr = 0x8e9d30;
const UINT64 kGetChatRoomDetailInfo = 0xe73590;
const UINT64 kNewChatRoomInfo = 0x12006b0;
const UINT64 kFreeChatRoomInfo = 0x1200890;
const UINT64 kDoAddMemberToChatRoom = 0xe63c70;
const UINT64 kDoModChatRoomMemberNickName = 0xe6db00;
const UINT64 kDelMemberFromChatRoom = 0xe64290;
const UINT64 kGetMemberFromChatRoom = 0xe74de0;
const UINT64 kNewChatRoom = 0x11fde50;
const UINT64 kFreeChatRoom = 0x11fe030;
} // namespace offset
} // namespace V3_9_5_81
Binary file not shown.
+13
View File
@@ -1 +1,14 @@
## 可以使用对应分支下的注入工具,或者自己编译一下 source目录下的注入程序。
1.ConsoleApplication.exe
编译好的x64版本的注入器
命令行注入工具,注入命令
``` javascript
//-i 注入程序名 -p 注入dll路径
// -u 卸载程序名 -d 卸载dll名称
//注入
ConsoleInject.exe -i demo.exe -p E:\wxhelper.dll
//卸载
ConsoleInject.exe -u demo.exe -d wxhelper.dll
```
Binary file not shown.