Compare commits

...
12 Commits
Author SHA1 Message Date
hugy 6436ce072a fix: 返回值修改 2023-08-08 20:46:08 +08:00
hugy 58caad4f34 doc: client 2023-08-08 17:44:49 +08:00
hugy bdf91943f3 feat: 发送@消息 2023-08-08 17:41:30 +08:00
hugy 129bb55c36 feat:收藏 2023-08-05 10:52:28 +08:00
hugy e9a6e0da57 feat: sns 2023-08-04 16:40:10 +08:00
hugy 9b4d326d63 doc:更新文档 2023-07-31 16:18:05 +08:00
hugy 64ba6007a8 feat:退群和转发 2023-07-31 16:11:47 +08:00
hugy ae44434662 fix:删除测试 2023-07-29 17:11:36 +08:00
hugy 1268d37a57 feat: 建群 2023-07-29 10:03:59 +08:00
hugy 17aff3b6aa feat: 邀请入群,hook日志 2023-07-27 21:18:42 +08:00
hugy 7e06eaf4e4 fix: 消除警告 2023-07-22 09:17:20 +08:00
hugy b996a9d91c feat: 群消息置顶 2023-07-22 09:13:50 +08:00
12 changed files with 1691 additions and 19 deletions
+630 -1
View File
@@ -215,7 +215,7 @@ enableHttp=0时,使用ip,port的tcp服务回传消息。
入参:
``` javascript
{
"port": "19099"
"port": "19099",
"ip":"127.0.0.1",
"url":"http://localhost:8080",
"timeout":"3000",
@@ -736,4 +736,633 @@ enableHttp=0时,使用ip,port的tcp服务回传消息。
},
"msg": "success"
}
```
#### 14.置顶群消息**
###### 接口功能
> 置顶群消息,需要群主权限
###### 接口地址
> [/api/topMsg](/api/topMsg)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|msgId |true |string| 消息id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"msgId":8005736725060623215
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 15.移除置顶群消息**
###### 接口功能
> 移除置顶群消息,需要群主权限
###### 接口地址
> [/api/removeTopMsg](/api/removeTopMsg)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|msgId |true |string| 消息id |
|chatRoomId |true |string| 群id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"msgId":8005736725060623215,
"chatRoomId":"12345678@chatroom"
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 16.邀请入群**
###### 接口功能
> 邀请入群,(40人以上的群需要使用邀请入群)
###### 接口地址
> [/api/InviteMemberToChatRoom](/api/InviteMemberToChatRoom)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|memberIds |true |string| wxid,用,分隔 |
|chatRoomId |true |string| 群id |
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"memberIds":"wxid_123,wxid_12341",
"chatRoomId":"12345678@chatroom"
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 17.hook日志**
###### 接口功能
> hook微信日志,输出在wechat安装目录的logs目录下
###### 接口地址
> [/api/hookLog](/api/hookLog)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,0成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{
"code": 0,
"data": null,
"msg": "success"
}
```
#### 18.取消hook日志**
###### 接口功能
> 取消hook日志
###### 接口地址
> [/api/unhookLog](/api/unhookLog)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,0成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{
"code": 0,
"data": null,
"msg": "success"
}
```
#### 19.建群**
###### 接口功能
> 建群(不建议使用,容易被封,测试期间被封了,无法保证效果)
###### 接口地址
> [/api/createChatRoom](/api/createChatRoom)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|memberIds|string|群成员id,以,分割|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,0成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 20.退群**
###### 接口功能
> 退群
###### 接口地址
> [/api/quitChatRoom](/api/quitChatRoom)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|chatRoomId|string|群id|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,大于0成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"chatRoomId":"123456@chatroom"
}
```
响应:
``` javascript
{
"code": 119536579329,
"data": null,
"msg": "success"
}
```
#### 21.转发消息**
###### 接口功能
> 转发消息
###### 接口地址
> [/api/forwardMsg](/api/forwardMsg)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid|string|接收人id|
|msgId|string|消息id|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"wxid":"filehelper",
"msgId":"1233312233123"
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 22.朋友圈首页**
###### 接口功能
> 朋友圈首页,前置条件需先调用hook消息接口成功,具体内容会在hook消息里返回,格式如下:
``` javascript
{
"data":[
{
"content": "",
"createTime': 1691125287,
"senderId': "",
"snsId': 123,
"xml':""
}
]
}
```
###### 接口地址
> [/api/getSNSFirstPage](/api/getSNSFirstPage)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 23.朋友圈下一页**
###### 接口功能
> 朋友圈下一页
###### 接口地址
> [/api/getSNSNextPage](/api/getSNSNextPage)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|snsId|number|snsId|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"snsid":123
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 24.收藏消息**
###### 接口功能
> 收藏消息
###### 接口地址
> [/api/addFavFromMsg](/api/addFavFromMsg)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|msgId|number|消息id|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"msgId":123
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 24.收藏图片**
###### 接口功能
> 收藏图片
###### 接口地址
> [/api/addFavFromImage](/api/addFavFromImage)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid|string|wxid|
|imagePath|string|图片地址|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,1成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"wxid":"wxid_12333",
"imagePath":"C:\\test\\test.png"
}
```
响应:
``` javascript
{
"code": 1,
"data": null,
"msg": "success"
}
```
#### 25.发送@消息**
###### 接口功能
> 发送@消息
###### 接口地址
> [/api/sendAtText](/api/sendAtText)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxids|string|wxid字符串,多个用,分隔,发送所有人传值"notify@all"|
|chatRoomId|string|群id|
|msg|string|消息内容|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,大于0成功, -1失败|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
入参:
``` javascript
{
"wxids":"notify@all",
"chatRoomId":"123@chatroom",
"msg":"你们好啊"
}
```
响应:
``` javascript
{
"code": 67316444768,
"data": null,
"msg": "success"
}
```
#### 26.获取群成员信息**
###### 接口功能
> 获取群成员基础信息
###### 接口地址
> [/api/getContactProfile](/api/getContactProfile)
###### HTTP请求方式
> POST JSON
###### 请求参数
|参数|必选|类型|说明|
|---|---|---|---|
|wxid|string|wxid|
###### 返回字段
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,大于0成功, -1失败|
|msg|string|成功提示|
|data|object|null|
|  account|string|账号|
|  headImage|string|头像|
|  nickname|string|昵称|
|  v3|string|v3|
|  wxid|string|wxid|
###### 接口示例
入参:
``` javascript
{
"wxid":"wxid_123"
}
```
响应:
``` javascript
{
"code": 1,
"data": {
"account": "account",
"headImage": "https://wx.qlogo.cn/mmhead/ver_1/0",
"nickname": "test",
"v3": "wxid_123",
"wxid": "wxid_123"
},
"msg": "success"
}
```
+401
View File
@@ -0,0 +1,401 @@
import requests
import json
def checkLogin():
url = "127.0.0.1:19088/api/checkLogin"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def userInfo():
url = "127.0.0.1:19088/api/userInfo"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def sendTextMsg():
url = "127.0.0.1:19088/api/sendTextMsg"
payload = json.dumps({
"wxid": "filehelper",
"msg": "12www"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def sendImagesMsg():
url = "127.0.0.1:19088/api/sendImagesMsg"
print("modify imagePath")
raise RuntimeError("modify imagePath then deleted me")
payload = json.dumps({
"wxid": "filehelper",
"imagePath": "C:\\pic.png"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def sendFileMsg():
url = "127.0.0.1:19088/api/sendFileMsg"
print("modify filePath")
raise RuntimeError("modify filePath then deleted me")
payload = json.dumps({
"wxid": "filehelper",
"filePath": "C:\\test.zip"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def hookSyncMsg():
url = "127.0.0.1:19088/api/hookSyncMsg"
print("modify ip port url ")
raise RuntimeError("modify ip port url then deleted me")
payload = json.dumps({
"port": "19099",
"ip": "127.0.0.1",
"url": "http://localhost:8080",
"timeout": "3000",
"enableHttp": "0"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def unhookSyncMsg():
url = "127.0.0.1:19088/api/unhookSyncMsg"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getContactList():
url = "127.0.0.1:19088/api/getContactList"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getDBInfo():
url = "127.0.0.1:19088/api/getDBInfo"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def execSql():
url = "127.0.0.1:19088/api/execSql"
print("modify dbHandle ")
raise RuntimeError("modify dbHandle then deleted me")
payload = json.dumps({
"dbHandle": 1713425147584,
"sql": "select * from MSG where localId =100;"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getChatRoomDetailInfo():
url = "127.0.0.1:19088/api/getChatRoomDetailInfo"
print("modify chatRoomId ")
raise RuntimeError("modify chatRoomId then deleted me")
payload = json.dumps({
"chatRoomId": "123333@chatroom"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def addMemberToChatRoom():
url = "127.0.0.1:19088/api/addMemberToChatRoom"
print("modify chatRoomId memberIds ")
raise RuntimeError("modify chatRoomId memberIds then deleted me")
payload = json.dumps({
"chatRoomId": "123@chatroom",
"memberIds": "wxid_123"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def delMemberFromChatRoom():
url = "127.0.0.1:19088/api/delMemberFromChatRoom"
print("modify chatRoomId memberIds ")
raise RuntimeError("modify chatRoomId memberIds then deleted me")
payload = json.dumps({
"chatRoomId": "21363231004@chatroom",
"memberIds": "wxid_123"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def modifyNickname():
url = "127.0.0.1:19088/api/modifyNickname"
print("modify chatRoomId wxid nickName")
raise RuntimeError("modify chatRoomId wxid nickName then deleted me")
payload = json.dumps({
"chatRoomId": "123@chatroom",
"wxid": "wxid_123",
"nickName": "test"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getMemberFromChatRoom():
print("modify chatRoomId ")
raise RuntimeError("modify chatRoomId then deleted me")
url = "127.0.0.1:19088/api/getMemberFromChatRoom"
payload = json.dumps({
"chatRoomId": "123@chatroom"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def topMsg():
print("modify msgId ")
raise RuntimeError("modify msgId then deleted me")
url = "127.0.0.1:19088/api/topMsg"
payload = json.dumps({
"msgId": 1222222
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def removeTopMsg():
print("modify msgId chatRoomId ")
raise RuntimeError("modify msgId chatRoomId then deleted me")
url = "127.0.0.1:19088/api/removeTopMsg"
payload = json.dumps({
"chatRoomId": "123@chatroom",
"msgId": 123
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def InviteMemberToChatRoom():
print("modify memberIds chatRoomId ")
raise RuntimeError("modify memberIds chatRoomId then deleted me")
url = "127.0.0.1:19088/api/InviteMemberToChatRoom"
payload = json.dumps({
"chatRoomId": "123@chatroom",
"memberIds": "wxid_123"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def hookLog():
url = "127.0.0.1:19088/api/hookLog"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def unhookLog():
url = "127.0.0.1:19088/api/unhookLog"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def createChatRoom():
print("modify memberIds ")
raise RuntimeError("modify memberIds then deleted me")
url = "127.0.0.1:19088/api/createChatRoom"
payload = json.dumps({
"memberIds": "wxid_8yn4k908tdqp22,wxid_oyb662qhop4422"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def quitChatRoom():
print("modify chatRoomId ")
raise RuntimeError("modify chatRoomId then deleted me")
url = "127.0.0.1:19088/api/quitChatRoom"
payload = json.dumps({
"chatRoomId": "123@chatroom"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def forwardMsg():
print("modify msgId ")
raise RuntimeError("modify msgId then deleted me")
url = "127.0.0.1:19088/api/forwardMsg"
payload = json.dumps({
"wxid": "filehelper",
"msgId": "12331"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getSNSFirstPage():
url = "127.0.0.1:19088/api/getSNSFirstPage"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getSNSNextPage():
print("modify snsId ")
raise RuntimeError("modify snsId then deleted me")
url = "127.0.0.1:19088/api/getSNSNextPage"
payload = json.dumps({
"snsId": ""
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def addFavFromMsg():
print("modify msgId ")
raise RuntimeError("modify msgId then deleted me")
url = "127.0.0.1:19088/api/addFavFromMsg"
payload = json.dumps({
"msgId": "1222222"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def addFavFromImage():
print("modify wxid imagePath ")
raise RuntimeError("modify wxid imagePath then deleted me")
url = "127.0.0.1:19088/api/addFavFromImage"
payload = json.dumps({
"wxid": "",
"imagePath": ""
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def getContactProfile():
print("modify wxid ")
raise RuntimeError("modify wxid then deleted me")
url = "127.0.0.1:19088/api/getContactProfile"
payload = json.dumps({
"wxid": ""
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
def sendAtText():
print("modify wxids chatRoomId")
raise RuntimeError("modify wxids chatRoomId then deleted me")
url = "127.0.0.1:19088/api/sendAtText"
payload = json.dumps({
"wxids": "notify@all",
"chatRoomId": "123@chatroom",
"msg": "你好啊"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
if __name__ == '__main__':
checkLogin()
# userInfo()
+13 -1
View File
@@ -933,7 +933,10 @@ int InjectDll(wchar_t* szPName, wchar_t* szDllPath)
result = 1;
}
else
{
{
DWORD dErrorCode = GetLastError();
printf("dll inject fail");
printf("error code : %d ", dErrorCode);
VirtualFreeEx(hProcess, lpRemoteDllBase, ulDllLength, MEM_DECOMMIT | MEM_RELEASE);
CloseHandle(hProcess);
result = 0;
@@ -941,6 +944,9 @@ int InjectDll(wchar_t* szPName, wchar_t* szDllPath)
}
else
{
DWORD dErrorCode = GetLastError();
printf("dll inject fail.VirtualAllocEx method fail.");
printf("error code : %d ", dErrorCode);
CloseHandle(hProcess);
result = 0;
}
@@ -986,6 +992,9 @@ int InjectDllByPid(unsigned int pid, wchar_t* szDllPath)
}
else
{
DWORD dErrorCode = GetLastError();
printf("dll inject fail");
printf("error code : %d ", dErrorCode);
VirtualFreeEx(hProcess, lpRemoteDllBase, ulDllLength, MEM_DECOMMIT | MEM_RELEASE);
CloseHandle(hProcess);
result = 0;
@@ -993,6 +1002,9 @@ int InjectDllByPid(unsigned int pid, wchar_t* szDllPath)
}
else
{
DWORD dErrorCode = GetLastError();
printf("dll inject fail.VirtualAllocEx method fail.");
printf("error code : %d ", dErrorCode);
CloseHandle(hProcess);
result = 0;
}
+2 -1
View File
@@ -344,6 +344,7 @@ std::vector<void *> DB::GetDbHandles() {
msg0_db.db_name = (wchar_t *)(*(UINT64 *)(db_addr));
msg0_db.db_name_len = *(DWORD *)(db_addr + 0x8);
msg0_db.handle = msg0_db_addr;
msg0_db.extrainfo = *(UINT64 *)(*(UINT64 *)(db_addr + 0x28) + 0x1E8);
ExecuteSQL(msg0_db_addr,
"select * from sqlite_master where type=\"table\";",
(UINT64)GetDbInfo, &msg0_db);
@@ -458,7 +459,7 @@ std::vector<std::string> DB::GetChatMsgByMsgId(ULONG64 msgid) {
wchar_t dbname[20] = {0};
for (int i = 0;; i++) {
swprintf_s(dbname, L"MSG%d.db", i);
DWORD handle = GetDbHandleByDbName(dbname);
UINT64 handle = GetDbHandleByDbName(dbname);
if (handle == 0) {
// LOG(INFO) << "MSG db handle is null";
return {};
+3 -1
View File
@@ -17,7 +17,9 @@ GlobalContext::~GlobalContext() {
void GlobalContext::initialize(HMODULE module) {
state =GlobalContextState::INITIALIZING;
module_ = module;
// Utils::Hide(module);
#ifndef _DEBUG
Utils::Hide(module);
#endif
UINT64 base = Utils::GetWeChatWinBase();
config.emplace();
config->Initialize();
-7
View File
@@ -24,13 +24,6 @@ class GlobalContext : public Singleton<GlobalContext> {
std::unique_ptr<HttpServer> http_server;
std::unique_ptr<Manager> mgr;
// std::optional<ContactMgr> contact_mgr;
// std::optional<MiscMgr> misc_mgr;
// std::optional<SendMessageMgr> send_mgr;
// std::optional<AccountMgr> account_mgr;
// std::optional<ChatRoomMgr> chat_room_mgr;
// std::optional<SNSMgr> sns_mgr;
GlobalContextState state = GlobalContextState::NOT_INITIALIZED;
private:
+118 -3
View File
@@ -16,12 +16,25 @@ static int kServerPort = 19099;
static bool kMsgHookFlag = false;
static char kServerIp[16] = "127.0.0.1";
static bool kEnableHttp = false;
static bool kLogHookFlag = false;
static bool kSnsFinishHookFlag = false;
static UINT64 (*R_DoAddMsg)(UINT64, UINT64, UINT64) = (UINT64(*)(
UINT64, UINT64, UINT64))(Utils::GetWeChatWinBase() + offset::kDoAddMsg);
static UINT64 (*R_Log)(UINT64, UINT64, UINT64, UINT64, UINT64, UINT64, UINT64,
UINT64, UINT64, UINT64, UINT64, UINT64) =
(UINT64(*)(UINT64, UINT64, UINT64, UINT64, UINT64, UINT64, UINT64, UINT64,
UINT64, UINT64, UINT64,
UINT64))(Utils::GetWeChatWinBase() + offset::kHookLog);
static UINT64 (*R_OnSnsTimeLineSceneFinish)(UINT64, UINT64, UINT64) =
(UINT64(*)(UINT64, UINT64, UINT64))(Utils::GetWeChatWinBase() +
offset::kOnSnsTimeLineSceneFinish);
VOID CALLBACK SendMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
PTP_WORK Work) {
common::InnerMessageStruct *msg = (common::InnerMessageStruct *)context;
@@ -140,6 +153,59 @@ void HandleSyncMsg(INT64 param1, INT64 param2, INT64 param3) {
R_DoAddMsg(param1,param2,param3);
}
UINT64 HandlePrintLog(UINT64 param1, UINT64 param2, UINT64 param3, UINT64 param4,
UINT64 param5, UINT64 param6, UINT64 param7, UINT64 param8,
UINT64 param9, UINT64 param10, UINT64 param11,
UINT64 param12) {
UINT64 p = R_Log(param1, param2, param3, param4, param5, param6, param7, param8, param9,
param10, param11, param12);
if(p== 0 || p == 1){
return p;
}
char *msg = (char *)p;
if (msg != NULL) {
// INT64 size = *(INT64 *)(p - 0x8);
std::string str(msg);
std::wstring ws = Utils::UTF8ToWstring(str);
std::string out = Utils::WstringToAnsi(ws, CP_ACP);
spdlog::info("wechat log:{}", out);
}
return p;
}
void HandleSNSMsg(INT64 param1, INT64 param2, INT64 param3) {
nlohmann::json j_sns;
INT64 begin_addr = *(INT64 *)(param2 + 0x30);
INT64 end_addr = *(INT64 *)(param2 + 0x38);
if (begin_addr == 0) {
j_sns = {{"data", nlohmann::json::array()}};
} else {
while (begin_addr < end_addr) {
nlohmann::json j_item;
j_item["snsId"] = *(UINT64 *)(begin_addr);
j_item["createTime"] = *(DWORD *)(begin_addr + 0x38);
j_item["senderId"] = Utils::ReadWstringThenConvert(begin_addr + 0x18);
j_item["content"] = Utils::ReadWstringThenConvert(begin_addr + 0x48);
j_item["xml"] = Utils::ReadWstringThenConvert(begin_addr + 0x580);
j_sns["data"].push_back(j_item);
begin_addr += 0x11E0;
}
}
std::string jstr = j_sns.dump() + '\n';
common::InnerMessageStruct *inner_msg = new common::InnerMessageStruct;
inner_msg->buffer = new char[jstr.size() + 1];
memcpy(inner_msg->buffer, jstr.c_str(), jstr.size() + 1);
inner_msg->length = jstr.size();
if (kEnableHttp) {
bool add = ThreadPool::GetInstance().AddWork(SendHttpMsgCallback, inner_msg);
SPDLOG_INFO("hook sns add http msg work:{}", add);
} else {
bool add = ThreadPool::GetInstance().AddWork(SendMsgCallback, inner_msg);
SPDLOG_INFO("hook sns add msg work:{}", add);
}
R_OnSnsTimeLineSceneFinish(param1, param2, param3);
}
int HookSyncMsg(std::string client_ip, int port, std::string url,
uint64_t timeout, bool enable) {
if (kMsgHookFlag) {
@@ -162,15 +228,23 @@ int HookSyncMsg(std::string client_ip, int port, std::string url,
return -1;
}
DetourRestoreAfterWith();
// DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kDoAddMsg;
DetourAttach(&(PVOID&)R_DoAddMsg, &HandleSyncMsg);
LONG ret = DetourTransactionCommit();
if(ret == NO_ERROR){
kMsgHookFlag = true;
}
SPDLOG_INFO("hook sync {}",ret);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)R_OnSnsTimeLineSceneFinish, &HandleSNSMsg);
ret = DetourTransactionCommit();
if(ret == NO_ERROR){
kSnsFinishHookFlag = true;
}
SPDLOG_INFO("hook sns {}",ret);
return ret;
}
@@ -185,7 +259,6 @@ int UnHookSyncMsg() {
UINT64 base = Utils::GetWeChatWinBase();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kDoAddMsg;
DetourDetach(&(PVOID&)R_DoAddMsg, &HandleSyncMsg);
LONG ret = DetourTransactionCommit();
if (ret == NO_ERROR) {
@@ -196,5 +269,47 @@ int UnHookSyncMsg() {
return ret;
}
int HookLog() {
if (kLogHookFlag) {
SPDLOG_INFO("log hook already called");
return 2;
}
UINT64 base = Utils::GetWeChatWinBase();
if (!base) {
SPDLOG_INFO("base addr is null");
return -1;
}
// DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kHookLog;
DetourAttach(&(PVOID &)R_Log, &HandlePrintLog);
LONG ret = DetourTransactionCommit();
if (ret == NO_ERROR) {
kMsgHookFlag = true;
}
return ret;
}
int UnHookLog() {
if (!kLogHookFlag) {
kLogHookFlag = false;
SPDLOG_INFO("hook log reset");
return NO_ERROR;
}
UINT64 base = Utils::GetWeChatWinBase();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
UINT64 do_add_msg_addr = base + offset::kHookLog;
DetourDetach(&(PVOID &)R_Log, &HandlePrintLog);
LONG ret = DetourTransactionCommit();
if (ret == NO_ERROR) {
kLogHookFlag = false;
}
return ret;
}
} // namespace hooks
} // namespace wxhelper
+4
View File
@@ -10,6 +10,10 @@ int HookSyncMsg(std::string client_ip, int port, std::string url, uint64_t timeo
int UnHookSyncMsg();
int HookLog();
int UnHookLog();
} // namespace hooks
} // namespace wxhelper
#endif
+163 -5
View File
@@ -6,10 +6,21 @@
#include "hooks.h"
#include "db.h"
#define STR2ULL(str) (wxhelper::Utils::IsDigit(str) ? stoull(str) : 0)
#define STR2LL(str) (wxhelper::Utils::IsDigit(str) ? stoll(str) : 0)
#define STR2I(str) (wxhelper::Utils::IsDigit(str) ? stoi(str) : 0)
namespace common = wxhelper::common;
int GetIntParam(nlohmann::json data, std::string key) {
int result;
try {
result = data[key].get<int>();
} catch (nlohmann::json::exception) {
result = STR2I(data[key].get<std::string>());
}
return result;
}
INT64 GetINT64Param(nlohmann::json data, std::string key) {
INT64 result;
@@ -21,6 +32,16 @@ INT64 GetINT64Param(nlohmann::json data, std::string key) {
return result;
}
INT64 GetUINT64Param(nlohmann::json data, std::string key) {
UINT64 result;
try {
result = data[key].get<UINT64>();
} catch (nlohmann::json::exception) {
result = STR2ULL(data[key].get<std::string>());
}
return result;
}
std::string GetStringParam(nlohmann::json data, std::string key) {
return data[key].get<std::string>();
}
@@ -164,8 +185,17 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/hookSyncMsg")) {
int port = GetIntParam(j_param, "port");
std::string ip = GetStringParam(j_param, "ip");
int enable = GetIntParam(j_param, "enableHttp");
std::string url = "";
int timeout = 0;
if (enable) {
url = GetStringParam(j_param, "url");
timeout = GetIntParam(j_param, "timeout");
}
INT64 success =
wxhelper::hooks::HookSyncMsg("127.0.0.1", 19099, "", 3000, false);
wxhelper::hooks::HookSyncMsg(ip, port, url, timeout, enable);
nlohmann::json ret_data = {
{"code", success}, {"data", {}}, {"msg", "success"}};
ret = ret_data.dump();
@@ -341,12 +371,140 @@ std::string HttpDispatch(struct mg_connection *c, struct mg_http_message *hm) {
}
ret = ret_data.dump();
return ret;
} else {
} else if (mg_http_match_uri(hm, "/api/topMsg")) {
INT64 msg_id = GetINT64Param(j_param, "msgId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->SetTopMsg(msg_id);
nlohmann::json ret_data = {
{"code", 200}, {"data", {}}, {"msg", "not support url"}};
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
}
} else if (mg_http_match_uri(hm, "/api/removeTopMsg")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
INT64 msg_id = GetINT64Param(j_param, "msgId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->RemoveTopMsg(room_id,msg_id);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/InviteMemberToChatRoom")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
std::vector<std::wstring> wxids = GetArrayParam(j_param, "memberIds");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->InviteMemberToChatRoom(
room_id, wxids);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/hookLog")) {
int success = wxhelper::hooks::HookLog();
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/unhookLog")) {
int success = wxhelper::hooks::UnHookLog();
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/createChatRoom")) {
std::vector<std::wstring> wxids = GetArrayParam(j_param, "memberIds");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->CreateChatRoom(wxids);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/quitChatRoom")) {
std::wstring room_id = GetWStringParam(j_param, "chatRoomId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->QuitChatRoom(room_id);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/forwardMsg")) {
INT64 msg_id = GetINT64Param(j_param, "msgId");
std::wstring wxid = GetWStringParam(j_param, "wxid");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->ForwardMsg(msg_id,wxid);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getSNSFirstPage")) {
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetSNSFirstPage();
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getSNSNextPage")) {
UINT64 snsid = GetUINT64Param(j_param, "snsId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->GetSNSNextPage(snsid);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/addFavFromMsg")) {
UINT64 msg_id = GetUINT64Param(j_param, "msgId");
INT64 success =
wxhelper::GlobalContext::GetInstance().mgr->AddFavFromMsg(msg_id);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/addFavFromImage")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
std::wstring image_path = GetWStringParam(j_param, "imagePath");
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->AddFavFromImage(
wxid, image_path);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/sendAtText")) {
std::wstring chat_room_id = GetWStringParam(j_param, "chatRoomId");
std::vector<std::wstring> wxids = GetArrayParam(j_param, "wxids");
std::wstring msg = GetWStringParam(j_param, "msg");
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->SendAtText(
chat_room_id, wxid_list, msg);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
ret = ret_data.dump();
return ret;
} else if (mg_http_match_uri(hm, "/api/getContactProfile")) {
std::wstring wxid = GetWStringParam(j_param, "wxid");
common::ContactProfileInner profile;
INT64 success = wxhelper::GlobalContext::GetInstance().mgr->GetContactByWxid(
wxid, profile);
nlohmann::json ret_data = {
{"code", success}, {"msg", "success"}, {"data", {}}};
if (success == 1) {
nlohmann::json contact_profile = {
{"account", profile.account}, {"headImage", profile.head_image},
{"nickname", profile.nickname}, {"v3", profile.v3},
{"wxid", profile.wxid},
};
ret_data["data"] = contact_profile;
}
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();
+283
View File
@@ -3,6 +3,7 @@
#include "export.h"
#include "wechat_function.h"
#include "db.h"
namespace offset = wxhelper::V3_9_5_81::offset;
namespace prototype = wxhelper::V3_9_5_81::prototype;
@@ -500,4 +501,286 @@ INT64 Manager::GetMemberFromChatRoom(const std::wstring &room_id,
free_chat_room(addr);
return success;
}
INT64 Manager::SetTopMsg(ULONG64 msg_id) {
INT64 success = -1;
UINT64 top_addr = base_addr_ + offset::kTopMsg;
func::__DoTopMsg top_msg = (func::__DoTopMsg)top_addr;
INT64 index = 0;
INT64 local_id = DB::GetInstance().GetLocalIdByMsgId(msg_id, index);
if (local_id <= 0 || index >> 32 == 0) {
success = -2;
return success;
}
LARGE_INTEGER l;
l.HighPart = index >> 32;
l.LowPart = (DWORD)local_id;
UINT64 ptr = reinterpret_cast<UINT64>(&l);
success = top_msg(ptr, 1);
return success;
}
INT64 Manager::RemoveTopMsg(const std::wstring &room_id, ULONG64 msg_id) {
INT64 success = -1;
UINT64 remove_addr = base_addr_ + offset::kRemoveTopMsg;
func::__RemoveTopMsg remove_top_msg = (func::__RemoveTopMsg)remove_addr;
prototype::WeChatString *chat_room_id = BuildWechatString(room_id);
const wchar_t *w_room = room_id.c_str();
success = remove_top_msg(reinterpret_cast<UINT64>(w_room), msg_id,
reinterpret_cast<UINT64>(chat_room_id));
return success;
}
INT64 Manager::InviteMemberToChatRoom(const std::wstring &room_id,
const std::vector<std::wstring> &wxids) {
INT64 success = -1;
UINT64 invite_addr = base_addr_ + offset::kInviteMember;
func::__InviteMemberToChatRoom invite =
(func::__InviteMemberToChatRoom)invite_addr;
const wchar_t *w_room = room_id.c_str();
prototype::WeChatString *chat_room_id = BuildWechatString(room_id);
std::vector<prototype::WeChatString> wxid_list;
common::VectorInner *list = (common::VectorInner *)&wxid_list;
INT64 head = (INT64)&list->start;
for (int i = 0; i < wxids.size(); i++) {
prototype::WeChatString id(wxids[i]);
wxid_list.push_back(id);
}
UINT64 temp[2] = {0};
success = invite(reinterpret_cast<UINT64>(w_room), head,
reinterpret_cast<UINT64>(chat_room_id),
reinterpret_cast<UINT64>(&temp));
return success;
}
INT64 Manager::CreateChatRoom(const std::vector<std::wstring>& wxids){
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 create_chat_room_addr = base_addr_ + offset::kCreateChatRoom;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__CreateChatRoom create_chat_room =
(func::__CreateChatRoom)create_chat_room_addr;
std::vector<prototype::WeChatString> wxid_list;
common::VectorInner *list = (common::VectorInner *)&wxid_list;
INT64 head = (INT64)&list->start;
for (int i = 0; i < wxids.size(); i++) {
prototype::WeChatString id(wxids[i]);
wxid_list.push_back(id);
}
INT64 end = list->end;
UINT64 mgr = get_chat_room_mgr();
success = create_chat_room(mgr, head, end);
return success;
}
INT64 Manager::QuitChatRoom(const std::wstring &room_id) {
INT64 success = -1;
UINT64 get_chat_room_mgr_addr = base_addr_ + offset::kChatRoomMgr;
UINT64 quit_chat_room_addr = base_addr_ + offset::kQuitChatRoom;
func::__GetChatRoomMgr get_chat_room_mgr =
(func::__GetChatRoomMgr)get_chat_room_mgr_addr;
func::__QuitChatRoom quit_chat_room =
(func::__QuitChatRoom)quit_chat_room_addr;
UINT64 mgr = get_chat_room_mgr();
prototype::WeChatString chat_room_id(room_id);
success = quit_chat_room(mgr, reinterpret_cast<UINT64>(&chat_room_id), 0);
return success;
}
INT64 Manager::ForwardMsg(UINT64 msg_id, const std::wstring &wxid) {
INT64 success = -1;
UINT64 forward_addr = base_addr_ + offset::kForwardMsg;
func::__ForwardMsg forward_msg = (func::__ForwardMsg)forward_addr;
INT64 index = 0;
INT64 local_id = DB::GetInstance().GetLocalIdByMsgId(msg_id, index);
if (local_id <= 0 || index >> 32 == 0) {
success = -2;
return success;
}
LARGE_INTEGER l;
l.HighPart = index >> 32;
l.LowPart = (DWORD)local_id;
prototype::WeChatString *recv = BuildWechatString(wxid);
success = forward_msg(reinterpret_cast<UINT64>(recv), l.QuadPart, 0x4, 0x0);
return success;
}
INT64 Manager::GetSNSFirstPage() {
INT64 success = -1;
UINT64 sns_data_mgr_addr = base_addr_ + offset::kSNSDataMgr;
UINT64 sns_first_page_addr = base_addr_ + offset::kSNSGetFirstPage;
func::__GetSNSDataMgr sns_data_mgr = (func::__GetSNSDataMgr)sns_data_mgr_addr;
func::__GetSNSFirstPage sns_first_page =
(func::__GetSNSFirstPage)sns_first_page_addr;
UINT64 mgr = sns_data_mgr();
INT64 buff[16] = {0};
success = sns_first_page(mgr, reinterpret_cast<UINT64>(&buff), 1);
return success;
}
INT64 Manager::GetSNSNextPage(UINT64 sns_id) {
INT64 success = -1;
UINT64 time_line_mgr_addr = base_addr_ + offset::kSNSTimeLineMgr;
UINT64 sns_next_page_addr = base_addr_ + offset::kSNSGetNextPageScene;
func::__GetSnsTimeLineMgr time_line_mgr =
(func::__GetSnsTimeLineMgr)time_line_mgr_addr;
func::__GetSNSNextPageScene sns_next_page =
(func::__GetSNSNextPageScene)sns_next_page_addr;
UINT64 mgr = time_line_mgr();
success = sns_next_page(mgr, sns_id);
return success;
}
INT64 Manager::AddFavFromMsg(UINT64 msg_id) {
INT64 success = -1;
UINT64 get_chat_mgr_addr = base_addr_ + offset::kGetChatMgr;
UINT64 get_by_local_id_addr = base_addr_ + offset::kGetMgrByPrefixLocalId;
UINT64 add_fav_addr = base_addr_ + offset::kAddFavFromMsg;
UINT64 get_favorite_mgr_addr = base_addr_ + offset::kGetFavoriteMgr;
UINT64 free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
func::__GetMgrByPrefixLocalId get_by_local_id = (func::__GetMgrByPrefixLocalId)get_by_local_id_addr;
UINT64 new_chat_msg_addr = base_addr_ + offset::kChatMsgInstanceCounter;
func::__AddFavFromMsg add_fav = (func::__AddFavFromMsg)add_fav_addr;
func::__GetChatMgr get_chat_mgr = (func::__GetChatMgr)get_chat_mgr_addr;
func::__GetFavoriteMgr get_favorite_mgr = (func::__GetFavoriteMgr)get_favorite_mgr_addr;
func::__FreeChatMsg free_chat_msg = (func::__FreeChatMsg)free_chat_msg_addr;
func::__NewChatMsg new_chat_msg = (func::__NewChatMsg)new_chat_msg_addr;
INT64 index = 0;
INT64 local_id = DB::GetInstance().GetLocalIdByMsgId(msg_id, index);
if (local_id <= 0 || index >> 32 == 0) {
success = -2;
return success;
}
char chat_msg[0x460]= {0};
LARGE_INTEGER l;
l.HighPart = index >> 32;
l.LowPart = (DWORD)local_id;
UINT64 p_chat_msg = new_chat_msg(reinterpret_cast<UINT64>(&chat_msg));
get_chat_mgr();
get_by_local_id(l.QuadPart,p_chat_msg);
UINT64 mgr = get_favorite_mgr();
success = add_fav(mgr,p_chat_msg);
free_chat_msg(p_chat_msg);
return success;
}
INT64 Manager::AddFavFromImage(const std::wstring &wxid,
const std::wstring &image_path) {
INT64 success = -1;
UINT64 get_favorite_mgr_addr = base_addr_ + offset::kGetFavoriteMgr;
UINT64 add_fav_from_image_addr = base_addr_ + offset::kAddFavFromImage;
prototype::WeChatString *send_id = BuildWechatString(wxid);
prototype::WeChatString *path = BuildWechatString(image_path);
func::__GetFavoriteMgr get_favorite_mgr =
(func::__GetFavoriteMgr)get_favorite_mgr_addr;
func::__AddFavFromImage add_fav_from_image =
(func::__AddFavFromImage)add_fav_from_image_addr;
UINT64 mgr = get_favorite_mgr();
success = add_fav_from_image(mgr, reinterpret_cast<UINT64>(path),
reinterpret_cast<UINT64>(send_id));
return success;
}
INT64 Manager::SendAtText(const std::wstring &room_id,
const std::vector<std::wstring> &wxids,
const std::wstring &msg) {
INT64 success = -1;
std::vector<prototype::WeChatString> wxid_list;
common::VectorInner *list = (common::VectorInner *)&wxid_list;
std::wstring at_msg = L"";
int number = 0;
for (unsigned int i = 0; i < wxids.size(); i++) {
std::wstring nickname;
std::wstring at_all = L"notify@all";
if (at_all.compare(wxids[i]) == 0 ) {
nickname = L"所有人";
} else {
nickname = GetContactOrChatRoomNickname(wxids[i]);
}
if (nickname.length() == 0) {
continue;
}
prototype::WeChatString id(wxids[i]);
wxid_list.push_back(id);
at_msg = at_msg + L"@" + nickname + L" ";
number++;
}
if (number < 1) {
return success;
}
at_msg += msg;
INT64 head = (INT64)&list->start;
prototype::WeChatString to_user(room_id);
prototype::WeChatString text_msg(at_msg);
UINT64 send_message_mgr_addr = base_addr_ + offset::kGetSendMessageMgr;
UINT64 send_text_msg_addr = base_addr_ + offset::kSendTextMsg;
UINT64 free_chat_msg_addr = base_addr_ + offset::kFreeChatMsg;
char chat_msg[0x460] = {0};
func::__GetSendMessageMgr mgr;
mgr = (func::__GetSendMessageMgr)send_message_mgr_addr;
func::__SendTextMsg send;
send = (func::__SendTextMsg)send_text_msg_addr;
func::__FreeChatMsg free;
free = (func::__FreeChatMsg)free_chat_msg_addr;
mgr();
success = send(reinterpret_cast<UINT64>(&chat_msg),
reinterpret_cast<UINT64>(&to_user),
reinterpret_cast<UINT64>(&text_msg), head, 1, 1, 0, 0);
free(reinterpret_cast<UINT64>(&chat_msg));
return success;
}
std::wstring Manager::GetContactOrChatRoomNickname(const std::wstring &wxid) {
prototype::WeChatString to_user(wxid);
UINT64 get_contact_mgr_addr = base_addr_ + offset::kGetContactMgr;
UINT64 new_contact_addr = base_addr_ + offset::kNewContact;
UINT64 get_contact_addr = base_addr_ + offset::kGetContact;
UINT64 free_contact_addr = base_addr_ + offset::kFreeContact;
func::__GetContactMgr get_contact_mgr =
(func::__GetContactMgr)get_contact_mgr_addr;
func::__GetContact get_contact = (func::__GetContact)get_contact_addr;
func::__NewContact new_contact = (func::__NewContact)new_contact_addr;
func::__FreeContact free_contact = (func::__FreeContact)free_contact_addr;
char buff[0x6A9] = {0};
UINT64 contact = new_contact(reinterpret_cast<UINT64>(&buff));
UINT64 mgr = get_contact_mgr();
INT64 success = get_contact(mgr, reinterpret_cast<UINT64>(&to_user), contact);
if (success == 1) {
std::wstring nickname = Utils::ReadWstring(contact + 0xA0);
free_contact(contact);
return nickname;
} else {
free_contact(contact);
return L"";
}
}
INT64 Manager::GetContactByWxid(const std::wstring &wxid,
common::ContactProfileInner &profile) {
INT64 success = -1;
prototype::WeChatString to_user(wxid);
UINT64 get_contact_mgr_addr = base_addr_ + offset::kGetContactMgr;
UINT64 new_contact_addr = base_addr_ + offset::kNewContact;
UINT64 get_contact_addr = base_addr_ + offset::kGetContact;
UINT64 free_contact_addr = base_addr_ + offset::kFreeContact;
func::__GetContactMgr get_contact_mgr =
(func::__GetContactMgr)get_contact_mgr_addr;
func::__GetContact get_contact = (func::__GetContact)get_contact_addr;
func::__NewContact new_contact = (func::__NewContact)new_contact_addr;
func::__FreeContact free_contact = (func::__FreeContact)free_contact_addr;
char buff[0x6A9] = {0};
UINT64 contact = new_contact(reinterpret_cast<UINT64>(&buff));
UINT64 mgr = get_contact_mgr();
success = get_contact(mgr, reinterpret_cast<UINT64>(&to_user), contact);
profile.wxid = Utils::ReadWstringThenConvert(contact + 0x10);
profile.account = Utils::ReadWstringThenConvert(contact + 0x30);
profile.v3 = Utils::ReadWstringThenConvert(contact + 0x50);
profile.nickname = Utils::ReadWstringThenConvert(contact + 0xA0);
profile.head_image = Utils::ReadWstringThenConvert(contact + 0x188);
free_contact(contact);
return success;
}
} // namespace wxhelper
+18
View File
@@ -25,6 +25,24 @@ class Manager {
const std::vector<std::wstring>& members);
INT64 GetMemberFromChatRoom(const std::wstring& room_id,
common::ChatRoomMemberInner& member);
INT64 SetTopMsg(ULONG64 msg_id);
INT64 RemoveTopMsg(const std::wstring& room_id,ULONG64 msg_id);
INT64 InviteMemberToChatRoom(const std::wstring& room_id,
const std::vector<std::wstring>& wxids);
INT64 CreateChatRoom(const std::vector<std::wstring>& wxids);
INT64 QuitChatRoom(const std::wstring& room_id);
INT64 ForwardMsg(UINT64 msg_id, const std::wstring& wxid);
INT64 GetSNSFirstPage();
INT64 GetSNSNextPage(UINT64 sns_id);
INT64 AddFavFromMsg(UINT64 msg_id);
INT64 AddFavFromImage(const std::wstring& wxid,
const std::wstring& image_path);
INT64 SendAtText(const std::wstring& room_id,
const std::vector<std::wstring>& wxids,
const std::wstring& msg);
std::wstring GetContactOrChatRoomNickname(const std::wstring& wxid);
INT64 GetContactByWxid(const std::wstring& wxid,
common::ContactProfileInner& profile);
private:
UINT64 base_addr_;
+56
View File
@@ -198,6 +198,16 @@ struct ChatRoomMemberInner {
member("") {}
};
struct ContactProfileInner {
std::string wxid;
std::string account;
std::string v3;
std::string nickname;
std::string head_image;
ContactProfileInner()
: wxid(""), account(""), v3(""), nickname(""), head_image("") {}
};
} // namespace common
namespace V3_9_5_81 {
namespace function {
@@ -233,6 +243,28 @@ typedef UINT64 (*__GetMemberFromChatRoom)(UINT64,UINT64,UINT64);
typedef UINT64 (*__NewChatRoom)(UINT64);
typedef UINT64 (*__FreeChatRoom)(UINT64);
typedef UINT64 (*__DoTopMsg)(UINT64,UINT64);
typedef UINT64 (*__RemoveTopMsg)(UINT64,UINT64,UINT64);
typedef UINT64 (*__InviteMemberToChatRoom)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__CreateChatRoom)(UINT64,UINT64,UINT64);
typedef UINT64 (*__QuitChatRoom)(UINT64,UINT64,UINT64);
typedef UINT64 (*__ForwardMsg)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__GetSNSFirstPage)(UINT64,UINT64,UINT64);
typedef UINT64 (*__GetSNSNextPageScene)(UINT64,UINT64);
typedef UINT64 (*__GetSNSDataMgr)();
typedef UINT64 (*__GetSnsTimeLineMgr)();
typedef UINT64 (*__GetMgrByPrefixLocalId)(UINT64,UINT64);
typedef UINT64 (*__AddFavFromMsg)(UINT64,UINT64);
typedef UINT64 (*__GetChatMgr)();
typedef UINT64 (*__GetFavoriteMgr)();
typedef UINT64 (*__AddFavFromImage)(UINT64,UINT64,UINT64);
typedef UINT64 (*__GetContact)(UINT64,UINT64,UINT64);
typedef UINT64 (*__NewContact)(UINT64);
typedef UINT64 (*__FreeContact)(UINT64);
} // namespace function
namespace prototype {
@@ -329,6 +361,30 @@ const UINT64 kDelMemberFromChatRoom = 0xe64290;
const UINT64 kGetMemberFromChatRoom = 0xe74de0;
const UINT64 kNewChatRoom = 0x11fde50;
const UINT64 kFreeChatRoom = 0x11fe030;
const UINT64 kTopMsg = 0xa5e4f0;
const UINT64 kRemoveTopMsg = 0xe787b0;
const UINT64 kInviteMember = 0xe63650;
const UINT64 kHookLog = 0x1304e60;
const UINT64 kCreateChatRoom = 0xe63340;
const UINT64 kQuitChatRoom = 0xe6e3b0;
const UINT64 kForwardMsg = 0xfcd0f0;
const UINT64 kOnSnsTimeLineSceneFinish = 0x1a73150;
const UINT64 kSNSGetFirstPage = 0x1a51dd0;
const UINT64 kSNSGetNextPageScene = 0x1a77240;
const UINT64 kSNSDataMgr = 0xeebda0;
const UINT64 kSNSTimeLineMgr = 0x19e83a0;
const UINT64 kGetMgrByPrefixLocalId = 0xe4add0;
const UINT64 kAddFavFromMsg = 0x1601520;
const UINT64 kGetChatMgr = 0x8f0400;
const UINT64 kGetFavoriteMgr = 0x8c69b0;
const UINT64 kAddFavFromImage = 0x160b920;
const UINT64 kGetContact = 0xEA5F90;
const UINT64 kNewContact = 0x1212e40;
const UINT64 kFreeContact = 0x12134e0;
} // namespace offset
} // namespace V3_9_5_81