Typora 序列号造假

生成假的typora序列号

事情的起因是因为我之前一直用的是法海之路的激活插件但是老哥把所有关于破解的文章全部删除了 没办法还是自己手动破解一波吧 有能力还是建议支持正版

注意: 该项目只适用于Typora v1.10.8以下版本 仅用于学习,请支持正版

本地生成

1. 下载NodeInject 源码

1
git clone https://github.com/DiamondHunters/NodeInject.git

编辑hooklog.js 配置文件,修改为以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//this file is a little example of how to use injecting ability
//to hook a function and change its behavior
//in this case we hook the function that is responsible for the decryption of the license
//and we change the behavior to return a valid license

// JUST FOR LEARNING PURPOSES, DON'T USE THIS TO CRACK SOFTWARE

//Adding hook
const crypto = require("crypto");
const pubdec = crypto["publicDecrypt"];
delete crypto["publicDecrypt"];
let fingerprint, email, uuid, license, computerInfo = "";
let License = ""
crypto.publicDecrypt = function (key, buffer) {
log("PubDec Key:" + key);
log("buf: " + buffer.toString('base64'));
if (buffer.slice(0, 26).compare(Buffer.from("CRACKED_BY_DIAMOND_HUNTERS")) == 0) {
License = buffer.toString('base64');
let ret = buffer.toString().replace("CRACKED_BY_DIAMOND_HUNTERS", "");
log("backdoor data,return : " + ret);
return Buffer.from(ret);
}
return pubdec(key, buffer);
};

const fetch = require("electron-fetch")
fetch_bak = fetch['default'];
delete fetch['default'];
fetch.default = async function fetch(url, options) {
log('[fetch]fetch ' + url);
log('[fetch]Arg ' + JSON.stringify(options));
data = await fetch_bak(url, options);
if (url.indexOf('api/client/activate') != -1) {
params = JSON.parse(options.body);
fingerprint = params.f, email = params.email, uuid = params.u, license = params.license, computerInfo = params.l
log('[activate]Fingerprint ' + fingerprint);
log('[activate]Email ' + email);
log('[activate]UUID ' + uuid);
log('[activate]License ' + license);
log('[activate]ComputerInfo ' + computerInfo);
log('[fetch]RetCode ' + data.status);
ret = await data.buffer();
log('[fetch]Ret ' + ret.toString());

ret = Buffer.from('{"code":0,"retry":true,"msg":"' + Buffer.from("CRACKED_BY_DIAMOND_HUNTERS" + JSON.stringify(
{
"fingerprint": fingerprint,
"email": email,
"license": license,
"type": ""
})).toString('base64') + '"}');
log("replace ret: " + ret.toString());
data.text = () => {
return new Promise((resolve, reject) => {
resolve(ret.toString());
});
};
data.json = () => {
return new Promise((resolve, reject) => {
resolve(JSON.parse(ret.toString()));
});
};
}
if (url.indexOf('api/client/renew') != -1) {
ret = await data.buffer();
log('[fetch]Ret ' + ret.toString());

ret = Buffer.from('{"success":true,"code":0,"retry":true,"msg":"' + License + '"}');
log("replace ret: " + ret.toString());
data.text = () => {
return new Promise((resolve, reject) => {
resolve(ret.toString());
});
};
data.json = () => {
return new Promise((resolve, reject) => {
resolve(JSON.parse(ret.toString()));
});
};
}
return new Promise((resolve, reject) => {
resolve(data);
});

}

http = require("http")

function log(str) {
http.get('http://127.0.0.1:3000/log?str=' + str, res => {
}).on('error', err => {
console.log('Error: ', err.message);
});
}

log = console.log;
log('Hook Init')


var Module = require('module');
var originalRequire = Module.prototype.require;

Module.prototype.require = function () {
log('Require ' + arguments[0])
if (arguments[0] == 'crypto') {
log('Hooking crypto');
return crypto;
}
if (arguments[0] == 'electron-fetch') {
log('Hooking electron-fetch');
return fetch;
}
return originalRequire.apply(this, arguments);
};


console.log = log
let validator = {
set: function (target, key, value) {
if (key === 'log') {
log('console.log override blocked');
return;
}
target[key] = value;
}
}

let proxy = new Proxy(console, validator);
console = proxy
module.exports = fetch

//hook finished

2. 激活码生成脚本

由于存在滥用原有hook激活部分已被删除,在上方的项目,新建一个 license-gen 按照以下目录树

1
2
3
4
5
6

Cargo.lock
Cargo.toml

└─src
main.rs

cargo.lock

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3

[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

[[package]]
name = "fastrand"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
dependencies = [
"instant",
]

[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]

[[package]]
name = "license-gen"
version = "0.1.0"
dependencies = [
"random-string",
]

[[package]]
name = "random-string"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4e63111ec5292d8af9c220f06fe3bb87991cc78b6f1f7e291d1ae6b8a60817"
dependencies = [
"fastrand",
]

cargo.toml

1
2
3
4
5
6
7
8
9
[package]
name = "license-gen"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
random-string = "1.0"

main.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
use random_string::generate;

const LICENSE_CHARS: &str = "L23456789ABCDEFGHJKMNPQRSTUVWXYZ";
fn main() {
generate_license();
}

fn generate_license(){
let mut license = generate(22, LICENSE_CHARS);
for n in 0..2 {
let mut o = 0;
for i in (0..16).step_by(2) {
o += LICENSE_CHARS.find(&license[n+i..=n+i]).unwrap()
}
o %= LICENSE_CHARS.len();
license += &LICENSE_CHARS[o..=o];
}
license.insert(6, '-');
license.insert(13, '-');
license.insert(20, '-');
println!("License for you: {}", license);
}


4. 编译运行

在NodeInject项目主目录运行cargo build

前提需要安装rust环境,下载x86_64-pc-windows-msvc


5. 进入NodeInject生成的\target\debug文件夹有一个名为node_inject的exe文件 将其复制到Typora 的安装根目录
6. 在Typora安装目录打开管理员cmd 输入.\node_inject.exe回车
7. 然后进入license-gen 运行cargo build 获得激活码
8. 打开Typora,设置使用国内服务器(网络问题,非必须,不开启可能第一次激活失败后会弹出询问是否开启)后填写邮箱(任意)与生成的激活码

Github Action (已失效)

在action中启用自动化脚本 然后在build中运行工作流程等待构建完成

成品

可以去ty_license 下载