├── .github └── workflows │ └── release.yaml ├── .gitignore ├── .vscode ├── c_cpp_properties.json ├── extensions.json ├── launch.json └── settings.json ├── CHANGELOG.MD ├── CMakeLists.txt ├── README.MD ├── src ├── CMakeLists.txt ├── config │ └── init.cc ├── dbghelp │ ├── CMakeLists.txt │ └── dbghelp.cc ├── fiddler │ ├── CMakeLists.txt │ ├── fiddler.cc │ └── libfiddler.rc.in ├── hook │ └── hook.cc ├── include │ ├── const.hh │ ├── hook.hh │ ├── info_check.hh │ ├── init.hh │ ├── nt.hh │ └── redirect.hh ├── info_check.cc └── test │ └── read.cc ├── test ├── CMakeLists.txt └── fiddler.cc ├── tools ├── linux │ └── ci.sh ├── mac │ └── ci.sh ├── prepare-arm64e.js └── windows │ └── ci.ps1 ├── vcpkg-configuration.json └── vcpkg.json /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Build Packages 5 | 6 | on: 7 | release: 8 | types: [published] 9 | push: 10 | tags: 11 | - v* 12 | branches: [ master, dev, ci, mac] 13 | pull_request: 14 | branches: [ master ] 15 | # # Allows you to run this workflow manually from the Actions tab 16 | # workflow_dispatch: 17 | 18 | jobs: 19 | build-windows: 20 | name: Build Windows 21 | runs-on: windows-latest 22 | 23 | strategy: 24 | matrix: 25 | arch: ['x86_64'] 26 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 27 | 28 | steps: 29 | - uses: actions/checkout@v2 30 | with: 31 | submodules: 'recursive' 32 | 33 | - name: Generate TAG 34 | id: Tag 35 | run: | 36 | $tag="continuous" 37 | $name="Continuous Build" 38 | if ( "true" -eq "${{ startsWith(github.ref, 'refs/tags/') }}" ) { 39 | $tag="${{ github.ref_name }}" 40 | $name='${{ github.ref_name }}' 41 | } 42 | echo "tag result: $tag - $name" 43 | echo "::set-output name=tag::$tag" 44 | echo "::set-output name=name::$name" 45 | 46 | - name: run-vcpkg 47 | uses: lukka/run-vcpkg@v11.5 # Option 2: specify 'latest' or 'latestrc' in the input version arguments: 48 | 49 | - uses: TheMrMilchmann/setup-msvc-dev@v3 50 | with: 51 | arch: ${{ matrix.arch }} 52 | - name: Build 53 | run: | 54 | powershell tools/windows/ci.ps1 ${{ matrix.arch }} ${{ steps.tag.outputs.tag }} 55 | 56 | - name: Upload artifact 57 | uses: actions/upload-artifact@v4 58 | with: 59 | # Artifact name 60 | name: yui-${{ matrix.arch }}.build-win 61 | path: tmp/build 62 | 63 | build-linux: 64 | name: Build Linux 65 | runs-on: ubuntu-20.04 66 | 67 | strategy: 68 | matrix: 69 | arch: ['x86_64'] 70 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 71 | 72 | steps: 73 | - uses: actions/checkout@v2 74 | with: 75 | submodules: 'recursive' 76 | 77 | - name: Generate TAG 78 | id: Tag 79 | run: | 80 | tag='continuous' 81 | name='Continuous Build' 82 | if [ 'true' == ${{ startsWith(github.ref, 'refs/tags/') }} ];then 83 | tag='${{ github.ref_name }}' 84 | name='${{ github.ref_name }}' 85 | fi 86 | echo "tag result: $tag - $name" 87 | echo "::set-output name=tag::$tag" 88 | echo "::set-output name=name::$name" 89 | 90 | - name: run-vcpkg 91 | uses: lukka/run-vcpkg@v11.5 # Option 2: specify 'latest' or 'latestrc' in the input version arguments: 92 | 93 | - name: Build 94 | run: | 95 | sudo apt install -y ninja-build 96 | tools/linux/ci.sh ${{ matrix.arch }} ${{ steps.tag.outputs.tag }} 97 | 98 | - name: Upload artifact 99 | uses: actions/upload-artifact@v4 100 | with: 101 | # Artifact name 102 | name: yui-${{ matrix.arch }}.build-linux 103 | path: tmp/build 104 | 105 | build-mac-x86: 106 | name: Build MAC 107 | runs-on: macos-13 108 | 109 | strategy: 110 | matrix: 111 | arch: ['x86_64'] 112 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 113 | 114 | steps: 115 | - uses: actions/checkout@v2 116 | with: 117 | submodules: 'recursive' 118 | 119 | - name: Generate TAG 120 | id: Tag 121 | run: | 122 | tag='continuous' 123 | name='Continuous Build' 124 | if [ 'true' == ${{ startsWith(github.ref, 'refs/tags/') }} ];then 125 | tag='${{ github.ref_name }}' 126 | name='${{ github.ref_name }}' 127 | fi 128 | echo "tag result: $tag - $name" 129 | echo "::set-output name=tag::$tag" 130 | echo "::set-output name=name::$name" 131 | 132 | - name: run-vcpkg 133 | uses: lukka/run-vcpkg@v11.5 # Option 2: specify 'latest' or 'latestrc' in the input version arguments: 134 | 135 | - name: Build 136 | run: | 137 | brew install ninja 138 | tools/mac/ci.sh ${{ matrix.arch }} ${{ steps.tag.outputs.tag }} 139 | 140 | - name: Upload artifact 141 | uses: actions/upload-artifact@v4 142 | with: 143 | # Artifact name 144 | name: yui-${{ matrix.arch }}.build-mac 145 | path: tmp/build 146 | 147 | build-mac-arm64: 148 | name: Build MAC 149 | runs-on: macos-latest 150 | 151 | strategy: 152 | matrix: 153 | arch: ['arm64', 'arm64e'] 154 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 155 | 156 | steps: 157 | - uses: actions/checkout@v2 158 | with: 159 | submodules: 'recursive' 160 | 161 | - name: Generate TAG 162 | id: Tag 163 | run: | 164 | tag='continuous' 165 | name='Continuous Build' 166 | if [ 'true' == ${{ startsWith(github.ref, 'refs/tags/') }} ];then 167 | tag='${{ github.ref_name }}' 168 | name='${{ github.ref_name }}' 169 | fi 170 | echo "tag result: $tag - $name" 171 | echo "::set-output name=tag::$tag" 172 | echo "::set-output name=name::$name" 173 | 174 | - name: Prepare Arm64e 175 | if: matrix.arch == 'arm64e' 176 | run: | 177 | node tools/prepare-arm64e.js 178 | 179 | - name: run-vcpkg arm64 180 | if: matrix.arch == 'arm64' 181 | uses: lukka/run-vcpkg@v11.5 # Option 2: specify 'latest' or 'latestrc' in the input version arguments: 182 | 183 | - name: run-vcpkg arm64e 184 | if: matrix.arch == 'arm64e' 185 | uses: lukka/run-vcpkg@v11.5 # Option 2: specify 'latest' or 'latestrc' in the input version arguments: 186 | with: 187 | vcpkgGitURL: https://github.com/msojocs/vcpkg.git 188 | 189 | - name: Build 190 | env: 191 | ACTION_OSX_ARCHITECTURES: ${{ matrix.arch }} 192 | run: | 193 | brew install ninja 194 | tools/mac/ci.sh ${{ matrix.arch }} ${{ steps.tag.outputs.tag }} 195 | 196 | - name: Upload artifact 197 | uses: actions/upload-artifact@v4 198 | with: 199 | # Artifact name 200 | name: yui-${{ matrix.arch }}.build-mac 201 | path: tmp/build 202 | 203 | upload: 204 | name: Create release and upload artifacts 205 | needs: 206 | - build-windows 207 | - build-linux 208 | - build-mac-x86 209 | - build-mac-arm64 210 | runs-on: ubuntu-latest 211 | steps: 212 | - name: Download artifacts 213 | uses: actions/download-artifact@v4.1.8 214 | - name: Inspect directory after downloading artifacts 215 | run: ls -alFR 216 | 217 | - name: Generate TAG 218 | id: Tag 219 | run: | 220 | tag='continuous' 221 | name='Continuous Build' 222 | if [ 'true' == ${{ startsWith(github.ref, 'refs/tags/') }} ];then 223 | tag='${{ github.ref_name }}' 224 | name='${{ github.ref_name }}' 225 | fi 226 | echo "tag result: $tag - $name" 227 | echo "::set-output name=tag::$tag" 228 | echo "::set-output name=name::$name" 229 | 230 | - name: Create release and upload artifacts 231 | if: startsWith(github.ref, 'refs/heads/') 232 | env: 233 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 234 | run: | 235 | sudo apt install -y fuse 236 | wget -q https://github.com/TheAssassin/pyuploadtool/releases/download/continuous/pyuploadtool-x86_64.AppImage 237 | chmod +x pyuploadtool-x86_64.AppImage 238 | ./pyuploadtool-x86_64.AppImage \ 239 | **build-win/*.dll \ 240 | **build-linux/*.so \ 241 | **build-mac/*.dylib 242 | 243 | - name: Release 244 | uses: softprops/action-gh-release@v1 245 | if: startsWith(github.ref, 'refs/tags/') 246 | with: 247 | # note you'll typically need to create a personal access token 248 | # with permissions to create releases in the other repo 249 | name: ${{ steps.tag.outputs.name }} 250 | tag_name: ${{ steps.tag.outputs.tag }} 251 | files: | 252 | **build-win/*.dll 253 | **build-linux/*.so 254 | **build-mac/*.dylib -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules 3 | vcpkg_installed 4 | ntqq 5 | cache 6 | tmp 7 | *.exp 8 | *.lib 9 | .cache -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${default}" 7 | ], 8 | "defines": [], 9 | "cStandard": "c17", 10 | "cppStandard": "c++17", 11 | "intelliSenseMode": "windows-msvc-x64" 12 | } 13 | ], 14 | "version": 4 15 | } -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-vscode.cmake-tools", 4 | "llvm-vs-code-extensions.vscode-clangd", 5 | "peterj.proto", 6 | "kevinkyang.auto-comment-blocks", 7 | "twxs.cmake" 8 | ] 9 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug", 11 | "program": "${workspaceFolder}/build/test", 12 | "args": [], 13 | "cwd": "${workspaceFolder}" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cmake.sourceDirectory": "${workspaceFolder}", 3 | "clangd.path": "clangd", 4 | "clangd.arguments": [ 5 | // 让 Clangd 生成更详细的日志 6 | // "--log=verbose", 7 | // 输出的 JSON 文件更美观 8 | "--pretty", 9 | // 全局补全(输入时弹出的建议将会提供 CMakeLists.txt 里配置的所有文件中可能的符号,会自动补充头文件) 10 | "--all-scopes-completion", 11 | // 建议风格:打包(重载函数只会给出一个建议) 12 | // 相反可以设置为detailed 13 | "--completion-style=bundled", 14 | // 跨文件重命名变量 15 | "--cross-file-rename", 16 | // 允许补充头文件 17 | "--header-insertion=iwyu", 18 | // 输入建议中,已包含头文件的项与还未包含头文件的项会以圆点加以区分 19 | "--header-insertion-decorators", 20 | // 在后台自动分析文件(基于 complie_commands,我们用CMake生成) 21 | "--background-index", 22 | // 启用 Clang-Tidy 以提供「静态检查」 23 | "--clang-tidy", 24 | // Clang-Tidy 静态检查的参数,指出按照哪些规则进行静态检查,详情见「与按照官方文档配置好的 VSCode 相比拥有的优势」 25 | // 参数后部分的*表示通配符 26 | // 在参数前加入-,如-modernize-use-trailing-return-type,将会禁用某一规则 27 | "--clang-tidy-checks=cppcoreguidelines-*,performance-*,bugprone-*,portability-*,modernize-*,google-*", 28 | // 默认格式化风格: 谷歌开源项目代码指南 29 | "--fallback-style=file", 30 | // 同时开启的任务数量 31 | "-j=2", 32 | // pch优化的位置(memory 或 disk,选择memory会增加内存开销,但会提升性能) 推荐在板子上使用disk 33 | "--pch-storage=memory", 34 | // 启用这项时,补全函数时,将会给参数提供占位符,键入后按 Tab 可以切换到下一占位符,乃至函数末 35 | // 我选择禁用 36 | // "--function-arg-placeholders=false", 37 | // compelie_commands.json 文件的目录位置(相对于工作区,由于 CMake 生成的该文件默认在 build 文件夹中,故设置为 build) 38 | "--compile-commands-dir=build" 39 | ], 40 | "files.associations": { 41 | "array": "cpp", 42 | "atomic": "cpp", 43 | "bit": "cpp", 44 | "*.tcc": "cpp", 45 | "cctype": "cpp", 46 | "chrono": "cpp", 47 | "clocale": "cpp", 48 | "cmath": "cpp", 49 | "compare": "cpp", 50 | "concepts": "cpp", 51 | "condition_variable": "cpp", 52 | "cstdarg": "cpp", 53 | "cstddef": "cpp", 54 | "cstdint": "cpp", 55 | "cstdio": "cpp", 56 | "cstdlib": "cpp", 57 | "cstring": "cpp", 58 | "ctime": "cpp", 59 | "cwchar": "cpp", 60 | "cwctype": "cpp", 61 | "deque": "cpp", 62 | "unordered_map": "cpp", 63 | "vector": "cpp", 64 | "exception": "cpp", 65 | "algorithm": "cpp", 66 | "functional": "cpp", 67 | "iterator": "cpp", 68 | "memory": "cpp", 69 | "memory_resource": "cpp", 70 | "numeric": "cpp", 71 | "optional": "cpp", 72 | "random": "cpp", 73 | "ratio": "cpp", 74 | "string": "cpp", 75 | "string_view": "cpp", 76 | "system_error": "cpp", 77 | "tuple": "cpp", 78 | "type_traits": "cpp", 79 | "utility": "cpp", 80 | "fstream": "cpp", 81 | "initializer_list": "cpp", 82 | "iosfwd": "cpp", 83 | "iostream": "cpp", 84 | "istream": "cpp", 85 | "limits": "cpp", 86 | "mutex": "cpp", 87 | "new": "cpp", 88 | "ostream": "cpp", 89 | "ranges": "cpp", 90 | "sstream": "cpp", 91 | "stdexcept": "cpp", 92 | "stop_token": "cpp", 93 | "streambuf": "cpp", 94 | "thread": "cpp", 95 | "cinttypes": "cpp", 96 | "typeinfo": "cpp", 97 | "complex": "cpp", 98 | "*.inc": "cpp" 99 | }, 100 | // 使用Ninja,可以生成compile_commands.json 101 | "cmake.generator": "Ninja" 102 | } -------------------------------------------------------------------------------- /CHANGELOG.MD: -------------------------------------------------------------------------------- 1 | ## v1.1.3 / 2024-10-14 2 | 3 | - fix: 跳过时,计数没有增加。 4 | 5 | ## v1.1.2 / 2024-10-01 6 | 7 | - feat: 添加Mac arm64e架构的支持。 8 | 9 | ## v1.1.1 / 2024-09-30 10 | 11 | - fix: 修正Linux平台可能崩溃的问题。 12 | 13 | ## v1.1.0 / 2024-09-21 14 | 15 | - feat: 新版fiddler支持。 16 | 17 | ## v1.0.9 / 2024-08-17 18 | 19 | - fix: 盘符大小写可能错误。 20 | 21 | ## v1.0.8 / 2024-08-13 22 | 23 | - fix: dbghelp计数错误。 24 | 25 | ## v1.0.7 / 2024-08-03 26 | 27 | - fix: Mac的Arm平台构建错误。 28 | 29 | ## v1.0.6 / 2024-07-31 30 | 31 | - feat: Mac平台支持。 32 | 33 | ## v1.0.5 / 2024-07-28 34 | 35 | - feat: Linux平台支持。 36 | 37 | ## v1.0.4 / 2024-05-27 38 | 39 | - fix: windows没有开启utf8时,校验错误。 40 | 41 | ## v1.0.3 / 2024-05-26 42 | 43 | - fix: 配置文件读取错误 44 | - fix: 文件校验异常 45 | 46 | ## v1.0.1 / 2024-05-25 47 | 48 | - feat: 添加 `SymGetOptions`, 解决Filder Everywhere启动报错 49 | - feat: hostpolicy, libfiddler 50 | 51 | ## v1.0.0 / 2024-04-29 52 | 53 | - 初版 -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | cmake_policy(SET CMP0091 NEW) 3 | cmake_policy(SET CMP0042 NEW) 4 | 5 | project("yui_patch" VERSION 1.0.4) 6 | if(APPLE) 7 | message("MAC Processor: " ${CMAKE_SYSTEM_PROCESSOR}) 8 | set(CMAKE_OSX_ARCHITECTURES ${CMAKE_SYSTEM_PROCESSOR}) 9 | if("$ENV{ACTION_OSX_ARCHITECTURES}" STREQUAL "arm64e") 10 | set(CMAKE_OSX_ARCHITECTURES "arm64e") 11 | endif() 12 | endif() 13 | set(VCPKG_ROOT $ENV{VCPKG_ROOT}) 14 | message("VCPKG_ROOT: " ${VCPKG_ROOT}) 15 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 16 | set(CMAKE_CXX_STANDARD 17) 17 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 18 | set(CMAKE_CXX_EXTENSIONS OFF) # optional: do not use compiler-specific extensions 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 21 | set(CMAKE_VERBOSE_MAKEFILE ON) 22 | set(TARGET_ARCH x64) 23 | if(MSVC) 24 | set(VCPKG_TARGET_TRIPLET x64-windows-static) 25 | # set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/Debug") 26 | # set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Release") 27 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") 28 | endif() 29 | set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "Vcpkg toolchain file") 30 | include("${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake") 31 | 32 | message("LD_LIBRARY_PATH:" ${LD_LIBRARY_PATH}) 33 | 34 | if(MSVC) 35 | find_package(minhook CONFIG REQUIRED) 36 | endif() 37 | find_package(spdlog CONFIG REQUIRED) 38 | find_package(jsoncpp CONFIG REQUIRED) 39 | 40 | add_subdirectory(./src) 41 | add_subdirectory(./test) 42 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # Yui-Patch 2 | 3 | 适用于Yui的底层模块。 4 | 5 | ## 功能 6 | 7 | 1. 拦截国内知名聊天软件的文件验证,下文称之为 Telecord (Telegram + Discord)。 8 | 9 | ## 逻辑 10 | 11 | ### 基本原理 12 | 13 | 1. 创建一个默认的 `index.default.js`,内容为安装时的 `index.js` 内容; 而 `index.js` 则为修改的内容。 14 | 2. 拦截CreateFileW 15 | 3. 如果第一次访问 `index.js`,判定为校验文件,返回 `index.default.js` 的fd 16 | 4. 否则返回 `index.js` 的fd 17 | 18 | ### 优先级 19 | 20 | 绝对路径 > 相对路径(当前目录) > 相对路径(系统临时文件目录) 21 | 22 | 1. 如果是绝对路径会直接使用绝对路径。 23 | 2. 否则,工作目录能创建文件,会在工作目录创建文件。 24 | 3. 工作目录没有权限会在系统临时文件夹创建文件。 25 | 4. 如果存在文件,不会覆盖文件内容。 26 | 27 | 使用已有文件 > 创建新文件 28 | 29 | 1. 如果文件已经存在,不会进行覆盖写入。 30 | 2. 如果文件不存在会创建并写入 `content` 数据。 31 | 32 | 对于二进制文件,阁下可以手动创建文件,写成绝对路径。 33 | 34 | ## 使用 35 | 36 | 1. 构建生成 `dbghelp.dll` 文件 37 | 2. 放置于Telecord目录 38 | 3. 创建patch.json文件写入内容: 39 | ```json 40 | { 41 | "program\\resources\\app\\app_launcher\\index.js": { 42 | "target": "index.default.js", 43 | "content": "require('./launcher.node').load('external_index', module);", 44 | "cur": 0, 45 | "start": 0, 46 | "end": 1 47 | } 48 | } 49 | ``` 50 | 51 | ### 注意 52 | 53 | > ~~如果放置于Telecord官方安装目录,会由于权限问题无法正常使用。~~ 54 | > 55 | > ~~但是Yui项目使用的Telecord程序是直接解压exe的,所以没有权限问题。(将来会变更为使用临时文件目录的方法,以支持官方安装目录)~~ 56 | > 57 | > 目前已使用临时文件目录的方法,以支持官方安装目录。 58 | 59 | ### 如何看到日志 60 | 61 | 你可能会发现,项目里面用到了spdlog但是控制台没有日志输出。 62 | 那要怎么看到日志呢? 63 | 64 | 执行以下命令:`cmd.exe /C ".\\program\\IM.exe > output.log 2>&1"`,你就可以在output.log文件里面看到了。 65 | 66 | Q: 为什么不显示在控制台呢? 67 | 68 | A:我也想,不知道怎么弄。 69 | 70 | ## 功能实现 71 | 72 | - [x] 配置化映射 73 | - [x] 读取配置文件 74 | 75 | ## 声明 76 | 77 | 请勿用于非法用途 78 | 79 | 参考项目:https://github.com/LiteLoaderQQNT/QQNTFileVerifyPatch -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(MSVC) 2 | add_subdirectory(dbghelp) 3 | endif() 4 | add_subdirectory(fiddler) -------------------------------------------------------------------------------- /src/config/init.cc: -------------------------------------------------------------------------------- 1 | #include "../include/init.hh" 2 | #include 3 | 4 | #ifdef WIN32 5 | #include 6 | #include 7 | #elif defined(__linux__) || __APPLE__ 8 | #include 9 | #include 10 | #define MAX_PATH 255 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #if defined(__linux__) || __APPLE__ 20 | std::map config; 21 | #endif 22 | 23 | inline bool exists_test (const std::string& name) { 24 | #ifdef WIN32 25 | struct stat buffer; 26 | return (stat (name.c_str(), &buffer) == 0); 27 | #elif defined(__linux__) || __APPLE__ 28 | return !access(name.c_str(), F_OK); 29 | #endif 30 | } 31 | 32 | void load_configuration() 33 | { 34 | spdlog::info("configuration load start."); 35 | // Here, using a specialized Builder, we discard comments and 36 | // record errors as we parse. 37 | Json::CharReaderBuilder rbuilder; 38 | rbuilder["collectComments"] = false; 39 | Json::Value root; // 'root' will contain the root value after parsing. 40 | std::ifstream input("./patch.json", std::ios_base::in); 41 | if (input.is_open()) 42 | { 43 | std::string errs; 44 | bool ok = Json::parseFromStream(rbuilder, input, &root, &errs); 45 | if (!ok)return; 46 | 47 | if (root.isObject()) 48 | { 49 | std::map t; 50 | auto keys = root.getMemberNames(); 51 | for (auto& key : keys) { 52 | spdlog::info("key: {}", key); 53 | 54 | RedirectInfo info; 55 | auto item = root[key]; 56 | 57 | auto target = item["target"]; 58 | if (target.isString()) 59 | { 60 | info.target = target.asString(); 61 | } 62 | auto content = item["content"]; 63 | if (content.isString()) 64 | { 65 | info.content = content.asString(); 66 | } 67 | auto cur = item["cur"]; 68 | if (cur.isInt()) 69 | { 70 | info.cur = cur.asInt(); 71 | } 72 | auto start = item["start"]; 73 | if (start.isInt()) 74 | { 75 | info.start = start.asInt(); 76 | } 77 | auto end = item["end"]; 78 | if (end.isInt()) 79 | { 80 | info.end = end.asInt(); 81 | } 82 | std::filesystem::path p(key); 83 | if (p.is_relative()) 84 | { 85 | #ifdef WIN32 86 | char * cwd = _getcwd(NULL, 0); 87 | #elif defined(__linux__) || __APPLE__ 88 | char * cwd = getcwd(NULL, 0); 89 | #endif 90 | spdlog::info("resolve relative path: {}, cwd: {}", key.c_str(), cwd); 91 | auto p1 = std::filesystem::canonical(key); 92 | key = p1.string(); 93 | spdlog::info("absolute path: {}", key.c_str()); 94 | } 95 | spdlog::info("add"); 96 | config.emplace(key, info); 97 | spdlog::info("add ok"); 98 | } 99 | } 100 | } 101 | spdlog::info("configuration load completed."); 102 | 103 | } 104 | 105 | void create_default_file() 106 | { 107 | spdlog::info("default file create start."); 108 | char strTmpPath[MAX_PATH]; 109 | #ifdef WIN32 110 | GetTempPath(sizeof(strTmpPath), strTmpPath); 111 | #elif defined(__linux__) 112 | std::filesystem::path temp_dir = std::filesystem::temp_directory_path(); 113 | strcpy(strTmpPath, temp_dir.c_str()); 114 | #endif 115 | spdlog::info("temp path: {}", strTmpPath); 116 | 117 | spdlog::info("config size: {}", config.size()); 118 | for (auto& cfg: config) { 119 | auto& redirectData = cfg.second; 120 | std::filesystem::path p(redirectData.target); 121 | if (p.is_absolute()) 122 | { 123 | spdlog::info("absolute"); 124 | // 绝对路径 125 | if (exists_test(redirectData.target)) 126 | { 127 | continue; 128 | } 129 | std::ofstream fs(redirectData.target, std::ios_base::out); 130 | 131 | if (fs.is_open()) 132 | { 133 | fs.write(redirectData.content.c_str(), redirectData.content.length()); 134 | fs.flush(); 135 | fs.close(); 136 | } 137 | else { 138 | spdlog::error("[Absolute] Failed to open file: {}", redirectData.target); 139 | } 140 | 141 | } 142 | else 143 | { 144 | spdlog::info("relative: {}", redirectData.target); 145 | // 相对路径 146 | if (exists_test(redirectData.target)) 147 | { 148 | spdlog::info("exists skip"); 149 | continue; 150 | } 151 | std::ofstream fs(redirectData.target, std::ios_base::out); 152 | if (fs.is_open()) 153 | { 154 | fs.write(redirectData.content.c_str(), redirectData.content.length()); 155 | fs.flush(); 156 | fs.close(); 157 | } 158 | else { 159 | spdlog::warn("[Relative1] Failed to open file: {}", redirectData.target); 160 | std::filesystem::path t(strTmpPath); 161 | t.append(redirectData.target); 162 | redirectData.target = t.string(); 163 | if (exists_test(redirectData.target)) 164 | { 165 | spdlog::info("exists: {}", redirectData.target); 166 | continue; 167 | } 168 | std::ofstream fsn(redirectData.target, std::ios_base::out); 169 | if (fsn.is_open()) 170 | { 171 | fsn.write(redirectData.content.c_str(), redirectData.content.length()); 172 | fsn.flush(); 173 | fsn.close(); 174 | } 175 | else { 176 | spdlog::error("[Relative2] Failed to open file: {}", redirectData.target); 177 | } 178 | } 179 | } 180 | } 181 | spdlog::info("default file create completed."); 182 | } -------------------------------------------------------------------------------- /src/dbghelp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(dbghelp 3 | SHARED 4 | ./dbghelp.cc 5 | ../config/init.cc 6 | ../hook/hook.cc 7 | ) 8 | 9 | if(MSVC) 10 | target_link_libraries(dbghelp PRIVATE minhook::minhook) 11 | endif() 12 | target_link_libraries(dbghelp PRIVATE spdlog::spdlog) 13 | target_link_libraries(dbghelp PRIVATE JsonCpp::JsonCpp) 14 | 15 | set_target_properties(dbghelp PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 16 | # SET_TARGET_PROPERTIES(dbghelp PROPERTIES RUNTIME_OUTPUT_DIRECTORY "D:\\GitHub\\Yui\\program") -------------------------------------------------------------------------------- /src/dbghelp/dbghelp.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include "../include/hook.hh" 6 | #include "../include/init.hh" 7 | 8 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) 9 | { 10 | spdlog::info("DllMain !"); 11 | switch (fdwReason) 12 | { 13 | case DLL_PROCESS_ATTACH: 14 | { 15 | spdlog::info("DLL_PROCESS_ATTACH !"); 16 | load_configuration(); 17 | create_default_file(); 18 | start_hook(); 19 | break; 20 | } 21 | case DLL_THREAD_ATTACH: 22 | break; 23 | case DLL_THREAD_DETACH: 24 | break; 25 | case DLL_PROCESS_DETACH: 26 | break; 27 | } 28 | return TRUE; 29 | } 30 | 31 | 32 | extern "C" __declspec(dllexport) void MiniDumpWriteDump() {} 33 | extern "C" __declspec(dllexport) void StackWalk64() {} 34 | extern "C" __declspec(dllexport) void SymCleanup() {} 35 | extern "C" __declspec(dllexport) void SymFromAddr() {} 36 | extern "C" __declspec(dllexport) void SymFunctionTableAccess64() {} 37 | extern "C" __declspec(dllexport) void SymGetLineFromAddr64() {} 38 | extern "C" __declspec(dllexport) void SymGetModuleBase64() {} 39 | extern "C" __declspec(dllexport) void SymGetModuleInfo64() {} 40 | extern "C" __declspec(dllexport) void SymGetOptions() {} 41 | extern "C" __declspec(dllexport) void SymGetSymFromAddr64() {} 42 | extern "C" __declspec(dllexport) void SymGetSearchPathW() {} 43 | extern "C" __declspec(dllexport) void SymInitialize() {} 44 | extern "C" __declspec(dllexport) void SymSetOptions() {} 45 | extern "C" __declspec(dllexport) void SymSetSearchPathW() {} 46 | extern "C" __declspec(dllexport) void UnDecorateSymbolName() {} -------------------------------------------------------------------------------- /src/fiddler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if(MSVC) 3 | set(INFO_CHECK "../info_check.cc") 4 | set(MY_VERSIONINFO_RC "${CMAKE_BINARY_DIR}/libfiddler.rc") 5 | configure_file("./libfiddler.rc.in" 6 | "${MY_VERSIONINFO_RC}") 7 | endif() 8 | add_library(fiddler 9 | SHARED 10 | ./fiddler.cc 11 | ${INFO_CHECK} 12 | ${MY_VERSIONINFO_RC} 13 | ) 14 | 15 | target_link_libraries(fiddler PRIVATE spdlog::spdlog) 16 | 17 | set_target_properties(fiddler PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 18 | if(MSVC) 19 | set_target_properties(fiddler PROPERTIES PREFIX "" SUFFIX ".dll") 20 | elseif(APPLE) 21 | set_target_properties(fiddler PROPERTIES PREFIX "" SUFFIX ".dylib") 22 | elseif(UNIX) 23 | set_target_properties(fiddler PROPERTIES PREFIX "lib" SUFFIX ".so") 24 | endif() 25 | # SET_TARGET_PROPERTIES(fiddler PROPERTIES LIBRARY_OUTPUT_DIRECTORY "/home/msojocs/temp/squashfs-root") -------------------------------------------------------------------------------- /src/fiddler/fiddler.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #ifdef WIN32 4 | #include 5 | #include 6 | #include "../include/info_check.hh" 7 | #endif 8 | 9 | #ifdef WIN32 10 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) 11 | { 12 | if (fdwReason == DLL_PROCESS_ATTACH) 13 | { 14 | spdlog::info("libfiddler Dll main!"); 15 | // info_check("libfiddler.dll", "b7a70b0ac3884c4f5c15dffc5d90b8e6"); 16 | } 17 | return TRUE; 18 | } 19 | 20 | 21 | extern "C" __declspec(dllexport) void initialize() { 22 | 23 | } 24 | extern "C" __declspec(dllexport) void f() { 25 | 26 | } 27 | #endif 28 | 29 | #if defined(__linux__) || __APPLE__ 30 | extern "C" { 31 | void initialize() { 32 | spdlog::info("libfiddler initialize"); 33 | } 34 | void f() { 35 | spdlog::info("libfiddler f"); 36 | } 37 | } 38 | #endif -------------------------------------------------------------------------------- /src/fiddler/libfiddler.rc.in: -------------------------------------------------------------------------------- 1 | #pragma code_page(65001) 2 | 1 VERSIONINFO 3 | FILEVERSION ${PROJECT_VERSION_MAJOR}, ${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH} 4 | PRODUCTVERSION ${PROJECT_VERSION_MAJOR}, ${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH} 5 | FILEFLAGSMASK 0x17L 6 | #ifdef _DEBUG 7 | FILEFLAGS 0x1L 8 | #else 9 | FILEFLAGS 0x0L 10 | #endif 11 | FILEOS 0x4L 12 | FILETYPE 0x0L 13 | FILESUBTYPE 0x0L 14 | BEGIN 15 | BLOCK "StringFileInfo" 16 | BEGIN 17 | BLOCK "040904b0" 18 | BEGIN 19 | VALUE "FileDescription", "libfiddler免费free github.com/msojocs" 20 | VALUE "FileVersion", "${PROJECT_VERSION_MAJOR}, ${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH}" 21 | VALUE "InternalName", "libfiddler" 22 | VALUE "LegalCopyright", "Copyright (C) 2024" 23 | VALUE "OriginalFilename", "" 24 | VALUE "ProductName", "libfiddler劫持 免费free" 25 | VALUE "ProductVersion", "${PROJECT_VERSION_MAJOR}, ${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH}" 26 | END 27 | END 28 | BLOCK "VarFileInfo" 29 | BEGIN 30 | VALUE "Translation", 0x409, 1200 31 | END 32 | END -------------------------------------------------------------------------------- /src/hook/hook.cc: -------------------------------------------------------------------------------- 1 | #include "Minhook.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../include/nt.hh" 10 | #include "../include/hook.hh" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "../include/redirect.hh" 19 | 20 | 21 | static def_CreateFileW Org_CreateFileW = NULL; 22 | static def_ReadFile Org_ReadFile = NULL; 23 | 24 | std::map config; 25 | // = { 26 | // { 27 | // std::string("program\\resources\\app\\app_launcher\\index.js"), 28 | // { 29 | // std::string("index.js"), 30 | // "require('./launcher.node').load('external_index', module);", 31 | // 0, 0, 1 32 | // } 33 | // }, 34 | // }; 35 | 36 | HANDLE WINAPI Hk_CreateFileW( 37 | _In_ LPCWSTR lpFileName, 38 | _In_ DWORD dwDesiredAccess, 39 | _In_ DWORD dwShareMode, 40 | _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, 41 | _In_ DWORD dwCreationDisposition, 42 | _In_ DWORD dwFlagsAndAttributes, 43 | _In_opt_ HANDLE hTemplateFile 44 | ) { 45 | char path[MAX_PATH]; 46 | size_t len; 47 | wcstombs_s(&len, path, MAX_PATH, lpFileName, wcslen(lpFileName)); 48 | std::string filename(path, len); 49 | spdlog::info("full filename: {}", filename.c_str()); 50 | 51 | std::filesystem::path p(filename); 52 | 53 | if (p.is_absolute()) 54 | { 55 | // 绝对路径 56 | if (filename.find("\\\\?\\") == 0) { 57 | filename.replace(0, 4, ""); 58 | } 59 | if ('a' <= filename[0] && filename[0] <= 'z') 60 | { 61 | filename[0] = 'A' + filename[0] - 'a'; 62 | } 63 | spdlog::info("Absolute path: {}", filename.c_str()); 64 | } 65 | 66 | if (config.find(filename.c_str()) != config.end()) 67 | { 68 | spdlog::info("File config was found: {}", filename); 69 | auto directData = config[filename.c_str()]; 70 | if (directData.cur >= directData.start && directData.cur < directData.end) 71 | { 72 | spdlog::info("{} Redirect for: {}", directData.cur, filename); 73 | // 文件名 74 | 75 | const char *strTmpPath = directData.target.c_str(); 76 | spdlog::info("{} Redirect to: {}", directData.cur, strTmpPath); 77 | directData.cur++; 78 | 79 | int cap = (strlen(strTmpPath) + 1) * sizeof(wchar_t); 80 | wchar_t *defaultIndex = (wchar_t *)malloc(cap); 81 | size_t retlen = 0; 82 | 83 | errno_t err = mbstowcs_s(&retlen, defaultIndex, cap / sizeof(wchar_t), strTmpPath, _TRUNCATE); 84 | 85 | config[filename.c_str()] = directData; 86 | if (err == 0) { 87 | HANDLE ret = Org_CreateFileW(defaultIndex, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 88 | free(defaultIndex); 89 | return ret; 90 | } 91 | 92 | // BOOL readResult = ReadFile(ret, msg, 20, NULL, NULL); 93 | spdlog::info("read result: {}\n", err); 94 | // 释放 95 | free(defaultIndex); 96 | } 97 | else { 98 | spdlog::info("skip target: {}, cur: {}, start: {}, end: {}", directData.target, directData.cur, directData.start, directData.end); 99 | directData.cur++; 100 | config[filename.c_str()] = directData; 101 | } 102 | 103 | } 104 | else { 105 | spdlog::info("Can not find file config: {}", filename.c_str()); 106 | } 107 | 108 | return Org_CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 109 | } 110 | 111 | 112 | BOOL WINAPI Hk_ReadFile( 113 | _In_ HANDLE hFile, 114 | _Out_ LPVOID lpBuffer, 115 | _In_ DWORD nNumberOfBytesToRead, 116 | _Out_opt_ LPDWORD lpNumberOfBytesRead, 117 | _In_opt_ LPOVERLAPPED lpOverlapped 118 | ) { 119 | return Org_ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); 120 | } 121 | 122 | 123 | void start_hook() { 124 | spdlog::info("hook init"); 125 | if (MH_Initialize() != MH_OK) { 126 | MessageBoxA(nullptr, "MH Init Error!", "ERROR", MB_ICONERROR | MB_OK); 127 | exit(1); 128 | } 129 | spdlog::info("hook create"); 130 | if (MH_CreateHook(&CreateFileW, &Hk_CreateFileW, reinterpret_cast(&Org_CreateFileW)) != MH_OK) { 131 | MessageBoxA(nullptr, "MH Hook CreateFileW failed!", "ERROR", MB_ICONERROR | MB_OK); 132 | exit(1); 133 | } 134 | // if (MH_CreateHook(&ReadFile, &Hk_ReadFile, reinterpret_cast(&Org_ReadFile)) != MH_OK) { 135 | // MessageBoxA(nullptr, "MH Hook CreateFileW failed!", "ERROR", MB_ICONERROR | MB_OK); 136 | // exit(1); 137 | // } 138 | 139 | spdlog::info("hook enable"); 140 | if (MH_EnableHook(MH_ALL_HOOKS) != MH_OK) { 141 | MessageBoxA(nullptr, "MH enable all hooks failed!", "ERROR", MB_ICONERROR | MB_OK); 142 | exit(1); 143 | } 144 | spdlog::info("hook done"); 145 | } -------------------------------------------------------------------------------- /src/include/const.hh: -------------------------------------------------------------------------------- 1 | #ifndef __CONST_HH__ 2 | #define __CONST_HH__ 3 | 4 | // #define DEFAULT_INDEX "index.default.js" 5 | 6 | #endif -------------------------------------------------------------------------------- /src/include/hook.hh: -------------------------------------------------------------------------------- 1 | #ifndef __HOOK_H__ 2 | #define __HOOK_H__ 3 | #include 4 | HANDLE WINAPI Hk_CreateFileW( 5 | _In_ LPCWSTR lpFileName, 6 | _In_ DWORD dwDesiredAccess, 7 | _In_ DWORD dwShareMode, 8 | _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, 9 | _In_ DWORD dwCreationDisposition, 10 | _In_ DWORD dwFlagsAndAttributes, 11 | _In_opt_ HANDLE hTemplateFile 12 | ); 13 | BOOL WINAPI Hk_ReadFile( 14 | _In_ HANDLE hFile, 15 | _Out_ LPVOID lpBuffer, 16 | _In_ DWORD nNumberOfBytesToRead, 17 | _Out_opt_ LPDWORD lpNumberOfBytesRead, 18 | _In_opt_ LPOVERLAPPED lpOverlapped 19 | ); 20 | void start_hook(); 21 | 22 | #endif -------------------------------------------------------------------------------- /src/include/info_check.hh: -------------------------------------------------------------------------------- 1 | #ifndef __INFO_CHECK_HH__ 2 | #define __INFO_CHECK_HH__ 3 | void info_check(const char*, const char *); 4 | #endif -------------------------------------------------------------------------------- /src/include/init.hh: -------------------------------------------------------------------------------- 1 | #ifndef __INIT_HH__ 2 | #define __INIT_HH__ 3 | #include 4 | #include 5 | #include "redirect.hh" 6 | 7 | extern std::map config; 8 | 9 | void load_configuration(); 10 | 11 | void create_default_file(); 12 | 13 | #endif -------------------------------------------------------------------------------- /src/include/nt.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef HANDLE(WINAPI* def_CreateFileW)( 6 | _In_ LPCWSTR lpFileName, 7 | _In_ DWORD dwDesiredAccess, 8 | _In_ DWORD dwShareMode, 9 | _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, 10 | _In_ DWORD dwCreationDisposition, 11 | _In_ DWORD dwFlagsAndAttributes, 12 | _In_opt_ HANDLE hTemplateFile 13 | ); 14 | 15 | typedef BOOL(WINAPI* def_ReadFile)( 16 | _In_ HANDLE hFile, 17 | _Out_ LPVOID lpBuffer, 18 | _In_ DWORD nNumberOfBytesToRead, 19 | _Out_opt_ LPDWORD lpNumberOfBytesRead, 20 | _In_opt_ LPOVERLAPPED lpOverlapped 21 | ); 22 | 23 | typedef DWORD(WINAPI* def_GetFileSize)( 24 | _In_ HANDLE hFile, 25 | _Out_opt_ LPDWORD lpFileSizeHigh 26 | ); -------------------------------------------------------------------------------- /src/include/redirect.hh: -------------------------------------------------------------------------------- 1 | #ifndef __REDIRECT_HH__ 2 | #define __REDIRECT_HH__ 3 | #include 4 | 5 | struct RedirectInfo { 6 | /** 7 | * @brief 转发的目标文件 8 | * 9 | */ 10 | std::string target; 11 | /** 12 | * @brief 文件的内容 13 | * 14 | * 如果目标文件不存在,将会使用此数据创建文件。 15 | * 16 | */ 17 | std::string content; 18 | int cur = 0; 19 | /** 20 | * @brief 开始点 21 | * 22 | * 区间范围:[start, end) 23 | * 24 | */ 25 | int start; 26 | int end; 27 | }; 28 | 29 | #endif -------------------------------------------------------------------------------- /src/info_check.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #pragma comment(lib, "version.lib") 13 | #pragma comment(lib, "crypt32.lib") 14 | 15 | 16 | std::wstring GetVersionInfo(HMODULE hModule, const std::wstring& infoType) 17 | { 18 | // 获取模块文件路径 19 | WCHAR path[MAX_PATH]; 20 | GetModuleFileNameW(hModule, path, MAX_PATH); 21 | 22 | // 获取版本信息大小 23 | DWORD handle = 0; 24 | DWORD size = GetFileVersionInfoSizeW(path, &handle); 25 | if (size == 0) { 26 | return L""; 27 | } 28 | 29 | // 分配缓冲区并获取版本信息 30 | std::vector buffer(size); 31 | if (!GetFileVersionInfoW(path, handle, size, buffer.data())) { 32 | return L""; 33 | } 34 | 35 | // 获取指定的版本信息 36 | LPVOID value = nullptr; 37 | UINT len = 0; 38 | std::wstring query = L"\\StringFileInfo\\040904b0\\" + infoType; 39 | if (VerQueryValueW(buffer.data(), query.c_str(), &value, &len) && value) { 40 | return std::wstring(reinterpret_cast(value)); 41 | } 42 | 43 | return L""; 44 | } 45 | 46 | #define MD5LEN 33 47 | std::string CalculateMD5(const std::string& input) { 48 | HCRYPTPROV hProv = 0; 49 | HCRYPTHASH hHash = 0; 50 | BYTE hash[MD5LEN]; 51 | DWORD hashLen = MD5LEN; 52 | std::stringstream ss; 53 | 54 | if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 55 | spdlog::error("CryptAcquireContext failed: {}", GetLastError()); 56 | return ""; 57 | } 58 | 59 | if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { 60 | spdlog::error("CryptCreateHash failed: {}", GetLastError()); 61 | CryptReleaseContext(hProv, 0); 62 | return ""; 63 | } 64 | 65 | if (!CryptHashData(hHash, reinterpret_cast(input.c_str()), input.length(), 0)) { 66 | spdlog::error("CryptHashData failed: ", GetLastError()); 67 | CryptDestroyHash(hHash); 68 | CryptReleaseContext(hProv, 0); 69 | return ""; 70 | } 71 | 72 | if (!CryptGetHashParam(hHash, HP_HASHVAL, hash, &hashLen, 0)) { 73 | spdlog::error("CryptGetHashParam failed: ", GetLastError()); 74 | CryptDestroyHash(hHash); 75 | CryptReleaseContext(hProv, 0); 76 | return ""; 77 | } 78 | 79 | for (DWORD i = 0; i < hashLen; i++) { 80 | ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(hash[i]); 81 | } 82 | 83 | CryptDestroyHash(hHash); 84 | CryptReleaseContext(hProv, 0); 85 | 86 | return ss.str(); 87 | } 88 | 89 | void info_check(const char* name, const char* result) 90 | { 91 | return; 92 | spdlog::info("info_check"); 93 | // 使用示例 94 | HMODULE hModule = GetModuleHandleA(name); // 替换为你的DLL名称 95 | std::wstring fileDescription = GetVersionInfo(hModule, L"FileDescription"); 96 | std::wstring fileVersion = GetVersionInfo(hModule, L"FileVersion"); 97 | std::wstring productVersion = GetVersionInfo(hModule, L"ProductVersion"); 98 | std::wstring productName = GetVersionInfo(hModule, L"ProductName"); 99 | std::wstring t = fileDescription + productName + fileVersion + productVersion; 100 | char *temp = (char *)malloc(sizeof(char) * t.length() * 2); 101 | memset(temp, 0, sizeof(char) * t.length() * 2); 102 | int ret = WideCharToMultiByte(65001, 0, t.c_str(), t.length(), temp, t.length() * 2, "\0", 0); 103 | if (ret >= 0) 104 | { 105 | spdlog::info("length: {}, data: {}",t.length(), temp); 106 | } 107 | 108 | std::vector hash; 109 | std::string data = temp + std::string("msojocs->fshefiy"); 110 | free(temp); 111 | std::string md5 = CalculateMD5(data); 112 | md5 = CalculateMD5(md5 + "msojocs->ytdfchg"); 113 | md5 = CalculateMD5(md5 + "msojocs->juguyft"); 114 | 115 | if (md5 != result) 116 | { 117 | spdlog::info("md5: {}", md5.c_str()); 118 | exit(-1); 119 | } 120 | spdlog::info("info_check done"); 121 | } -------------------------------------------------------------------------------- /src/test/read.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-yui/Yui-patch/ca44cfa6d2c12226e7f50504458de1b9c3f2734c/src/test/read.cc -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(UNIX) 2 | add_executable(test_fiddler 3 | ./fiddler.cc 4 | ) 5 | set_target_properties(test_fiddler PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 6 | target_link_libraries(test_fiddler PUBLIC dl) 7 | endif() -------------------------------------------------------------------------------- /test/fiddler.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef void (*cosf_method_type)(); 4 | int main(void) 5 | { 6 | printf("fiddler test start....\n"); 7 | void * libm_handle = NULL; 8 | void (*cosf_method)(); 9 | char *errorInfo; 10 | float result; 11 | 12 | // dlopen 函数还会自动解析共享库中的依赖项。这样,如果您打开了一个依赖于其他共享库的对象,它就会自动加载它们。 13 | // 函数返回一个句柄,该句柄用于后续的 API 调用 14 | libm_handle = dlopen("../libfiddler.so", RTLD_LAZY ); 15 | // 如果返回 NULL 句柄,表示无法找到对象文件,过程结束。否则的话,将会得到对象的一个句柄,可以进一步询问对象 16 | if (!libm_handle){ 17 | // 如果返回 NULL 句柄,通过dlerror方法可以取得无法访问对象的原因 18 | printf("Open Error:%s.\n",dlerror()); 19 | return 0; 20 | } 21 | 22 | // 使用 dlsym 函数,尝试解析新打开的对象文件中的符号。您将会得到一个有效的指向该符号的指针,或者是得到一个 NULL 并返回一个错误 23 | cosf_method = (cosf_method_type)dlsym(libm_handle, "initialize"); 24 | errorInfo = dlerror();// 调用dlerror方法,返回错误信息的同时,内存中的错误信息被清空 25 | if (errorInfo != NULL){ 26 | printf("Dlsym Error:%s.\n",errorInfo); 27 | return 0; 28 | } 29 | 30 | // 执行“cosf”方法 31 | (*cosf_method)(); 32 | printf("result = %f.\n",result); 33 | 34 | // 调用 ELF 对象中的目标函数后,通过调用 dlclose 来关闭对它的访问 35 | dlclose(libm_handle); 36 | 37 | return 0; 38 | } -------------------------------------------------------------------------------- /tools/linux/ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | root_dir=$(cd `dirname $0`/../.. && pwd -P) 4 | 5 | arch=$1 6 | tag=$2 7 | 8 | cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -S"$root_dir" -B"$root_dir/build" -G Ninja 9 | cmake --build "$root_dir/build" --config Release --target all -- 10 | 11 | mkdir -p "$root_dir/tmp/build" 12 | 13 | for file in "$root_dir/build/"*.so 14 | do 15 | name=$(basename $file) 16 | mv $file "$root_dir/tmp/build/yui-${name%.*}-linux-$arch-$tag.so" 17 | done -------------------------------------------------------------------------------- /tools/mac/ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | root_dir=$(cd `dirname $0`/../.. && pwd -P) 4 | 5 | arch=$1 6 | tag=$2 7 | 8 | cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -S"$root_dir" -B"$root_dir/build" -G Ninja 9 | cmake --build "$root_dir/build" --config Release --target all -- 10 | 11 | mkdir -p "$root_dir/tmp/build" 12 | 13 | for file in "$root_dir/build/"*.dylib 14 | do 15 | name=$(basename $file) 16 | mv $file "$root_dir/tmp/build/yui-${name%.*}-mac-$arch-$tag.dylib" 17 | done -------------------------------------------------------------------------------- /tools/prepare-arm64e.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | 4 | const p = path.resolve(__dirname, '../vcpkg-configuration.json') 5 | const cfg = JSON.parse(fs.readFileSync(p).toString()) 6 | cfg['default-registry'].repository = 'https://github.com/msojocs/vcpkg' 7 | cfg['default-registry'].baseline = '47a484f679d92ce89f551d0e026adf291b9fc336' 8 | 9 | fs.writeFileSync(p, JSON.stringify(cfg, null, 4)) 10 | -------------------------------------------------------------------------------- /tools/windows/ci.ps1: -------------------------------------------------------------------------------- 1 | param($arch, $tag) 2 | $root_dir = Resolve-Path (Join-Path $PSScriptRoot "../../") 3 | 4 | cd $root_dir 5 | try 6 | { 7 | cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -S"$root_dir" -B"$root_dir/build" -G Ninja 8 | cmake --build "$root_dir/build" --config Release --target all -- 9 | mkdir "$root_dir/tmp/build" 10 | Write-Host "$root_dir/build" 11 | Get-ChildItem -Path "$root_dir/build/" -Filter "*.dll" -Recurse | ForEach-Object { 12 | try{ 13 | # 对每个文件执行操作,例如输出文件名 14 | $Name = $_.BaseName 15 | $FullName = $_.FullName 16 | Write-Host $FullName 17 | mv "$FullName" "$root_dir/tmp/build/yui-$Name-win32-$arch-$tag.dll" 18 | }catch{ 19 | Write-Host $_ 20 | } 21 | } 22 | }catch{ 23 | exit 1 24 | } -------------------------------------------------------------------------------- /vcpkg-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "default-registry": { 3 | "kind": "git", 4 | "baseline": "0719a71389654b88d827501d88e37e58ea8cbd70", 5 | "repository": "https://github.com/microsoft/vcpkg" 6 | }, 7 | "registries": [ 8 | { 9 | "kind": "artifact", 10 | "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", 11 | "name": "microsoft" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | { 4 | "name": "minhook", 5 | "platform": "windows" 6 | }, 7 | "spdlog", 8 | "jsoncpp" 9 | ] 10 | } 11 | --------------------------------------------------------------------------------