├── .github └── workflows │ └── build.yml ├── .gitignore ├── LICENSE ├── README.md ├── hook.js └── license-gen ├── Cargo.lock ├── Cargo.toml └── src └── main.rs /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: 3 | workflow_dispatch: {} 4 | jobs: 5 | build: 6 | name: build 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | build: [linux, windows] 11 | include: 12 | - build: linux 13 | os: ubuntu-latest 14 | rust: nightly 15 | target: x86_64-unknown-linux-musl 16 | archive-name: NodeInject-linux.tar.gz 17 | - build: windows 18 | os: windows-2019 19 | rust: nightly-x86_64-msvc 20 | target: x86_64-pc-windows-msvc 21 | archive-name: NodeInject-windows.7z 22 | fail-fast: false 23 | 24 | steps: 25 | - name: Checkout NodeInject 26 | uses: actions/checkout@v4 27 | with: 28 | repository: DiamondHunters/NodeInject 29 | - name: Checkout repository 30 | uses: actions/checkout@v4 31 | with: 32 | path: './js' 33 | - name: Install Rust 34 | uses: actions-rs/toolchain@v1 35 | with: 36 | toolchain: ${{ matrix.rust }} 37 | profile: minimal 38 | override: true 39 | target: ${{ matrix.target }} 40 | 41 | - name: Build binary 42 | shell: bash 43 | run: | 44 | cp -f ./js/hook.js ./src/hooklog.js 45 | cargo build --verbose --release --target ${{ matrix.target }} 46 | cd ./js/license-gen 47 | cargo build --verbose --release --target ${{ matrix.target }} 48 | cd ../.. 49 | env: 50 | RUST_BACKTRACE: 1 51 | 52 | - name: Build archive 53 | shell: bash 54 | run: | 55 | mkdir archive 56 | cp LICENSE README.md archive/ 57 | ls -lR 58 | if [ "${{ matrix.build }}" = "windows" ]; then 59 | cp "./target/${{ matrix.target }}/release/node_inject.exe" ./archive/ 60 | cp "./js/license-gen/target/${{ matrix.target }}/release/license-gen.exe" ./archive/ 61 | cd archive 62 | 7z a "${{ matrix.archive-name }}" LICENSE README.md node_inject.exe license-gen.exe 63 | else 64 | cp "./target/${{ matrix.target }}/release/node_inject" ./archive/ 65 | cp "./js/license-gen/target/${{ matrix.target }}/release/license-gen" ./archive/ 66 | cd archive 67 | tar -czf "${{ matrix.archive-name }}" LICENSE README.md node_inject license-gen 68 | fi 69 | - name: Upload archive 70 | uses: actions/upload-artifact@v4 71 | with: 72 | name: ${{ matrix.archive-name }} 73 | path: archive/${{ matrix.archive-name }} 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /license-gen/target/ 2 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 DiamondHunters 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NodeInject_Hook_example 2 | A hooking example for NodeInject 3 | 4 | ## About `hook.js` 5 | 6 | #### WARNING 7 | 8 | JUST FOR LEARNING! 9 | 10 | **PLEASE DO NOT ABUSE THIS SCRIPT CAPABILITY FOR THE PURPOSE OF INFRINGEMENT, AND YOU SHALL BEAR ALL CONSEQUENCES CAUSED BY YOUR ACTIONS.** 11 | 12 | 13 | #### Usage 14 | 15 | 1. `git clone https://github.com/DiamondHunters/NodeInject.git` 16 | 2. Replace `hooklog.js` with `hook.js` in this repo (or use `no_embed` feature and set `NO_EMBED_HOOK_JS_PATH` to the path of `hook.js`) 17 | 3. Run `cargo build` or `cargo build --features no_embed` to build a type of executable (If you enabled `no_embed` feature, you need to copy `hook.js` to the same directory of executable) 18 | 4. Run the executable 19 | 20 | If you need a fake license, you can run `cargo run` in `license-gen` directory 21 | 22 | This fake license is not valid and just used for **testing**. Please do not use it for any other purpose. 23 | 24 | #### Ability 25 | 26 | - [x] make typora to activate with the generated activation code (Test passed in version 1.5.8 on Windows,1.4.7 on Ubuntu) 27 | - [x] hook `console.log` to remote http server and block override 28 | - [x] hook `electron-fetch` for sniffing request 29 | - [ ] Full version compatibility (older version not using `electron-fetch` and may fail in the future) 30 | - [ ] Multi os compatibility (not work in macOS) 31 | -------------------------------------------------------------------------------- /hook.js: -------------------------------------------------------------------------------- 1 | //this file is a little example of how to use injecting ability 2 | //to hook a function and change its behavior 3 | //in this case we hook the function that is responsible for the decryption of the license 4 | //and we change the behavior to return a valid license 5 | 6 | // JUST FOR LEARNING PURPOSES, DON'T USE THIS TO CRACK SOFTWARE 7 | 8 | //Adding hook 9 | const crypto = require("crypto"); 10 | const pubdec = crypto["publicDecrypt"]; 11 | delete crypto["publicDecrypt"]; 12 | let fingerprint, email, uuid, license, computerInfo = ""; 13 | let License = "" 14 | crypto.publicDecrypt = function (key, buffer) { 15 | log("PubDec Key:" + key); 16 | log("buf: " + buffer.toString('base64')); 17 | if (buffer.slice(0, 26).compare(Buffer.from("CRACKED_BY_DIAMOND_HUNTERS")) == 0) { 18 | License = buffer.toString('base64'); 19 | let ret = buffer.toString().replace("CRACKED_BY_DIAMOND_HUNTERS", ""); 20 | log("backdoor data,return : " + ret); 21 | return Buffer.from(ret); 22 | } 23 | return pubdec(key, buffer); 24 | }; 25 | 26 | const fetch = require("electron-fetch") 27 | fetch_bak = fetch['default']; 28 | delete fetch['default']; 29 | fetch.default = async function fetch(url, options) { 30 | log('[fetch]fetch ' + url); 31 | log('[fetch]Arg ' + JSON.stringify(options)); 32 | data = await fetch_bak(url, options); 33 | if (url.indexOf('api/client/activate') != -1) { 34 | params = JSON.parse(options.body); 35 | fingerprint = params.f, email = params.email, uuid = params.u, license = params.license, computerInfo = params.l 36 | log('[activate]Fingerprint ' + fingerprint); 37 | log('[activate]Email ' + email); 38 | log('[activate]UUID ' + uuid); 39 | log('[activate]License ' + license); 40 | log('[activate]ComputerInfo ' + computerInfo); 41 | log('[fetch]RetCode ' + data.status); 42 | ret = await data.buffer(); 43 | log('[fetch]Ret ' + ret.toString()); 44 | 45 | ret = Buffer.from('{"code":0,"retry":true,"msg":"' + Buffer.from("CRACKED_BY_DIAMOND_HUNTERS" + JSON.stringify( 46 | { 47 | "fingerprint": fingerprint, 48 | "email": email, 49 | "license": license, 50 | "type": "" 51 | })).toString('base64') + '"}'); 52 | log("replace ret: " + ret.toString()); 53 | data.text = () => { 54 | return new Promise((resolve, reject) => { 55 | resolve(ret.toString()); 56 | }); 57 | }; 58 | data.json = () => { 59 | return new Promise((resolve, reject) => { 60 | resolve(JSON.parse(ret.toString())); 61 | }); 62 | }; 63 | } 64 | if (url.indexOf('api/client/renew') != -1) { 65 | ret = await data.buffer(); 66 | log('[fetch]Ret ' + ret.toString()); 67 | 68 | ret = Buffer.from('{"success":true,"code":0,"retry":true,"msg":"' + License + '"}'); 69 | log("replace ret: " + ret.toString()); 70 | data.text = () => { 71 | return new Promise((resolve, reject) => { 72 | resolve(ret.toString()); 73 | }); 74 | }; 75 | data.json = () => { 76 | return new Promise((resolve, reject) => { 77 | resolve(JSON.parse(ret.toString())); 78 | }); 79 | }; 80 | } 81 | return new Promise((resolve, reject) => { 82 | resolve(data); 83 | }); 84 | 85 | } 86 | 87 | http = require("http") 88 | 89 | function log(str) { 90 | http.get('http://127.0.0.1:3000/log?str=' + str, res => { 91 | }).on('error', err => { 92 | console.log('Error: ', err.message); 93 | }); 94 | } 95 | 96 | log = console.log; 97 | log('Hook Init') 98 | 99 | 100 | var Module = require('module'); 101 | var originalRequire = Module.prototype.require; 102 | 103 | Module.prototype.require = function () { 104 | log('Require ' + arguments[0]) 105 | if (arguments[0] == 'crypto') { 106 | log('Hooking crypto'); 107 | return crypto; 108 | } 109 | if (arguments[0] == 'electron-fetch') { 110 | log('Hooking electron-fetch'); 111 | return fetch; 112 | } 113 | return originalRequire.apply(this, arguments); 114 | }; 115 | 116 | 117 | console.log = log 118 | let validator = { 119 | set: function (target, key, value) { 120 | if (key === 'log') { 121 | log('console.log override blocked'); 122 | return; 123 | } 124 | target[key] = value; 125 | } 126 | } 127 | 128 | let proxy = new Proxy(console, validator); 129 | console = proxy 130 | module.exports = fetch 131 | 132 | //hook finished -------------------------------------------------------------------------------- /license-gen/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "cfg-if" 7 | version = "1.0.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 10 | 11 | [[package]] 12 | name = "fastrand" 13 | version = "1.8.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" 16 | dependencies = [ 17 | "instant", 18 | ] 19 | 20 | [[package]] 21 | name = "instant" 22 | version = "0.1.12" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 25 | dependencies = [ 26 | "cfg-if", 27 | ] 28 | 29 | [[package]] 30 | name = "license-gen" 31 | version = "0.1.0" 32 | dependencies = [ 33 | "random-string", 34 | ] 35 | 36 | [[package]] 37 | name = "random-string" 38 | version = "1.0.0" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "cf4e63111ec5292d8af9c220f06fe3bb87991cc78b6f1f7e291d1ae6b8a60817" 41 | dependencies = [ 42 | "fastrand", 43 | ] 44 | -------------------------------------------------------------------------------- /license-gen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "license-gen" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | random-string = "1.0" -------------------------------------------------------------------------------- /license-gen/src/main.rs: -------------------------------------------------------------------------------- 1 | use random_string::generate; 2 | 3 | const LICENSE_CHARS: &str = "L23456789ABCDEFGHJKMNPQRSTUVWXYZ"; 4 | fn main() { 5 | generate_license(); 6 | } 7 | 8 | fn generate_license(){ 9 | let mut license = generate(22, LICENSE_CHARS); 10 | for n in 0..2 { 11 | let mut o = 0; 12 | for i in (0..16).step_by(2) { 13 | o += LICENSE_CHARS.find(&license[n+i..=n+i]).unwrap() 14 | } 15 | o %= LICENSE_CHARS.len(); 16 | license += &LICENSE_CHARS[o..=o]; 17 | } 18 | license.insert(6, '-'); 19 | license.insert(13, '-'); 20 | license.insert(20, '-'); 21 | println!("License for you: {}", license); 22 | } 23 | 24 | --------------------------------------------------------------------------------