Initial commit
This commit is contained in:
commit
16754c3279
7
.editorconfig
Normal file
7
.editorconfig
Normal file
@ -0,0 +1,7 @@
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
.*
|
||||
!.gitignore
|
||||
!.editorconfig
|
||||
|
||||
# VS2019 build files
|
||||
Debug/
|
||||
Release/
|
||||
x64/
|
||||
|
||||
# RPC generated files
|
||||
*_c.c
|
||||
*_s.c
|
||||
*_h.h
|
58
App/App.cpp
Normal file
58
App/App.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <iostream>
|
||||
#include <process.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "sdk.h"
|
||||
/*
|
||||
#pragma comment(lib, "SDK.lib")
|
||||
等效为在属性,链接,输入中添加该依赖
|
||||
*/
|
||||
|
||||
int onTextMsg(WxMessage_t msg)
|
||||
{
|
||||
try {
|
||||
wcout << msg.id << L" msgType: " << msg.type << L", msgSource: " << msg.source << L", isSelf: " << msg.self
|
||||
<< endl;
|
||||
wcout << msg.wxId << L"[" << msg.roomId << L"]" << L" >> " << msg.content << endl;
|
||||
wcout << L"msgSourceXml: " << msg.xml << endl;
|
||||
} catch (...) {
|
||||
wcout << "something wrong..." << endl;
|
||||
}
|
||||
wcout.flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
DWORD status = 0;
|
||||
wstring wxid = L"filehelper"; // 微信ID
|
||||
wstring at_wxid = L"";
|
||||
wstring content = L"这里填写消息内容";
|
||||
|
||||
//_setmode(_fileno(stdout), _O_WTEXT); // 没有这个wcout遇到一些字符会导致console卡死,用了会导致脱离控制台
|
||||
_wsetlocale(LC_ALL, L"chs"); // 这是个大坑,不设置中文直接不见了。。。
|
||||
|
||||
// 获取消息类型
|
||||
const MsgTypesMap_t WxMsgTypes = WxGetMsgTypes();
|
||||
for (auto it = WxMsgTypes.begin(); it != WxMsgTypes.end(); ++it) {
|
||||
wcout << it->first << L": " << it->second << endl;
|
||||
}
|
||||
|
||||
status = WxInitSDK();
|
||||
wcout << L"WxInitSDK: " << status << endl;
|
||||
if (status != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
wcout << L"Message: 接收通知中......" << endl;
|
||||
WxSetTextMsgCb(onTextMsg);
|
||||
|
||||
// 测试消息发送
|
||||
WxSendTextMsg(wxid, at_wxid, content);
|
||||
|
||||
while (1) {
|
||||
Sleep(10000); // 休眠,释放CPU
|
||||
}
|
||||
}
|
54
App/App.py
Normal file
54
App/App.py
Normal file
@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
import time
|
||||
import wcferry as sdk
|
||||
|
||||
|
||||
def main():
|
||||
print(dir(sdk)) # 查看SDK支持的方法和属性
|
||||
help(sdk.WxSetTextMsgCb) # 查看某方法的情况
|
||||
help(sdk.WxMessage) # 查看消息结构
|
||||
WxMsgTypes = sdk.WxGetMsgTypes() # 获取消息类型
|
||||
print(WxMsgTypes) # 查看消息类型
|
||||
|
||||
# 初始化SDK,如果成功,返回0;否则失败
|
||||
status = sdk.WxInitSDK()
|
||||
if status != 0:
|
||||
print("初始化失败")
|
||||
exit(-1)
|
||||
|
||||
print("初始化成功")
|
||||
|
||||
time.sleep(2)
|
||||
print("发送文本消息......")
|
||||
sdk.WxSendTextMsg("filehelper", "", "message from WeChatFerry...")
|
||||
|
||||
# 接收消息。先定义消息处理回调
|
||||
def OnTextMsg(msg: sdk.WxMessage):
|
||||
if msg.self == 1: # 忽略自己发的消息
|
||||
return 0
|
||||
|
||||
s = ""
|
||||
msgType = WxMsgTypes.get(msg.type, '未知消息类型')
|
||||
if msg.source == 0:
|
||||
s += f"收到来自好友[{msg.wxId}]的{msgType}消息:"
|
||||
else:
|
||||
s += f"收到来自群[{msg.roomId}]的[{msg.wxId}]的{msgType}消息:"
|
||||
|
||||
s += f"\r\n{msg.content}"
|
||||
if msg.type != 0x01:
|
||||
s += f"\r\n{msg.xml}"
|
||||
|
||||
print(f"\n{s}")
|
||||
|
||||
return 0
|
||||
|
||||
print("Message: 接收通知中......")
|
||||
sdk.WxSetTextMsgCb(OnTextMsg) # 设置回调,接收消息
|
||||
while True:
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
163
App/App.vcxproj
Normal file
163
App/App.vcxproj
Normal file
@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="app.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{44c1a579-22a7-4ba3-a618-45bd01600294}</ProjectGuid>
|
||||
<RootNamespace>App</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalOptions> /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Rpc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(OutDir)SDK.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)SDK;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(OutDir)SDK.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>md wx
|
||||
xcopy /y $(OutDir)Spy.dll $(OutDir)wx\
|
||||
xcopy /y $(OutDir)SDK.dll $(OutDir)wx\
|
||||
xcopy /y $(OutDir)wcferry.pyd $(OutDir)wx\
|
||||
xcopy /y $(OutDir)App.exe $(OutDir)wx\
|
||||
xcopy /y $(SolutionDir)App\App.py $(OutDir)wx\</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Message>Copy output</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
22
App/App.vcxproj.filters
Normal file
22
App/App.vcxproj.filters
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="app.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
4
App/App.vcxproj.user
Normal file
4
App/App.vcxproj.user
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
28
README.MD
Normal file
28
README.MD
Normal file
@ -0,0 +1,28 @@
|
||||
# WeChatFerry
|
||||
传送信息往返微信的摆渡车。
|
||||
|
||||
## 快速开始
|
||||
1. 使用 VS2019 编译。
|
||||
2. 打开 `CMD`,运行 `App.exe`
|
||||
|
||||
## 项目结构
|
||||
### Spy
|
||||
间谍模块,注入到微信中,通过 RPC 做消息转发工作。
|
||||
|
||||
### SDK
|
||||
RPC 的客户端,封装接口,供其他方调用。
|
||||
|
||||
### SDKpy
|
||||
用于生成 Python 接口。为编译该项目,需要做一些配置:
|
||||
1. 添加附加包含目录
|
||||
* Python 头:`C:\Program Files (x86)\Python37-32\Include`
|
||||
* Pybind11 头:`C:\Projs\.pyenv\pybind11\lib\site-packages\pybind11\include`
|
||||
*注*:
|
||||
1. pybind11 可以通过 Python 安装(本工程安装到虚拟环境里了):`pip install pybind11`
|
||||
2. 然后通过命令查找:`python -m pybind11 --includes`
|
||||
|
||||
2. 添加 Python 的库
|
||||
* `C:\Program Files (x86)\Python37-32\libs`
|
||||
|
||||
### App
|
||||
示例应用,介绍如何调用 SDK。
|
16
Rpc/rpc.idl
Normal file
16
Rpc/rpc.idl
Normal file
@ -0,0 +1,16 @@
|
||||
[
|
||||
uuid(ed838ecd-8a1e-4da7-bfda-9f2d12d07893),
|
||||
version(1.0),
|
||||
implicit_handle(handle_t hSpyBinding),
|
||||
]
|
||||
|
||||
interface ISpy
|
||||
{
|
||||
import "rpc_types.h";
|
||||
|
||||
int IsLogin();
|
||||
int SendTextMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *at_wxid, [ in, string ] const wchar_t *msg);
|
||||
|
||||
void EnableReceiveMsg();
|
||||
[callback] int ReceiveMsg([ in ] RpcMessage_t *msg);
|
||||
};
|
9
Rpc/rpc_memory.cpp
Normal file
9
Rpc/rpc_memory.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include <windows.h>
|
||||
|
||||
/******************************************************/
|
||||
/* MIDL allocate and free */
|
||||
/******************************************************/
|
||||
|
||||
void __RPC_FAR *__RPC_USER midl_user_allocate(size_t len) { return (malloc(len)); }
|
||||
|
||||
void __RPC_USER midl_user_free(void __RPC_FAR *ptr) { free(ptr); }
|
18
Rpc/rpc_types.h
Normal file
18
Rpc/rpc_types.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#define MSG_SIZE_MSG_ID 64
|
||||
#define MSG_SIZE_MSG_XML 4096
|
||||
#define MSG_SIZE_WXID 64
|
||||
#define MSG_SIZE_ROOMID 64
|
||||
#define MSG_SIZE_CONTENT 16385
|
||||
|
||||
typedef struct RpcMessage {
|
||||
int self; // 是否自己发的消息:0=否,1=是
|
||||
int type; // 消息类型
|
||||
int source; // 消息来源:0=好友消息,1=群消息
|
||||
wchar_t id[MSG_SIZE_MSG_ID]; // 消息ID
|
||||
wchar_t xml[MSG_SIZE_MSG_XML]; // 群其他消息
|
||||
wchar_t wxId[MSG_SIZE_WXID]; // 发送人微信ID
|
||||
wchar_t roomId[MSG_SIZE_ROOMID]; // 群ID
|
||||
wchar_t content[MSG_SIZE_CONTENT]; // 消息内容,MAC版最大:16384,即16KB
|
||||
} RpcMessage_t;
|
181
SDK/SDK.vcxproj
Normal file
181
SDK/SDK.vcxproj
Normal file
@ -0,0 +1,181 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{707f2dcd-1001-42a7-b20e-b85b1bbab228}</ProjectGuid>
|
||||
<RootNamespace>SDK</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;SDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalOptions> /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Rpc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>sdk.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;SDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Rpc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>sdk.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;SDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>sdk.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;SDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>sdk.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Rpc\rpc_h.h" />
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="injector.h" />
|
||||
<ClInclude Include="sdk.h" />
|
||||
<ClInclude Include="util.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\Rpc\rpc_c.c" />
|
||||
<ClCompile Include="..\Rpc\rpc_memory.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="injector.cpp" />
|
||||
<ClCompile Include="sdk.cpp" />
|
||||
<ClCompile Include="util.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="sdk.def" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
59
SDK/SDK.vcxproj.filters
Normal file
59
SDK/SDK.vcxproj.filters
Normal file
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Rpc\rpc_h.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="injector.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sdk.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Rpc\rpc_c.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Rpc\rpc_memory.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="injector.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="sdk.def">
|
||||
<Filter>源文件</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
4
SDK/SDK.vcxproj.user
Normal file
4
SDK/SDK.vcxproj.user
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
21
SDK/dllmain.cpp
Normal file
21
SDK/dllmain.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
// dllmain.cpp : 定义 DLL 应用程序的入口点。
|
||||
#include "framework.h"
|
||||
#include <rpc.h>
|
||||
|
||||
extern RPC_STATUS RpcConnectServer();
|
||||
extern RPC_STATUS RpcDisconnectServer();
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
switch (ul_reason_for_call) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH: {
|
||||
RpcDisconnectServer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
5
SDK/framework.h
Normal file
5
SDK/framework.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
|
||||
// Windows 头文件
|
||||
#include <windows.h>
|
653
SDK/injector.cpp
Normal file
653
SDK/injector.cpp
Normal file
@ -0,0 +1,653 @@
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "injector.h"
|
||||
#include <malloc.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef BOOL(WINAPI *IsWow64Process2_t)(HANDLE hProcess, USHORT *pProcessMachine, USHORT *pNativeMachine);
|
||||
|
||||
static DWORD page_size = 0;
|
||||
static size_t func_LoadLibraryW;
|
||||
static size_t func_FreeLibrary;
|
||||
static size_t func_GetLastError;
|
||||
static char errmsg[512];
|
||||
static injector_t *g_injector;
|
||||
|
||||
#ifdef _M_AMD64
|
||||
static const char x64_code_template[] =
|
||||
// ---------- call LoadLibraryW ----------
|
||||
/* 0000: */ "\x48\x83\xEC\x28" // sub rsp,28h
|
||||
/* 0004: */ "\xFF\x15\x3E\x00\x00\x00" // call LoadLibraryW
|
||||
// 0x0000003e = X64_ADDR_LoadLibraryW - (0x0004 + 6)
|
||||
/* 000A: */ "\x48\x85\xC0" // test rax,rax
|
||||
/* 000D: */ "\x74\x0B" // je L1
|
||||
/* 000F: */ "\x48\x89\x05\xEA\x0F\x00\x00" // mov [load_address], rax
|
||||
// 0x00000fea = 0x1000 - (0x000F + 7)
|
||||
/* 0016: */ "\x33\xC0" // xor eax,eax
|
||||
/* 0018: */ "\xEB\x06" // jmp L2
|
||||
/* 001A: L1: */ "\xFF\x15\x38\x00\x00\x00" // call GetLastError
|
||||
// 0x00000038 = X64_ADDR_GetLastError - (0x001A + 6)
|
||||
/* 0020: L2: */ "\x48\x83\xC4\x28" // add rsp,28h
|
||||
/* 0024: */ "\xC3" // ret
|
||||
|
||||
// ---------- call FreeLibrary ----------
|
||||
#define X64_UNINJECTION_CODE_OFFSET 0x25
|
||||
/* 0025: */ "\x48\x83\xEC\x28" // sub rsp,28h
|
||||
/* 0029: */ "\xFF\x15\x21\x00\x00\x00" // call FreeLibrary
|
||||
// 0x00000021 = X64_ADDR_FreeLibrary - (0x0029 + 6)
|
||||
/* 002F: */ "\x85\xC0" // test eax,eax
|
||||
/* 0031: */ "\x74\x04" // je L1
|
||||
/* 0033: */ "\x33\xC0" // xor eax,eax
|
||||
/* 0035: */ "\xEB\x06" // jmp L2
|
||||
/* 0037: L1: */ "\xFF\x15\x1B\x00\x00\x00" // call GetLastError
|
||||
// 0x0000001B = X64_ADDR_GetLastError - (0x0037 + 6)
|
||||
/* 003D: L2: */ "\x48\x83\xC4\x28" // add rsp,28h
|
||||
/* 0041: */ "\xC3" // ret
|
||||
|
||||
// padding
|
||||
/* 0042: */ "\x90\x90\x90\x90\x90\x90"
|
||||
|
||||
// ---------- literal pool ----------
|
||||
#define X64_ADDR_LoadLibraryW 0x0048
|
||||
/* 0048: */ "\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
#define X64_ADDR_FreeLibrary 0x0050
|
||||
/* 0050: */ "\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
#define X64_ADDR_GetLastError 0x0058
|
||||
/* 0058: */ "\x90\x90\x90\x90\x90\x90\x90\x90";
|
||||
|
||||
#define X64_CODE_SIZE 0x0060
|
||||
#endif
|
||||
|
||||
#if defined(_M_AMD64) || defined(_M_IX86)
|
||||
static const char x86_code_template[] =
|
||||
// ---------- call LoadLibraryW ----------
|
||||
/* 0000: */ "\xFF\x74\x24\x04" // push dword ptr [esp+4]
|
||||
#define X86_CALL_LoadLibraryW 0x0004
|
||||
/* 0004: */ "\xE8\x00\x00\x00\x00" // call LoadLibraryW@4
|
||||
/* 0009: */ "\x85\xC0" // test eax,eax
|
||||
/* 000B: */ "\x74\x09" // je L1
|
||||
#define X86_MOV_EAX 0x000D
|
||||
/* 000D: */ "\xA3\x00\x00\x00\x00" // mov dword ptr [load_address], eax
|
||||
/* 0012: */ "\x33\xC0" // xor eax,eax
|
||||
/* 0014: */ "\xEB\x05" // jmp L2
|
||||
#define X86_CALL_GetLastError1 0x0016
|
||||
/* 0016: L1: */ "\xE8\x00\x00\x00\x00" // call GetLastError@0
|
||||
/* 001B: L2: */ "\xC2\x04\x00" // ret 4
|
||||
|
||||
// ---------- call FreeLibrary ----------
|
||||
#define X86_UNINJECTION_CODE_OFFSET 0x001E
|
||||
/* 001E: */ "\xFF\x74\x24\x04" // push dword ptr [esp+4]
|
||||
#define X86_CALL_FreeLibrary 0x0022
|
||||
/* 0022: */ "\xE8\x00\x00\x00\x00" // call FreeLibrary@4
|
||||
/* 0027: */ "\x85\xC0" // test eax,eax
|
||||
/* 0029: */ "\x74\x04" // je L1
|
||||
/* 002B: */ "\x33\xC0" // xor eax,eax
|
||||
/* 002D: */ "\xEB\x05" // jmp L2
|
||||
#define X86_CALL_GetLastError2 0x002F
|
||||
/* 002F: L1: */ "\xE8\x00\x00\x00\x00" // call GetLastError@0
|
||||
/* 0034: L2: */ "\xC2\x04\x00" // ret 4
|
||||
;
|
||||
|
||||
#define X86_CODE_SIZE 0x0037
|
||||
#endif
|
||||
|
||||
#ifdef _M_AMD64
|
||||
#define CURRENT_ARCH "x64"
|
||||
#define CODE_SIZE X64_CODE_SIZE
|
||||
#endif
|
||||
|
||||
#ifdef _M_IX86
|
||||
#define CURRENT_ARCH "x86"
|
||||
#define CODE_SIZE X86_CODE_SIZE
|
||||
#endif
|
||||
|
||||
static void set_errmsg(const char *format, ...);
|
||||
static const char *w32strerr(DWORD err);
|
||||
static USHORT process_arch(HANDLE hProcess);
|
||||
static const char *arch_name(USHORT arch);
|
||||
|
||||
struct injector {
|
||||
HANDLE hProcess;
|
||||
char *remote_mem;
|
||||
char *injection_code;
|
||||
char *uninjection_code;
|
||||
};
|
||||
|
||||
static BOOL init(void)
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
HANDLE hToken;
|
||||
LUID luid;
|
||||
TOKEN_PRIVILEGES tp;
|
||||
HMODULE kernel32 = GetModuleHandleA("kernel32");
|
||||
if (kernel32 == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
GetSystemInfo(&si);
|
||||
page_size = si.dwPageSize;
|
||||
func_LoadLibraryW = (size_t)GetProcAddress(kernel32, "LoadLibraryW");
|
||||
func_FreeLibrary = (size_t)GetProcAddress(kernel32, "FreeLibrary");
|
||||
func_GetLastError = (size_t)GetProcAddress(kernel32, "GetLastError");
|
||||
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!LookupPrivilegeValue(0, SE_DEBUG_NAME, &luid)) {
|
||||
CloseHandle(hToken);
|
||||
return FALSE;
|
||||
}
|
||||
tp.PrivilegeCount = 1;
|
||||
tp.Privileges[0].Luid = luid;
|
||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL)) {
|
||||
CloseHandle(hToken);
|
||||
return FALSE;
|
||||
}
|
||||
CloseHandle(hToken);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if defined(_M_AMD64)
|
||||
static int cmp_func(const void *context, const void *key, const void *datum)
|
||||
{
|
||||
ptrdiff_t rva_to_va = (ptrdiff_t)context;
|
||||
const char *k = (const char *)key;
|
||||
const char *d = (const char *)(rva_to_va + *(const DWORD *)datum);
|
||||
return strcmp(k, d);
|
||||
}
|
||||
|
||||
static int funcaddr(DWORD pid, size_t *load_library, size_t *free_library, size_t *get_last_error)
|
||||
{
|
||||
HANDLE hSnapshot;
|
||||
MODULEENTRY32W me;
|
||||
BOOL ok;
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
HANDLE hFileMapping = NULL;
|
||||
void *base = NULL;
|
||||
IMAGE_NT_HEADERS *nt_hdrs;
|
||||
ULONG exp_size;
|
||||
const IMAGE_EXPORT_DIRECTORY *exp;
|
||||
const DWORD *names, *name, *funcs;
|
||||
const WORD *ordinals;
|
||||
ptrdiff_t rva_to_va;
|
||||
int rv = INJERR_OTHER;
|
||||
|
||||
/* Get the full path of kernel32.dll. */
|
||||
retry:
|
||||
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
|
||||
if (hSnapshot == INVALID_HANDLE_VALUE) {
|
||||
DWORD err = GetLastError();
|
||||
switch (err) {
|
||||
case ERROR_BAD_LENGTH:
|
||||
goto retry;
|
||||
case ERROR_ACCESS_DENIED:
|
||||
rv = INJERR_PERMISSION;
|
||||
break;
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
rv = INJERR_NO_PROCESS;
|
||||
break;
|
||||
default:
|
||||
rv = INJERR_OTHER;
|
||||
}
|
||||
set_errmsg("CreateToolhelp32Snapshot error: %s", w32strerr(err));
|
||||
return rv;
|
||||
}
|
||||
me.dwSize = sizeof(me);
|
||||
for (ok = Module32FirstW(hSnapshot, &me); ok; ok = Module32NextW(hSnapshot, &me)) {
|
||||
if (wcsicmp(me.szModule, L"kernel32.dll") == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseHandle(hSnapshot);
|
||||
if (!ok) {
|
||||
set_errmsg("kernel32.dll could not be found.");
|
||||
return INJERR_OTHER;
|
||||
}
|
||||
|
||||
/* Get the export directory in the kernel32.dll. */
|
||||
hFile = CreateFileW(me.szExePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
set_errmsg("failed to open file %s: %s", me.szExePath, w32strerr(GetLastError()));
|
||||
goto exit;
|
||||
}
|
||||
hFileMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (hFileMapping == NULL) {
|
||||
set_errmsg("failed to create file mapping of %s: %s", me.szExePath, w32strerr(GetLastError()));
|
||||
goto exit;
|
||||
}
|
||||
base = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
|
||||
if (base == NULL) {
|
||||
set_errmsg("failed to map file %s to memory: %s", me.szExePath, w32strerr(GetLastError()));
|
||||
goto exit;
|
||||
}
|
||||
nt_hdrs = ImageNtHeader(base);
|
||||
if (nt_hdrs == NULL) {
|
||||
set_errmsg("ImageNtHeader error: %s", w32strerr(GetLastError()));
|
||||
goto exit;
|
||||
}
|
||||
exp = (const IMAGE_EXPORT_DIRECTORY *)ImageDirectoryEntryToDataEx(base, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT,
|
||||
&exp_size, NULL);
|
||||
if (exp == NULL) {
|
||||
set_errmsg("ImageDirectoryEntryToDataEx error: %s", w32strerr(GetLastError()));
|
||||
goto exit;
|
||||
}
|
||||
if (exp->NumberOfNames == 0) {
|
||||
set_errmsg("No export entires are not found.");
|
||||
goto exit;
|
||||
}
|
||||
names = (const DWORD *)ImageRvaToVa(nt_hdrs, base, exp->AddressOfNames, NULL);
|
||||
if (names == NULL) {
|
||||
set_errmsg("ImageRvaToVa error: %s", w32strerr(GetLastError()));
|
||||
goto exit;
|
||||
}
|
||||
ordinals = (const WORD *)ImageRvaToVa(nt_hdrs, base, exp->AddressOfNameOrdinals, NULL);
|
||||
if (ordinals == NULL) {
|
||||
set_errmsg("ImageRvaToVa error: %s", w32strerr(GetLastError()));
|
||||
goto exit;
|
||||
}
|
||||
funcs = (const DWORD *)ImageRvaToVa(nt_hdrs, base, exp->AddressOfFunctions, NULL);
|
||||
if (funcs == NULL) {
|
||||
set_errmsg("ImageRvaToVa error: %s", w32strerr(GetLastError()));
|
||||
goto exit;
|
||||
}
|
||||
rva_to_va = (size_t)ImageRvaToVa(nt_hdrs, base, names[0], NULL) - (size_t)names[0];
|
||||
|
||||
/* Find the address of LoadLibraryW */
|
||||
name = bsearch_s((void *)"LoadLibraryW", names, exp->NumberOfNames, sizeof(DWORD), cmp_func, (void *)rva_to_va);
|
||||
if (name == NULL) {
|
||||
set_errmsg("Could not find the address of LoadLibraryW");
|
||||
goto exit;
|
||||
}
|
||||
*load_library = (size_t)me.modBaseAddr + funcs[ordinals[name - names]];
|
||||
|
||||
/* Find the address of FreeLibrary */
|
||||
name = bsearch_s((void *)"FreeLibrary", names, exp->NumberOfNames, sizeof(DWORD), cmp_func, (void *)rva_to_va);
|
||||
if (name == NULL) {
|
||||
set_errmsg("Could not find the address of FreeLibrary");
|
||||
goto exit;
|
||||
}
|
||||
*free_library = (size_t)me.modBaseAddr + funcs[ordinals[name - names]];
|
||||
|
||||
/* Find the address of GetLastError */
|
||||
name = bsearch_s((void *)"GetLastError", names, exp->NumberOfNames, sizeof(DWORD), cmp_func, (void *)rva_to_va);
|
||||
if (name == NULL) {
|
||||
set_errmsg("Could not find the address of GetLastError");
|
||||
goto exit;
|
||||
}
|
||||
*get_last_error = (size_t)me.modBaseAddr + funcs[ordinals[name - names]];
|
||||
rv = 0;
|
||||
exit:
|
||||
if (base != NULL) {
|
||||
UnmapViewOfFile(base);
|
||||
}
|
||||
if (hFileMapping != NULL) {
|
||||
CloseHandle(hFileMapping);
|
||||
}
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
int cki_attach(injector_t **injector_out, DWORD pid)
|
||||
{
|
||||
injector_t *injector;
|
||||
DWORD dwDesiredAccess = PROCESS_QUERY_LIMITED_INFORMATION | /* for IsWow64Process() */
|
||||
PROCESS_CREATE_THREAD | /* for CreateRemoteThread() */
|
||||
PROCESS_VM_OPERATION | /* for VirtualAllocEx() */
|
||||
PROCESS_VM_READ | /* for ReadProcessMemory() */
|
||||
PROCESS_VM_WRITE; /* for WriteProcessMemory() */
|
||||
USHORT arch;
|
||||
DWORD old_protect;
|
||||
SIZE_T written;
|
||||
int rv;
|
||||
char code[CODE_SIZE];
|
||||
size_t code_size;
|
||||
size_t load_library, free_library, get_last_error;
|
||||
|
||||
if (page_size == 0) {
|
||||
init();
|
||||
}
|
||||
|
||||
load_library = func_LoadLibraryW;
|
||||
free_library = func_FreeLibrary;
|
||||
get_last_error = func_GetLastError;
|
||||
|
||||
injector = (injector_t *)calloc(1, sizeof(injector_t));
|
||||
if (injector == NULL) {
|
||||
set_errmsg("malloc error: %s", strerror(errno));
|
||||
return INJERR_NO_MEMORY;
|
||||
}
|
||||
injector->hProcess = OpenProcess(dwDesiredAccess, FALSE, pid);
|
||||
if (injector->hProcess == NULL) {
|
||||
DWORD err = GetLastError();
|
||||
set_errmsg("OpenProcess error: %s", w32strerr(err));
|
||||
switch (err) {
|
||||
case ERROR_ACCESS_DENIED:
|
||||
rv = INJERR_PERMISSION;
|
||||
break;
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
rv = INJERR_NO_PROCESS;
|
||||
break;
|
||||
default:
|
||||
rv = INJERR_OTHER;
|
||||
}
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
arch = process_arch(injector->hProcess);
|
||||
switch (arch) {
|
||||
#ifdef _M_AMD64
|
||||
case IMAGE_FILE_MACHINE_AMD64:
|
||||
break;
|
||||
case IMAGE_FILE_MACHINE_I386:
|
||||
rv = funcaddr(pid, &load_library, &free_library, &get_last_error);
|
||||
if (rv != 0) {
|
||||
goto error_exit;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef _M_IX86
|
||||
case IMAGE_FILE_MACHINE_I386:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
set_errmsg("%s target process isn't supported by %s process.", arch_name(arch), CURRENT_ARCH);
|
||||
rv = INJERR_UNSUPPORTED_TARGET;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
injector->remote_mem
|
||||
= (char *)VirtualAllocEx(injector->hProcess, NULL, 2 * page_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
if (injector->remote_mem == NULL) {
|
||||
set_errmsg("VirtualAllocEx error: %s", w32strerr(GetLastError()));
|
||||
rv = INJERR_OTHER;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
injector->injection_code = injector->remote_mem;
|
||||
switch (arch) {
|
||||
#ifdef _M_AMD64
|
||||
case IMAGE_FILE_MACHINE_AMD64: /* x64 */
|
||||
memcpy(code, x64_code_template, X64_CODE_SIZE);
|
||||
code_size = X64_CODE_SIZE;
|
||||
*(size_t *)(code + X64_ADDR_LoadLibraryW) = load_library;
|
||||
*(size_t *)(code + X64_ADDR_FreeLibrary) = free_library;
|
||||
*(size_t *)(code + X64_ADDR_GetLastError) = get_last_error;
|
||||
injector->uninjection_code = injector->remote_mem + X64_UNINJECTION_CODE_OFFSET;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(_M_AMD64) || defined(_M_IX86)
|
||||
case IMAGE_FILE_MACHINE_I386: /* x86 */
|
||||
memcpy(code, x86_code_template, X86_CODE_SIZE);
|
||||
code_size = X86_CODE_SIZE;
|
||||
#define FIX_CALL_RELATIVE(addr, offset) \
|
||||
*(uint32_t *)(code + offset + 1) = addr - ((uint32_t)(size_t)injector->remote_mem + offset + 5)
|
||||
FIX_CALL_RELATIVE(load_library, X86_CALL_LoadLibraryW);
|
||||
FIX_CALL_RELATIVE(free_library, X86_CALL_FreeLibrary);
|
||||
FIX_CALL_RELATIVE(get_last_error, X86_CALL_GetLastError1);
|
||||
FIX_CALL_RELATIVE(get_last_error, X86_CALL_GetLastError2);
|
||||
*(uint32_t *)(code + X86_MOV_EAX + 1) = (uint32_t)(size_t)injector->remote_mem + page_size;
|
||||
injector->uninjection_code = injector->remote_mem + X86_UNINJECTION_CODE_OFFSET;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
set_errmsg("Never reach here: arch=0x%x", arch);
|
||||
rv = INJERR_OTHER;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (!WriteProcessMemory(injector->hProcess, injector->remote_mem, code, code_size, &written)) {
|
||||
set_errmsg("WriteProcessMemory error: %s", w32strerr(GetLastError()));
|
||||
rv = INJERR_OTHER;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (!VirtualProtectEx(injector->hProcess, injector->remote_mem, page_size, PAGE_EXECUTE_READ, &old_protect)) {
|
||||
set_errmsg("VirtualProtectEx error: %s", w32strerr(GetLastError()));
|
||||
rv = INJERR_OTHER;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
*injector_out = injector;
|
||||
return 0;
|
||||
|
||||
error_exit:
|
||||
cki_detach(injector);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int cki_inject(injector_t *injector, const char *path, void **handle)
|
||||
{
|
||||
DWORD pathlen = (DWORD)strlen(path);
|
||||
wchar_t *wpath;
|
||||
DWORD wpathlen;
|
||||
|
||||
if (pathlen == 0) {
|
||||
set_errmsg("The specified path is empty.");
|
||||
return INJERR_FILE_NOT_FOUND;
|
||||
}
|
||||
if (pathlen > MAX_PATH) {
|
||||
set_errmsg("too long file path: %s", path);
|
||||
return INJERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
wpath = (wchar_t *)_alloca((pathlen + 1) * sizeof(wchar_t));
|
||||
wpathlen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, path, pathlen, wpath, pathlen + 1);
|
||||
wpath[wpathlen] = L'\0';
|
||||
return cki_inject_w(injector, wpath, handle);
|
||||
}
|
||||
|
||||
int cki_inject_w(injector_t *injector, const wchar_t *path, void **handle)
|
||||
{
|
||||
struct {
|
||||
void *load_address;
|
||||
wchar_t fullpath[MAX_PATH];
|
||||
} data = {
|
||||
NULL,
|
||||
};
|
||||
DWORD pathlen;
|
||||
SIZE_T written;
|
||||
HANDLE hThread;
|
||||
DWORD err;
|
||||
|
||||
pathlen = GetFullPathNameW(path, MAX_PATH, data.fullpath, NULL);
|
||||
if (pathlen > MAX_PATH) {
|
||||
set_errmsg("too long file path: %S", path);
|
||||
return INJERR_FILE_NOT_FOUND;
|
||||
}
|
||||
if (pathlen == 0) {
|
||||
set_errmsg("failed to get the full path: %S", path);
|
||||
return INJERR_FILE_NOT_FOUND;
|
||||
}
|
||||
if (!WriteProcessMemory(injector->hProcess, injector->remote_mem + page_size, &data, sizeof(data), &written)) {
|
||||
set_errmsg("WriteProcessMemory error: %s", w32strerr(GetLastError()));
|
||||
return INJERR_OTHER;
|
||||
}
|
||||
hThread = CreateRemoteThread(injector->hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)injector->injection_code,
|
||||
injector->remote_mem + page_size + sizeof(void *), 0, NULL);
|
||||
if (hThread == NULL) {
|
||||
set_errmsg("CreateRemoteThread error: %s", w32strerr(GetLastError()));
|
||||
return INJERR_OTHER;
|
||||
}
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
GetExitCodeThread(hThread, &err);
|
||||
CloseHandle(hThread);
|
||||
if (err != 0) {
|
||||
set_errmsg("LoadLibrary in the target process failed: %s", w32strerr(err));
|
||||
return INJERR_ERROR_IN_TARGET;
|
||||
}
|
||||
if (!ReadProcessMemory(injector->hProcess, injector->remote_mem + page_size, &data, sizeof(void *), &written)) {
|
||||
set_errmsg("ReadProcessMemory error: %s", w32strerr(GetLastError()));
|
||||
return INJERR_OTHER;
|
||||
}
|
||||
if (handle != NULL) {
|
||||
*handle = data.load_address;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cki_uninject(injector_t *injector, void *handle)
|
||||
{
|
||||
HANDLE hThread;
|
||||
DWORD err;
|
||||
|
||||
hThread = CreateRemoteThread(injector->hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)injector->uninjection_code,
|
||||
handle, 0, NULL);
|
||||
if (hThread == NULL) {
|
||||
set_errmsg("CreateRemoteThread error: %s", w32strerr(GetLastError()));
|
||||
return INJERR_OTHER;
|
||||
}
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
GetExitCodeThread(hThread, &err);
|
||||
CloseHandle(hThread);
|
||||
if (err != 0) {
|
||||
set_errmsg("FreeLibrary in the target process failed: %s", w32strerr(err));
|
||||
return INJERR_ERROR_IN_TARGET;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cki_detach(injector_t *injector)
|
||||
{
|
||||
if (injector->remote_mem != NULL) {
|
||||
VirtualFreeEx(injector->hProcess, injector->remote_mem, 0, MEM_RELEASE);
|
||||
}
|
||||
if (injector->hProcess != NULL) {
|
||||
CloseHandle(injector->hProcess);
|
||||
}
|
||||
free(injector);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *cki_error(void) { return errmsg; }
|
||||
|
||||
static void set_errmsg(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int rv;
|
||||
|
||||
va_start(ap, format);
|
||||
rv = vsnprintf(errmsg, sizeof(errmsg), format, ap);
|
||||
va_end(ap);
|
||||
if (rv == -1 || rv >= sizeof(errmsg)) {
|
||||
errmsg[sizeof(errmsg) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static const char *w32strerr(DWORD err)
|
||||
{
|
||||
static char errmsg[512];
|
||||
DWORD len;
|
||||
|
||||
len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
|
||||
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), errmsg, sizeof(errmsg), NULL);
|
||||
if (len > 0) {
|
||||
while (len > 0) {
|
||||
char c = errmsg[len - 1];
|
||||
if (c == ' ' || c == '\n' || c == '\r') {
|
||||
len--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
errmsg[len] = '\0';
|
||||
} else if ((int)err >= 0) {
|
||||
sprintf(errmsg, "win32 error code %d", err);
|
||||
} else {
|
||||
sprintf(errmsg, "win32 error code 0x%x", err);
|
||||
}
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
static USHORT process_arch(HANDLE hProcess)
|
||||
{
|
||||
static IsWow64Process2_t IsWow64Process2_func = (IsWow64Process2_t)-1;
|
||||
if (IsWow64Process2_func == (IsWow64Process2_t)-1) {
|
||||
IsWow64Process2_func = (IsWow64Process2_t)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process2");
|
||||
}
|
||||
if (IsWow64Process2_func != NULL) {
|
||||
/* Windows 10 */
|
||||
USHORT process_machine;
|
||||
USHORT native_machine;
|
||||
if (IsWow64Process2_func(hProcess, &process_machine, &native_machine)) {
|
||||
if (process_machine != IMAGE_FILE_MACHINE_UNKNOWN) {
|
||||
return process_machine;
|
||||
} else {
|
||||
return native_machine;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Windows 8.1 or earlier */
|
||||
/* arch will be either x86 or x64. */
|
||||
#ifdef _M_AMD64
|
||||
BOOL is_wow64_proc;
|
||||
if (IsWow64Process(hProcess, &is_wow64_proc)) {
|
||||
if (is_wow64_proc) {
|
||||
return IMAGE_FILE_MACHINE_I386;
|
||||
} else {
|
||||
return IMAGE_FILE_MACHINE_AMD64;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef _M_IX86
|
||||
BOOL is_wow64_proc;
|
||||
if (IsWow64Process(GetCurrentProcess(), &is_wow64_proc)) {
|
||||
if (!is_wow64_proc) {
|
||||
/* Run on 32-bit Windows */
|
||||
return IMAGE_FILE_MACHINE_I386;
|
||||
}
|
||||
/* Run on Windows x64 */
|
||||
if (IsWow64Process(hProcess, &is_wow64_proc)) {
|
||||
if (is_wow64_proc) {
|
||||
return IMAGE_FILE_MACHINE_I386;
|
||||
} else {
|
||||
return IMAGE_FILE_MACHINE_AMD64;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
}
|
||||
|
||||
static const char *arch_name(USHORT arch)
|
||||
{
|
||||
switch (arch) {
|
||||
case IMAGE_FILE_MACHINE_AMD64:
|
||||
return "x64";
|
||||
case IMAGE_FILE_MACHINE_I386:
|
||||
return "x86";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
BOOL InjectDll(DWORD pid, const WCHAR *dllpath)
|
||||
{
|
||||
if (cki_attach(&g_injector, pid) != 0) {
|
||||
printf("%s\n", cki_error());
|
||||
return FALSE;
|
||||
}
|
||||
if (cki_inject_w(g_injector, dllpath, NULL) == 0) {
|
||||
return TRUE;
|
||||
} else {
|
||||
fprintf(stderr, " %s\n", cki_error());
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL EnjectDll(DWORD pid, const WCHAR *dllname)
|
||||
{
|
||||
if (cki_detach(g_injector) == 0) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
40
SDK/injector.h
Normal file
40
SDK/injector.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef __INJECTOR_H__
|
||||
#define __INJECTOR_H__
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define INJERR_SUCCESS 0
|
||||
#define INJERR_OTHER -1
|
||||
#define INJERR_NO_MEMORY -2
|
||||
#define INJERR_NO_PROCESS -3
|
||||
#define INJERR_NO_LIBRARY -4
|
||||
#define INJERR_NO_FUNCTION -4
|
||||
#define INJERR_ERROR_IN_TARGET -5
|
||||
#define INJERR_FILE_NOT_FOUND -6
|
||||
#define INJERR_INVALID_MEMORY_AREA -7
|
||||
#define INJERR_PERMISSION -8
|
||||
#define INJERR_UNSUPPORTED_TARGET -9
|
||||
#define INJERR_INVALID_ELF_FORMAT -10
|
||||
#define INJERR_WAIT_TRACEE -11
|
||||
|
||||
typedef struct injector injector_t;
|
||||
|
||||
int cki_attach(injector_t **injector, DWORD pid);
|
||||
int cki_inject(injector_t *injector, const char *path, void **handle);
|
||||
int cki_inject_w(injector_t *injector, const wchar_t *path, void **handle);
|
||||
int cki_uninject(injector_t *injector, void *handle);
|
||||
int cki_detach(injector_t *injector);
|
||||
const char *cki_error(void);
|
||||
|
||||
BOOL InjectDll(DWORD pid, const WCHAR *dllpath);
|
||||
BOOL EnjectDll(DWORD pid, const WCHAR *dllname);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}; /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
282
SDK/sdk.cpp
Normal file
282
SDK/sdk.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
#include "Shlwapi.h"
|
||||
#include "framework.h"
|
||||
#include <process.h>
|
||||
#include <queue>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <vector>
|
||||
|
||||
#include "../Rpc/rpc_h.h"
|
||||
#pragma comment(lib, "Rpcrt4.lib")
|
||||
|
||||
#include "injector.h"
|
||||
#include "rpc_types.h"
|
||||
#include "sdk.h"
|
||||
#include "util.h"
|
||||
|
||||
static HANDLE hEvent;
|
||||
static std::queue<RpcMessage_t> MsgQueue;
|
||||
static RPC_WSTR pszStringBinding = NULL;
|
||||
static std::function<int(WxMessage_t)> cbReceiveTextMsg;
|
||||
static const MsgTypesMap_t WxMsgTypes = MsgTypesMap_t { { 0x01, L"文字" },
|
||||
{ 0x03, L"图片" },
|
||||
{ 0x22, L"语音" },
|
||||
{ 0x25, L"好友确认" },
|
||||
{ 0x28, L"POSSIBLEFRIEND_MSG" },
|
||||
{ 0x2A, L"名片" },
|
||||
{ 0x2B, L"视频" },
|
||||
{ 0x2F, L"石头剪刀布 | 表情图片" },
|
||||
{ 0x30, L"位置" },
|
||||
{ 0x31, L"共享实时位置、文件、转账、链接" },
|
||||
{ 0x32, L"VOIPMSG" },
|
||||
{ 0x33, L"微信初始化" },
|
||||
{ 0x34, L"VOIPNOTIFY" },
|
||||
{ 0x35, L"VOIPINVITE" },
|
||||
{ 0x3E, L"小视频" },
|
||||
{ 0x270F, L"SYSNOTICE" },
|
||||
{ 0x2710, L"红包、系统消息" },
|
||||
{ 0x2712, L"撤回消息" } };
|
||||
|
||||
RPC_STATUS RpcConnectServer()
|
||||
{
|
||||
RPC_STATUS status = 0;
|
||||
// Creates a string binding handle.
|
||||
status = RpcStringBindingCompose(NULL, // UUID to bind to
|
||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
|
||||
NULL, // TCP/IP network address to use
|
||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use
|
||||
NULL, // Protocol dependent network options to use
|
||||
&pszStringBinding); // String binding output
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Validates the format of the string binding handle and converts it to a binding handle.
|
||||
pszStringBinding: The string binding to validate
|
||||
hSpyBinding: Put the result in the implicit binding(defined in the IDL file)
|
||||
*/
|
||||
status = RpcBindingFromStringBinding(pszStringBinding, &hSpyBinding);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
RPC_STATUS RpcDisconnectServer()
|
||||
{
|
||||
RPC_STATUS status;
|
||||
// Free the memory allocated by a string
|
||||
status = RpcStringFree(&pszStringBinding);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
// Releases binding handle resources and disconnects from the server
|
||||
status = RpcBindingFree(&hSpyBinding);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int WxInitSDK()
|
||||
{
|
||||
int loginFlag = 0;
|
||||
unsigned long ulCode = 0;
|
||||
DWORD status = 0;
|
||||
DWORD pid = 0;
|
||||
WCHAR DllPath[MAX_PATH] = { 0 };
|
||||
|
||||
GetModuleFileNameW(GetModuleHandleW(WECHATSDKDLL), DllPath, MAX_PATH);
|
||||
PathRemoveFileSpecW(DllPath);
|
||||
PathAppendW(DllPath, WECHATINJECTDLL);
|
||||
|
||||
if (!PathFileExistsW(DllPath)) {
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
status = OpenWeChat(&pid);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!InjectDll(pid, DllPath)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
RpcConnectServer();
|
||||
|
||||
while (!loginFlag) {
|
||||
RpcTryExcept
|
||||
{
|
||||
// 查询登录状态
|
||||
loginFlag = client_IsLogin();
|
||||
}
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept
|
||||
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static unsigned int __stdcall waitForMsg(void *p)
|
||||
{
|
||||
RpcMessage_t *rpcMsg;
|
||||
while (true) {
|
||||
// 中断式,兼顾及时性和CPU使用率
|
||||
WaitForSingleObject(hEvent, INFINITE); // 等待消息
|
||||
while (!MsgQueue.empty()) {
|
||||
rpcMsg = (RpcMessage_t *)&MsgQueue.front();
|
||||
WxMessage_t msg;
|
||||
msg.id = wstring(rpcMsg->id);
|
||||
msg.self = rpcMsg->self;
|
||||
msg.type = rpcMsg->type;
|
||||
msg.source = rpcMsg->source;
|
||||
msg.xml = wstring(rpcMsg->xml);
|
||||
msg.wxId = wstring(rpcMsg->wxId);
|
||||
msg.roomId = wstring(rpcMsg->roomId);
|
||||
msg.content = wstring(rpcMsg->content);
|
||||
|
||||
try {
|
||||
cbReceiveTextMsg(msg); // 调用接收消息回调
|
||||
} catch (...) {
|
||||
printf("callback error...\n");
|
||||
}
|
||||
MsgQueue.pop();
|
||||
}
|
||||
ResetEvent(hEvent);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int __stdcall innerWxSetTextMsgCb(void *p)
|
||||
{
|
||||
unsigned long ulCode = 0;
|
||||
RpcTryExcept
|
||||
{
|
||||
// 建立RPC通道,让服务端能够调用客户端的回调函数。(该接口会被服务端阻塞直到异常退出)
|
||||
client_EnableReceiveMsg();
|
||||
}
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WxSetTextMsgCb(const std::function<int(WxMessage_t)> &onMsg)
|
||||
{
|
||||
if (onMsg) {
|
||||
HANDLE msgThread;
|
||||
cbReceiveTextMsg = onMsg;
|
||||
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
msgThread = (HANDLE)_beginthreadex(NULL, 0, waitForMsg, NULL, 0, NULL);
|
||||
if (msgThread == NULL) {
|
||||
printf("Failed to create message listening thread.\n");
|
||||
return -2;
|
||||
}
|
||||
CloseHandle(msgThread);
|
||||
|
||||
msgThread = (HANDLE)_beginthreadex(NULL, 0, innerWxSetTextMsgCb, NULL, 0, NULL);
|
||||
if (msgThread == NULL) {
|
||||
printf("Failed to create innerWxRecvTextMsg.\n");
|
||||
return -2;
|
||||
}
|
||||
CloseHandle(msgThread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Empty Callback.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int server_ReceiveMsg(RpcMessage_t *rpcMsg)
|
||||
{
|
||||
MsgQueue.push(*rpcMsg); // 发送消息
|
||||
SetEvent(hEvent); // 发送消息通知
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int innerWxSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
|
||||
RpcTryExcept { ret = client_SendTextMsg(wxid, at_wxid, msg); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WxSendTextMsg(wstring wxid, wstring at_wxid, wstring msg)
|
||||
{
|
||||
return innerWxSendTextMsg(wxid.c_str(), at_wxid.c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
static int getAddrHandle(DWORD *addr, HANDLE *handle)
|
||||
{
|
||||
DWORD processID = 0;
|
||||
wstring processName = L"WeChat.exe";
|
||||
wstring moduleName = L"WeChatWin.dll";
|
||||
|
||||
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
|
||||
while (Process32Next(hSnapshot, &pe32)) {
|
||||
wstring strProcess = pe32.szExeFile;
|
||||
if (strProcess == processName) {
|
||||
processID = pe32.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseHandle(hSnapshot);
|
||||
if (processID == 0) {
|
||||
printf("Failed to get Process ID\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processID);
|
||||
if (hProcessSnapshot == INVALID_HANDLE_VALUE) {
|
||||
printf("Failed to get Process Snapshot\r\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
MODULEENTRY32 me32;
|
||||
SecureZeroMemory(&me32, sizeof(MODULEENTRY32));
|
||||
me32.dwSize = sizeof(MODULEENTRY32);
|
||||
while (Module32Next(hProcessSnapshot, &me32)) {
|
||||
me32.dwSize = sizeof(MODULEENTRY32);
|
||||
|
||||
if (!wcscmp(me32.szModule, moduleName.c_str())) {
|
||||
*addr = (DWORD)me32.modBaseAddr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hProcessSnapshot);
|
||||
if (*addr == 0) {
|
||||
printf("Failed to get Module Address\r\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
*handle = OpenProcess(PROCESS_VM_READ, FALSE, processID);
|
||||
if (*handle == 0) {
|
||||
printf("Failed to open Process\r\n");
|
||||
return -4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MsgTypesMap_t WxGetMsgTypes() { return WxMsgTypes; }
|
5
SDK/sdk.def
Normal file
5
SDK/sdk.def
Normal file
@ -0,0 +1,5 @@
|
||||
EXPORTS
|
||||
WxInitSDK
|
||||
WxSetTextMsgCb
|
||||
WxSendTextMsg
|
||||
WxGetMsgTypes
|
25
SDK/sdk.h
Normal file
25
SDK/sdk.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef struct WxMessage {
|
||||
int self; // 是否自己发的消息:0=否,1=是
|
||||
int type; // 消息类型
|
||||
int source; // 消息来源:0=好友消息,1=群消息
|
||||
wstring id; // 消息ID
|
||||
wstring xml; // 群其他消息
|
||||
wstring wxId; // 发送人微信ID
|
||||
wstring roomId; // 群ID
|
||||
wstring content; // 消息内容,MAC版最大:16384,即16KB
|
||||
} WxMessage_t;
|
||||
|
||||
typedef map<int, wstring> MsgTypesMap_t;
|
||||
|
||||
int WxInitSDK();
|
||||
int WxSetTextMsgCb(const std::function<int(WxMessage_t)> &onMsg);
|
||||
int WxSendTextMsg(wstring wxid, wstring at_wxid, wstring msg);
|
||||
MsgTypesMap_t WxGetMsgTypes();
|
191
SDK/util.cpp
Normal file
191
SDK/util.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
#include "Shlwapi.h"
|
||||
#include "framework.h"
|
||||
#include <string.h>
|
||||
#include <strsafe.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#pragma comment(lib, "shlwapi")
|
||||
#pragma comment(lib, "Version.lib")
|
||||
|
||||
using namespace std;
|
||||
|
||||
int GetWeChatPath(wchar_t *path);
|
||||
int GetWeChatWinDLLPath(wchar_t *path);
|
||||
int GetWeChatVersion(wchar_t *version);
|
||||
bool GetFileVersion(const wchar_t *filePath, wchar_t *version);
|
||||
|
||||
int GetWeChatPath(wchar_t *path)
|
||||
{
|
||||
int ret = -1;
|
||||
HKEY hKey = NULL;
|
||||
// HKEY_CURRENT_USER\Software\Tencent\WeChat InstallPath = xx
|
||||
if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, L"Software\\Tencent\\WeChat", &hKey)) {
|
||||
ret = GetLastError();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DWORD Type = REG_SZ;
|
||||
DWORD cbData = MAX_PATH * sizeof(WCHAR);
|
||||
if (ERROR_SUCCESS != RegQueryValueEx(hKey, L"InstallPath", 0, &Type, (LPBYTE)path, &cbData)) {
|
||||
ret = GetLastError();
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if (path != NULL) {
|
||||
PathAppend(path, WECHAREXE);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (hKey) {
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int GetWeChatWinDLLPath(wchar_t *path)
|
||||
{
|
||||
int ret = GetWeChatPath(path);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
PathRemoveFileSpecW(path);
|
||||
PathAppendW(path, WECHATWINDLL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int GetWeChatVersion(wchar_t *version)
|
||||
{
|
||||
WCHAR Path[MAX_PATH] = { 0 };
|
||||
|
||||
int ret = GetWeChatWinDLLPath(Path);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = GetFileVersion(Path, version);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GetFileVersion(const wchar_t *filePath, wchar_t *version)
|
||||
{
|
||||
if (wcslen(filePath) > 0 && PathFileExists(filePath)) {
|
||||
VS_FIXEDFILEINFO *pVerInfo = NULL;
|
||||
DWORD dwTemp, dwSize;
|
||||
BYTE *pData = NULL;
|
||||
UINT uLen;
|
||||
|
||||
dwSize = GetFileVersionInfoSize(filePath, &dwTemp);
|
||||
if (dwSize == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pData = new BYTE[dwSize + 1];
|
||||
if (pData == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetFileVersionInfo(filePath, 0, dwSize, pData)) {
|
||||
delete[] pData;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!VerQueryValue(pData, TEXT("\\"), (void **)&pVerInfo, &uLen)) {
|
||||
delete[] pData;
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD verMS = pVerInfo->dwFileVersionMS;
|
||||
DWORD verLS = pVerInfo->dwFileVersionLS;
|
||||
DWORD major = HIWORD(verMS);
|
||||
DWORD minor = LOWORD(verMS);
|
||||
DWORD build = HIWORD(verLS);
|
||||
DWORD revision = LOWORD(verLS);
|
||||
delete[] pData;
|
||||
|
||||
StringCbPrintf(version, 0x20, TEXT("%d.%d.%d.%d"), major, minor, build, revision);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int OpenWeChat(DWORD *pid)
|
||||
{
|
||||
int ret = -1;
|
||||
STARTUPINFO si = { sizeof(si) };
|
||||
PROCESS_INFORMATION pi = { 0 };
|
||||
|
||||
WCHAR Path[MAX_PATH] = { 0 };
|
||||
ret = GetWeChatPath(Path);
|
||||
if (ERROR_SUCCESS != ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!CreateProcess(NULL, Path, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
|
||||
ret = GetLastError();
|
||||
return ret;
|
||||
}
|
||||
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
|
||||
*pid = pi.dwProcessId;
|
||||
|
||||
ret = ERROR_SUCCESS;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
|
||||
{
|
||||
DWORD strLength = GET_DWORD(address + 4);
|
||||
if (strLength == 0) {
|
||||
return 0;
|
||||
} else if (strLength > buffer_size) {
|
||||
strLength = buffer_size - 1;
|
||||
}
|
||||
|
||||
wmemcpy_s(buffer, strLength + 1, GET_WSTRING(address), strLength + 1);
|
||||
|
||||
return strLength;
|
||||
}
|
||||
|
||||
DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address)
|
||||
{
|
||||
DWORD value = 0;
|
||||
|
||||
unsigned char data[4] = { 0 };
|
||||
if (ReadProcessMemory(hProcess, (LPVOID)address, data, 4, 0)) {
|
||||
value = data[0] & 0xFF;
|
||||
value |= ((data[1] << 8) & 0xFF00);
|
||||
value |= ((data[2] << 16) & 0xFF0000);
|
||||
value |= ((data[3] << 24) & 0xFF000000);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address)
|
||||
{
|
||||
wstring value = L"";
|
||||
|
||||
DWORD strAddress = GetMemoryIntByAddress(hProcess, address);
|
||||
DWORD strLen = GetMemoryIntByAddress(hProcess, address + 0x4);
|
||||
if (strLen > 500)
|
||||
return value;
|
||||
|
||||
wchar_t cValue[500] = { 0 };
|
||||
memset(cValue, 0, sizeof(cValue) / sizeof(wchar_t));
|
||||
if (ReadProcessMemory(hProcess, (LPVOID)strAddress, cValue, (strLen + 1) * 2, 0)) {
|
||||
value = wstring(cValue);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
21
SDK/util.h
Normal file
21
SDK/util.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#define WECHAREXE L"WeChat.exe"
|
||||
#define WECHATWINDLL L"WeChatWin.dll"
|
||||
#define WECHATSDKDLL L"SDK.dll"
|
||||
#define WECHATINJECTDLL L"Spy.dll"
|
||||
|
||||
#define GET_DWORD(addr) ((DWORD) * (DWORD *)(addr))
|
||||
#define GET_STRING(addr) ((CHAR *)(addr))
|
||||
#define GET_WSTRING(addr) ((WCHAR *)(*(DWORD *)(addr)))
|
||||
|
||||
int OpenWeChat(DWORD *pid);
|
||||
int GetWeChatPath(wchar_t *path);
|
||||
int GetWeChatWinDLLPath(wchar_t *path);
|
||||
int GetWeChatVersion(wchar_t *version);
|
||||
bool GetFileVersion(const wchar_t *filePath, wchar_t *version);
|
||||
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size);
|
||||
DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address);
|
||||
std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address);
|
168
SDKpy/SDKpy.vcxproj
Normal file
168
SDKpy/SDKpy.vcxproj
Normal file
@ -0,0 +1,168 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{121ad245-72fb-47a6-99d6-5427b74fa7b9}</ProjectGuid>
|
||||
<RootNamespace>SDKpy</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetName>wcferry</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;SDKPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;SDKPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)SDK;$(SolutionDir)Rpc;C:\Program Files (x86)\Python37-32\Include;C:\Projs\.pyenv\pybind11\lib\site-packages\pybind11\include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalLibraryDirectories>C:\Program Files (x86)\Python37-32\libs;</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>$(OutDir)SDK.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;SDKPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;SDKPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\SDK\sdk.h" />
|
||||
<ClInclude Include="framework.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="sdkpy.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
30
SDKpy/SDKpy.vcxproj.filters
Normal file
30
SDKpy/SDKpy.vcxproj.filters
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SDK\sdk.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="sdkpy.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
4
SDKpy/SDKpy.vcxproj.user
Normal file
4
SDKpy/SDKpy.vcxproj.user
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
5
SDKpy/framework.h
Normal file
5
SDKpy/framework.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
|
||||
// Windows 头文件
|
||||
#include <windows.h>
|
35
SDKpy/sdkpy.cpp
Normal file
35
SDKpy/sdkpy.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
#include "sdk.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
int WxSetTextMsgCbPy(const std::function<int(WxMessage_t)> &onMsg) { return WxSetTextMsgCb(onMsg); }
|
||||
|
||||
PYBIND11_MODULE(wcferry, m)
|
||||
{
|
||||
m.doc() = "SDK python API";
|
||||
|
||||
py::class_<WxMessage>(m, "WxMessage")
|
||||
.def_readonly("id", &WxMessage::id)
|
||||
.def_readonly("self", &WxMessage::self)
|
||||
.def_readonly("type", &WxMessage::type)
|
||||
.def_readonly("source", &WxMessage::source)
|
||||
.def_readonly("xml", &WxMessage::xml)
|
||||
.def_readonly("wxId", &WxMessage::wxId)
|
||||
.def_readonly("roomId", &WxMessage::roomId)
|
||||
.def_readonly("content", &WxMessage::content);
|
||||
|
||||
m.def("WxInitSDK", &WxInitSDK);
|
||||
m.def("WxSetTextMsgCb", &WxSetTextMsgCbPy);
|
||||
m.def("WxSendTextMsg", &WxSendTextMsg);
|
||||
m.def("WxGetMsgTypes", &WxGetMsgTypes, py::return_value_policy::reference);
|
||||
|
||||
#ifdef VERSION_INFO
|
||||
m.attr("__version__") = VERSION_INFO;
|
||||
#else
|
||||
m.attr("__version__") = "dev";
|
||||
#endif
|
||||
}
|
200
Spy/Spy.vcxproj
Normal file
200
Spy/Spy.vcxproj
Normal file
@ -0,0 +1,200 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{4a0a22f7-0b1c-4565-a443-c43fac6c6396}</ProjectGuid>
|
||||
<RootNamespace>Spy</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Rpc;$(SolutionDir)SDK;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions> /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
<Midl>
|
||||
<AdditionalOptions>/app_config /prefix client "client_" server "server_" </AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Rpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Rpc;$(SolutionDir)SDK;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions> /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
<Midl>
|
||||
<AdditionalOptions>/prefix client "client_" server "server_" </AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Rpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Rpc\rpc_types.h" />
|
||||
<ClInclude Include="..\Rpc\rpc_h.h" />
|
||||
<ClInclude Include="..\SDK\util.h" />
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="load_calls.h" />
|
||||
<ClInclude Include="monitor.h" />
|
||||
<ClInclude Include="receive_msg.h" />
|
||||
<ClInclude Include="rpc_server.h" />
|
||||
<ClInclude Include="send_msg.h" />
|
||||
<ClInclude Include="spy_types.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\Rpc\rpc_memory.cpp" />
|
||||
<ClCompile Include="..\Rpc\rpc_s.c" />
|
||||
<ClCompile Include="..\SDK\util.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="load_calls.cpp" />
|
||||
<ClCompile Include="monitor.cpp" />
|
||||
<ClCompile Include="receive_msg.cpp" />
|
||||
<ClCompile Include="rpc_server.cpp" />
|
||||
<ClCompile Include="send_msg.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="..\Rpc\rpc.idl">
|
||||
<OutputDirectory Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)Rpc</OutputDirectory>
|
||||
<AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">/app_config /ms_ext /prefix client "client_" server "server_" </AdditionalOptions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)Rpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<OutputDirectory Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)Rpc</OutputDirectory>
|
||||
<AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">/app_config /ms_ext /prefix client "client_" server "server_" %(AdditionalOptions)</AdditionalOptions>
|
||||
</Midl>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
86
Spy/Spy.vcxproj.filters
Normal file
86
Spy/Spy.vcxproj.filters
Normal file
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Rpc">
|
||||
<UniqueIdentifier>{37eb8a5c-e792-4c10-a858-9abc84f79f80}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Rpc\rpc_h.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="monitor.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Rpc\rpc_types.h">
|
||||
<Filter>Rpc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpc_server.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="load_calls.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SDK\util.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="receive_msg.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="send_msg.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="spy_types.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Rpc\rpc_s.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Rpc\rpc_memory.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="monitor.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpc_server.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="load_calls.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SDK\util.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="receive_msg.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="send_msg.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="..\Rpc\rpc.idl">
|
||||
<Filter>Rpc</Filter>
|
||||
</Midl>
|
||||
</ItemGroup>
|
||||
</Project>
|
4
Spy/Spy.vcxproj.user
Normal file
4
Spy/Spy.vcxproj.user
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
37
Spy/dllmain.cpp
Normal file
37
Spy/dllmain.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "monitor.h"
|
||||
#include "rpc_server.h"
|
||||
|
||||
extern HANDLE g_hEvent;
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
switch (ul_reason_for_call) {
|
||||
case DLL_PROCESS_ATTACH: {
|
||||
// MessageBox(NULL, L"RpcStartServer", L"Hey", 0);
|
||||
if (InitDLL() != 0) {
|
||||
// Exit
|
||||
FreeLibraryAndExitThread(hModule, 0);
|
||||
}
|
||||
HANDLE rpcThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RpcStartServer, hModule, NULL, 0);
|
||||
if (rpcThread != 0) {
|
||||
CloseHandle(rpcThread);
|
||||
}
|
||||
g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // 创建消息句柄
|
||||
HANDLE mThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Monitor, hModule, NULL, 0);
|
||||
if (mThread != 0) {
|
||||
CloseHandle(mThread);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH: {
|
||||
RpcStopServer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
5
Spy/framework.h
Normal file
5
Spy/framework.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
|
||||
// Windows 头文件
|
||||
#include <windows.h>
|
26
Spy/load_calls.cpp
Normal file
26
Spy/load_calls.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include "load_calls.h"
|
||||
|
||||
std::map<std::wstring, WxCalls_t> wxCalls {
|
||||
{ L"3.0.0.57",
|
||||
{ 0x1874F38, // Login Status
|
||||
{ 0x1856BF0, 0x1856A8C, 0x1856AC0 }, // User Info: wxid, nickname, mobile
|
||||
0x38D8A0, // Send Message
|
||||
// Receive Message:
|
||||
// Hook, call, type, self, id, msgXml, roomId, wxId, content
|
||||
{ 0x36A350, 0x36A5A0, 0x30, 0x34, 0x164, 0x1A4, 0x40, 0x150, 0x68 } } }
|
||||
};
|
||||
|
||||
int LoadCalls(const wchar_t *version, WxCalls_t *calls)
|
||||
{
|
||||
auto iter = wxCalls.find(version);
|
||||
if (iter == wxCalls.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy_s(calls, sizeof(WxCalls_t), &(iter->second), sizeof(WxCalls_t));
|
||||
|
||||
return 0;
|
||||
}
|
5
Spy/load_calls.h
Normal file
5
Spy/load_calls.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "spy_types.h"
|
||||
|
||||
int LoadCalls(const wchar_t *version, WxCalls_t *calls);
|
54
Spy/monitor.cpp
Normal file
54
Spy/monitor.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include <atlstr.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "load_calls.h"
|
||||
#include "monitor.h"
|
||||
#include "receive_msg.h"
|
||||
#include "util.h"
|
||||
|
||||
HANDLE g_hEvent = NULL;
|
||||
WxCalls_t g_WxCalls = { 0 };
|
||||
RpcMessage_t *g_pMsg = NULL; // Find a palce to free
|
||||
DWORD g_WeChatWinDllAddr = 0;
|
||||
|
||||
int InitDLL(void)
|
||||
{
|
||||
wchar_t version[16] = { 0 };
|
||||
|
||||
g_WeChatWinDllAddr = (DWORD)LoadLibrary(L"WeChatWin.dll"); //获取wechatWin模块地址
|
||||
if (g_WeChatWinDllAddr == 0) {
|
||||
MessageBox(NULL, L"获取wechatWin.dll模块地址", L"错误", 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!GetWeChatVersion(version)) { //获取微信版本
|
||||
MessageBox(NULL, L"获取微信版本失败", L"错误", 0);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (LoadCalls(version, &g_WxCalls) != 0) { //加载微信版本对应的Call地址
|
||||
MessageBox(NULL, L"不支持当前版本", L"错误", 0);
|
||||
return -3;
|
||||
}
|
||||
|
||||
g_pMsg = new RpcMessage_t;
|
||||
g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WINAPI Monitor(HMODULE hModule)
|
||||
{
|
||||
ListenMessage();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int IsLogin(void)
|
||||
{
|
||||
if (g_WeChatWinDllAddr == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int)GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.login);
|
||||
}
|
7
Spy/monitor.h
Normal file
7
Spy/monitor.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "framework.h"
|
||||
|
||||
int InitDLL(void);
|
||||
DWORD WINAPI Monitor(HMODULE hModule);
|
||||
int IsLogin();
|
79
Spy/receive_msg.cpp
Normal file
79
Spy/receive_msg.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
#include "framework.h"
|
||||
|
||||
#include "load_calls.h"
|
||||
#include "receive_msg.h"
|
||||
#include "spy_types.h"
|
||||
#include "util.h"
|
||||
|
||||
extern HANDLE g_hEvent;
|
||||
extern RpcMessage_t *g_pMsg;
|
||||
extern WxCalls_t g_WxCalls;
|
||||
extern DWORD g_WeChatWinDllAddr;
|
||||
|
||||
MsgQueue_t g_MsgQueue;
|
||||
DWORD reg_buffer = 0;
|
||||
DWORD recvMsgCallAddr = 0;
|
||||
DWORD recvMsgJumpBackAddr = 0;
|
||||
|
||||
void DispatchMsg(DWORD reg)
|
||||
{
|
||||
DWORD **p = (DWORD **)reg; //消息结构基址
|
||||
|
||||
memset(g_pMsg, 0, sizeof(RpcMessage_t));
|
||||
|
||||
g_pMsg->type = GET_DWORD(**p + g_WxCalls.recvMsg.type);
|
||||
g_pMsg->self = GET_DWORD(**p + g_WxCalls.recvMsg.isSelf);
|
||||
|
||||
GetWstringByAddress(**p + g_WxCalls.recvMsg.msgId, g_pMsg->id, MSG_SIZE_MSG_ID);
|
||||
GetWstringByAddress(**p + g_WxCalls.recvMsg.msgXml, g_pMsg->xml, MSG_SIZE_MSG_XML);
|
||||
|
||||
if (wcsstr(g_pMsg->xml, L"<membercount>") == NULL) {
|
||||
// g_pMsg.roomId = {0};
|
||||
GetWstringByAddress(**p + g_WxCalls.recvMsg.roomId, g_pMsg->wxId, MSG_SIZE_WXID);
|
||||
} else {
|
||||
g_pMsg->source = 1;
|
||||
GetWstringByAddress(**p + g_WxCalls.recvMsg.roomId, g_pMsg->roomId, MSG_SIZE_ROOMID);
|
||||
GetWstringByAddress(**p + g_WxCalls.recvMsg.wxId, g_pMsg->wxId, MSG_SIZE_WXID);
|
||||
}
|
||||
GetWstringByAddress(**p + g_WxCalls.recvMsg.content, g_pMsg->content, MSG_SIZE_CONTENT);
|
||||
g_MsgQueue.push(*g_pMsg); // 发送消息
|
||||
SetEvent(g_hEvent); // 发送消息通知
|
||||
}
|
||||
|
||||
__declspec(naked) void RecieveMsgHook()
|
||||
{
|
||||
__asm {
|
||||
push ebp // 保护现场
|
||||
add ebp, 0x3C // 地址为 ebp + 0x3C
|
||||
mov reg_buffer, ebp //把值复制出来
|
||||
pop ebp // 还原现场
|
||||
}
|
||||
|
||||
DispatchMsg(reg_buffer);
|
||||
|
||||
__asm
|
||||
{
|
||||
call recvMsgCallAddr // 这个为被覆盖的call
|
||||
jmp recvMsgJumpBackAddr // 跳回被HOOK指令的下一条指令
|
||||
}
|
||||
}
|
||||
|
||||
void ListenMessage()
|
||||
{
|
||||
// MessageBox(NULL, L"ListenMessage", L"ListenMessage", 0);
|
||||
if (g_WeChatWinDllAddr == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD hookAddress = g_WeChatWinDllAddr + g_WxCalls.recvMsg.hook;
|
||||
recvMsgCallAddr = g_WeChatWinDllAddr + g_WxCalls.recvMsg.call;
|
||||
recvMsgJumpBackAddr = hookAddress + 5;
|
||||
|
||||
BYTE jmpCode[5] = { 0 };
|
||||
jmpCode[0] = 0xE9;
|
||||
|
||||
*(DWORD *)&jmpCode[1] = (DWORD)RecieveMsgHook - hookAddress - 5;
|
||||
|
||||
// 6FB6A350 E8 4B020000 call WeChatWi .6FB6A5A0;
|
||||
WriteProcessMemory(GetCurrentProcess(), (LPVOID)hookAddress, jmpCode, 5, 0);
|
||||
}
|
3
Spy/receive_msg.h
Normal file
3
Spy/receive_msg.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void ListenMessage();
|
94
Spy/rpc_server.cpp
Normal file
94
Spy/rpc_server.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "monitor.h"
|
||||
#include "rpc_server.h"
|
||||
#include "send_msg.h"
|
||||
#include "spy_types.h"
|
||||
|
||||
#include "../Rpc/rpc_h.h"
|
||||
#pragma comment(lib, "Rpcrt4.lib")
|
||||
|
||||
extern HANDLE g_hEvent;
|
||||
extern MsgQueue_t g_MsgQueue;
|
||||
|
||||
int server_IsLogin() { return IsLogin(); }
|
||||
|
||||
void server_EnableReceiveMsg()
|
||||
{
|
||||
unsigned long ulCode = 0;
|
||||
|
||||
RpcTryExcept
|
||||
{
|
||||
// 调用客户端的回调函数
|
||||
while (true) {
|
||||
// 中断式,兼顾及时性和CPU使用率
|
||||
WaitForSingleObject(g_hEvent, INFINITE); // 等待消息
|
||||
while (!g_MsgQueue.empty()) {
|
||||
client_ReceiveMsg((RpcMessage_t *)&g_MsgQueue.front()); // 调用接收消息回调
|
||||
g_MsgQueue.pop();
|
||||
}
|
||||
ResetEvent(g_hEvent);
|
||||
}
|
||||
}
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept
|
||||
}
|
||||
|
||||
int server_SendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg)
|
||||
{
|
||||
SendTextMessage(wxid, at_wxid, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/)
|
||||
{
|
||||
return RPC_S_OK; // Always allow anyone.
|
||||
}
|
||||
|
||||
int RpcStartServer(HMODULE hModule)
|
||||
{
|
||||
RPC_STATUS status;
|
||||
// Uses the protocol combined with the endpoint for receiving
|
||||
// remote procedure calls.
|
||||
status = RpcServerUseProtseqEp(reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
|
||||
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Backlog queue length for TCP/IP.
|
||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use
|
||||
NULL // No security
|
||||
);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
// Registers the interface and auto listen
|
||||
// Equal to RpcServerRegisterIf + RpcServerListen
|
||||
status = RpcServerRegisterIf2(server_ISpy_v1_0_s_ifspec, // Interface to register.
|
||||
NULL, // Use the MIDL generated entry-point vector.
|
||||
NULL, // Use the MIDL generated entry-point vector.
|
||||
RPC_IF_ALLOW_LOCAL_ONLY | RPC_IF_AUTOLISTEN, // Forces use of security callback.
|
||||
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Use default number of concurrent calls.
|
||||
(unsigned)-1, // Infinite max size of incoming data blocks.
|
||||
SecurityCallback); // Naive security callback.
|
||||
|
||||
while (1) {
|
||||
Sleep(10000); // 休眠,释放CPU
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RpcStopServer(void)
|
||||
{
|
||||
RPC_STATUS status;
|
||||
status = RpcMgmtStopServerListening(NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = RpcServerUnregisterIf(NULL, NULL, FALSE);
|
||||
return status;
|
||||
}
|
5
Spy/rpc_server.h
Normal file
5
Spy/rpc_server.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include "framework.h"
|
||||
|
||||
int RpcStartServer(HMODULE hModule);
|
||||
int RpcStopServer(void);
|
49
Spy/send_msg.cpp
Normal file
49
Spy/send_msg.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "framework.h"
|
||||
#include <string>
|
||||
|
||||
#include "spy_types.h"
|
||||
|
||||
extern HANDLE g_hEvent;
|
||||
extern WxCalls_t g_WxCalls;
|
||||
extern RpcMessage_t *g_pMsg;
|
||||
extern DWORD g_WeChatWinDllAddr;
|
||||
|
||||
using namespace std;
|
||||
|
||||
void SendTextMessage(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg)
|
||||
{
|
||||
if (g_WeChatWinDllAddr == 0) {
|
||||
return;
|
||||
}
|
||||
char buffer[0x5F0] = { 0 };
|
||||
TextStruct_t txtWxid = { 0 };
|
||||
TextStruct_t txtAtWxid = { 0 };
|
||||
TextStruct_t txtMsg = { 0 };
|
||||
|
||||
wstring wsWxid = wxid;
|
||||
wstring wsAtWxid = at_wxid;
|
||||
wstring wsMsg = msg;
|
||||
|
||||
// 发送消息Call地址 = 微信基址 + 偏移
|
||||
DWORD sendCallAddress = g_WeChatWinDllAddr + g_WxCalls.sendTextMsg;
|
||||
|
||||
txtWxid.text = (wchar_t *)wsWxid.c_str();
|
||||
txtWxid.size = wsWxid.size();
|
||||
txtWxid.capacity = wsWxid.capacity();
|
||||
|
||||
txtMsg.text = (wchar_t *)wsMsg.c_str();
|
||||
txtMsg.size = wsMsg.size();
|
||||
txtMsg.capacity = wsMsg.capacity();
|
||||
|
||||
__asm {
|
||||
lea edx, txtWxid
|
||||
lea edi, txtAtWxid
|
||||
lea ebx, txtMsg
|
||||
push 0x01
|
||||
push edi
|
||||
push ebx
|
||||
lea ecx, buffer;
|
||||
call sendCallAddress
|
||||
add esp, 0xC
|
||||
}
|
||||
}
|
3
Spy/send_msg.h
Normal file
3
Spy/send_msg.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void SendTextMessage(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg);
|
46
Spy/spy_types.h
Normal file
46
Spy/spy_types.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "framework.h"
|
||||
#include <queue>
|
||||
|
||||
#include "rpc_types.h"
|
||||
|
||||
typedef struct UserInfoCall {
|
||||
DWORD wxid;
|
||||
DWORD nickName;
|
||||
DWORD mobile;
|
||||
} UserInfoCall_t;
|
||||
|
||||
typedef struct RecvMsg {
|
||||
DWORD hook; // Hook地址
|
||||
DWORD call; // Call地址
|
||||
DWORD type; // 消息类型地址
|
||||
DWORD isSelf; // 是否自己发送标志地址
|
||||
DWORD msgId; // 消息ID地址
|
||||
DWORD msgXml; // 消息xml内容地址
|
||||
DWORD roomId; // 群聊时,为群ID;私聊时,为微信ID
|
||||
DWORD wxId; // 私聊时,为空;群群时,为发送者微信ID
|
||||
DWORD content; // 消息内容地址
|
||||
} RecvMsg_t;
|
||||
|
||||
typedef struct SendImg {
|
||||
DWORD call1;
|
||||
DWORD call2;
|
||||
DWORD call3;
|
||||
} SendImg_t;
|
||||
|
||||
typedef struct WxCalls {
|
||||
DWORD login; // 登录状态
|
||||
UserInfoCall_t ui; // 用户信息
|
||||
DWORD sendTextMsg; // 发送消息
|
||||
RecvMsg_t recvMsg; // 接收消息
|
||||
} WxCalls_t;
|
||||
|
||||
typedef struct TextStruct {
|
||||
wchar_t *text;
|
||||
DWORD size;
|
||||
DWORD capacity;
|
||||
char fill[8];
|
||||
} TextStruct_t;
|
||||
|
||||
typedef std::queue<RpcMessage_t> MsgQueue_t;
|
72
WeChatFerry.sln
Normal file
72
WeChatFerry.sln
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30503.244
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Spy", "Spy\Spy.vcxproj", "{4A0A22F7-0B1C-4565-A443-C43FAC6C6396}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDK", "SDK\SDK.vcxproj", "{707F2DCD-1001-42A7-B20E-B85B1BBAB228}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{4A0A22F7-0B1C-4565-A443-C43FAC6C6396} = {4A0A22F7-0B1C-4565-A443-C43FAC6C6396}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "App", "App\App.vcxproj", "{44C1A579-22A7-4BA3-A618-45BD01600294}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{121AD245-72FB-47A6-99D6-5427B74FA7B9} = {121AD245-72FB-47A6-99D6-5427B74FA7B9}
|
||||
{707F2DCD-1001-42A7-B20E-B85B1BBAB228} = {707F2DCD-1001-42A7-B20E-B85B1BBAB228}
|
||||
{4A0A22F7-0B1C-4565-A443-C43FAC6C6396} = {4A0A22F7-0B1C-4565-A443-C43FAC6C6396}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDKpy", "SDKpy\SDKpy.vcxproj", "{121AD245-72FB-47A6-99D6-5427B74FA7B9}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{707F2DCD-1001-42A7-B20E-B85B1BBAB228} = {707F2DCD-1001-42A7-B20E-B85B1BBAB228}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4A0A22F7-0B1C-4565-A443-C43FAC6C6396}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4A0A22F7-0B1C-4565-A443-C43FAC6C6396}.Debug|x64.Build.0 = Debug|x64
|
||||
{4A0A22F7-0B1C-4565-A443-C43FAC6C6396}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4A0A22F7-0B1C-4565-A443-C43FAC6C6396}.Debug|x86.Build.0 = Debug|Win32
|
||||
{4A0A22F7-0B1C-4565-A443-C43FAC6C6396}.Release|x64.ActiveCfg = Release|x64
|
||||
{4A0A22F7-0B1C-4565-A443-C43FAC6C6396}.Release|x64.Build.0 = Release|x64
|
||||
{4A0A22F7-0B1C-4565-A443-C43FAC6C6396}.Release|x86.ActiveCfg = Release|Win32
|
||||
{4A0A22F7-0B1C-4565-A443-C43FAC6C6396}.Release|x86.Build.0 = Release|Win32
|
||||
{707F2DCD-1001-42A7-B20E-B85B1BBAB228}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{707F2DCD-1001-42A7-B20E-B85B1BBAB228}.Debug|x64.Build.0 = Debug|x64
|
||||
{707F2DCD-1001-42A7-B20E-B85B1BBAB228}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{707F2DCD-1001-42A7-B20E-B85B1BBAB228}.Debug|x86.Build.0 = Debug|Win32
|
||||
{707F2DCD-1001-42A7-B20E-B85B1BBAB228}.Release|x64.ActiveCfg = Release|x64
|
||||
{707F2DCD-1001-42A7-B20E-B85B1BBAB228}.Release|x64.Build.0 = Release|x64
|
||||
{707F2DCD-1001-42A7-B20E-B85B1BBAB228}.Release|x86.ActiveCfg = Release|Win32
|
||||
{707F2DCD-1001-42A7-B20E-B85B1BBAB228}.Release|x86.Build.0 = Release|Win32
|
||||
{44C1A579-22A7-4BA3-A618-45BD01600294}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{44C1A579-22A7-4BA3-A618-45BD01600294}.Debug|x64.Build.0 = Debug|x64
|
||||
{44C1A579-22A7-4BA3-A618-45BD01600294}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{44C1A579-22A7-4BA3-A618-45BD01600294}.Debug|x86.Build.0 = Debug|Win32
|
||||
{44C1A579-22A7-4BA3-A618-45BD01600294}.Release|x64.ActiveCfg = Release|x64
|
||||
{44C1A579-22A7-4BA3-A618-45BD01600294}.Release|x64.Build.0 = Release|x64
|
||||
{44C1A579-22A7-4BA3-A618-45BD01600294}.Release|x86.ActiveCfg = Release|Win32
|
||||
{44C1A579-22A7-4BA3-A618-45BD01600294}.Release|x86.Build.0 = Release|Win32
|
||||
{121AD245-72FB-47A6-99D6-5427B74FA7B9}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{121AD245-72FB-47A6-99D6-5427B74FA7B9}.Debug|x64.Build.0 = Debug|x64
|
||||
{121AD245-72FB-47A6-99D6-5427B74FA7B9}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{121AD245-72FB-47A6-99D6-5427B74FA7B9}.Debug|x86.Build.0 = Debug|Win32
|
||||
{121AD245-72FB-47A6-99D6-5427B74FA7B9}.Release|x64.ActiveCfg = Release|x64
|
||||
{121AD245-72FB-47A6-99D6-5427B74FA7B9}.Release|x64.Build.0 = Release|x64
|
||||
{121AD245-72FB-47A6-99D6-5427B74FA7B9}.Release|x86.ActiveCfg = Release|Win32
|
||||
{121AD245-72FB-47A6-99D6-5427B74FA7B9}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {569E7E61-8FD2-43B5-8F34-C61D6417F905}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
Loading…
Reference in New Issue
Block a user