Compare commits

..
Author SHA1 Message Date
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
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
20 changed files with 1535 additions and 167 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.获取登录微信信息
+521 -2
View File
@@ -164,7 +164,8 @@ data: 接口返回的数据
|返回字段|字段类型|说明 |
|---|---|---|
|code|int|返回状态,不为0成功, 0失败|
|result|string|成功提示|
|msg|string|成功提示|
|data|object|null|
###### 接口示例
@@ -214,7 +215,7 @@ enableHttp=0时,使用ip,port的tcp服务回传消息。
入参:
``` javascript
{
"port": "19099"
"port": "19099",
"ip":"127.0.0.1",
"url":"http://localhost:8080",
"timeout":"3000",
@@ -474,4 +475,522 @@ 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"
}
```
#### 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"
}
```
+280
View File
@@ -0,0 +1,280 @@
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)
if __name__ == '__main__':
checkLogin()
# userInfo()
-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的消息。
+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;
}
Submodule
+1
Submodule spdlog added at ad0e89cbfb
+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 {};
+70 -1
View File
@@ -16,12 +16,19 @@ 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 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);
VOID CALLBACK SendMsgCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
PTP_WORK Work) {
common::InnerMessageStruct *msg = (common::InnerMessageStruct *)context;
@@ -101,7 +108,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) {
@@ -140,6 +147,26 @@ 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;
}
int HookSyncMsg(std::string client_ip, int port, std::string url,
uint64_t timeout, bool enable) {
if (kMsgHookFlag) {
@@ -196,5 +223,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
+224 -66
View File
@@ -7,9 +7,18 @@
#include "db.h"
#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;
@@ -29,6 +38,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 +140,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 +166,53 @@ 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;
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(ip, port, url, timeout, 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 +226,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 +254,164 @@ 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 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", 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 {
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();
+245 -25
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;
@@ -10,6 +11,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 +266,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 +308,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 +357,220 @@ 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;
}
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;
}
} // namespace wxhelper
+18
View File
@@ -13,6 +13,24 @@ 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);
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);
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
+88 -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,25 @@ 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);
typedef UINT64 (*__DoTopMsg)(UINT64,UINT64);
typedef UINT64 (*__RemoveTopMsg)(UINT64,UINT64,UINT64);
typedef UINT64 (*__InviteMemberToChatRoom)(UINT64,UINT64,UINT64,UINT64);
typedef UINT64 (*__CreateChatRoom)(UINT64,UINT64,UINT64);
} // namespace function
namespace prototype {
@@ -254,20 +310,38 @@ 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;
const UINT64 kTopMsg = 0xa5e4f0;
const UINT64 kRemoveTopMsg = 0xe787b0;
const UINT64 kInviteMember = 0xe63650;
const UINT64 kHookLog = 0x1304e60;
const UINT64 kCreateChatRoom = 0xe63340;
} // 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.