mirror of
https://github.com/Mas0nShi/typoraCracker.git
synced 2023-07-10 13:41:20 +08:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
768f9e870a | ||
|
|
4d15e2a665 | ||
|
|
6a052ea508 | ||
|
|
214f7b5c79 | ||
|
|
7c83710ede | ||
|
|
dac502ef7f | ||
|
|
6874fc54bf | ||
|
|
f74141b4fa | ||
|
|
71c41fcaec | ||
|
|
1d28997146 | ||
|
|
ed3fb49ad0 | ||
|
|
f3310f448a | ||
|
|
1927e06b26 | ||
|
|
d067e4e296 | ||
|
|
0147f7c384 | ||
|
|
1c7a0daf60 | ||
|
|
a45d1b01a8 | ||
|
|
957e412291 | ||
|
|
d5c1bc55c2 | ||
|
|
6152b16fca | ||
|
|
f8ef3769c7 | ||
|
|
b43a44045f | ||
|
|
9787c2dd50 | ||
|
|
9589526703 | ||
|
|
263c976b1a | ||
|
|
9fd4bad0ab | ||
|
|
009b2ebff3 | ||
|
|
583ae2efe7 | ||
|
|
f586be4b1e | ||
|
|
c60fa54d54 | ||
|
|
4532c94d2b | ||
|
|
41ae7e552b | ||
|
|
00f916b16f |
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: [ 'javascript', 'python' ]
|
language: ["javascript" , 'python' ]
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||||
|
|
||||||
|
|||||||
29
README.md
29
README.md
@@ -1,36 +1,39 @@
|
|||||||
# typora Cracker
|
# typora Cracker
|
||||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2FMas0nShi%2FtyporaCracker?ref=badge_shield)
|
|
||||||
|

|
||||||

|

|
||||||
|
|
||||||
A patch and keygen tools for typora.
|
A extract & decryption and pack & encryption tools for typora.
|
||||||
|
|
||||||
中文说明请戳[这里](README_CN.md)
|
中文说明请戳[这里](README_CN.md)
|
||||||
|
|
||||||
## WARNING
|
## WARNING
|
||||||
|
|
||||||
|
**NOTE: typoraCracker doesn't provide support for crack.**
|
||||||
|
|
||||||
```
|
```
|
||||||
FOR STUDY AND DISCUSSION ONLY, PLEASE DO NOT ENGAGE IN ANY ILLEGAL ACTS.
|
FOR STUDY AND DISCUSSION ONLY, PLEASE DO NOT ENGAGE IN ANY ILLEGAL ACTS.
|
||||||
ANY PROBLEMS ARISING FROM THIS WILL BE BORNE BY THE USER (YOU).
|
ANY PROBLEMS ARISING FROM THIS WILL BE BORNE BY THE USER (YOU).
|
||||||
```
|
```
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
- Supports Version 1.0.0+ (At least for now.)
|
||||||
- Supports ALL OS supported by typora
|
- tested fine in Windows, Ubuntu
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
1. `pip install -r requirements.txt`
|
1. `pip install -r requirements.txt`
|
||||||
2. `python typroa.py --help`
|
2. `python typora.py --help`
|
||||||
3. read and use.
|
3. read and use.
|
||||||
4. patch License.js.
|
4. do something.
|
||||||
5. replace app.asar.
|
5. pack and replace app.asar.
|
||||||
6. run keygen.
|
6. enjoy it.
|
||||||
7. enjoy it.
|
|
||||||
|
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
> python typroa.py --help
|
> python typora.py --help
|
||||||
usage: typora.py [-h] [-u] [-f] asarPath dirPath
|
usage: typora.py [-h] [-u] [-f] asarPath dirPath
|
||||||
|
|
||||||
[extract and decryption / pack and encryption] app.asar file from [Typora].
|
[extract and decryption / pack and encryption] app.asar file from [Typora].
|
||||||
@@ -48,12 +51,12 @@ If you have any questions, please contact [ MasonShi@88.com ]
|
|||||||
|
|
||||||
> python typora.py {installRoot}/Typora/resources/app.asar workstation/outfile/
|
> python typora.py {installRoot}/Typora/resources/app.asar workstation/outfile/
|
||||||
⋯
|
⋯
|
||||||
> python typora.py -u workstation/outfile/ workstation/outappasar
|
# (patch code by yourself in workstation/outfile/dec_app)
|
||||||
|
> python typora.py -u workstation/outfile/dec_app workstation/outappasar
|
||||||
⋯
|
⋯
|
||||||
> cp {installRoot}/Typora/resources/app.asar {installRoot}/Typora/resources/app.asar.bak
|
> cp {installRoot}/Typora/resources/app.asar {installRoot}/Typora/resources/app.asar.bak
|
||||||
> mv workstation/outappasar/app.asar {installRoot}/Typora/resources/app.asar
|
> mv workstation/outappasar/app.asar {installRoot}/Typora/resources/app.asar
|
||||||
# (patch code)
|
> node example/keygen.js
|
||||||
> node keygen.js
|
|
||||||
XXXXXX-XXXXXX-XXXXXX-XXXXXX
|
XXXXXX-XXXXXX-XXXXXX-XXXXXX
|
||||||
> typora
|
> typora
|
||||||
# (input info)
|
# (input info)
|
||||||
|
|||||||
27
README_CN.md
27
README_CN.md
@@ -1,8 +1,11 @@
|
|||||||
# typora Cracker
|
# typora Cracker
|
||||||
|
|
||||||
一个typora的Patch和KeyGen工具
|
一个typora的解包&解密,打包&加密工具
|
||||||
|
|
||||||
## 敬告
|
## 敬告
|
||||||
|
|
||||||
|
**请注意:** typoraCracker不会提供破解相关支持,包括但不限于思路、流程、成品。
|
||||||
|
|
||||||
```
|
```
|
||||||
仅供学习和讨论,请不要从事任何非法行为。
|
仅供学习和讨论,请不要从事任何非法行为。
|
||||||
由此产生的任何问题都将由用户(您)承担。
|
由此产生的任何问题都将由用户(您)承担。
|
||||||
@@ -10,23 +13,23 @@
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- 理论上支持Typora支持的所有操作系统
|
- 支持版本1.0.0以上(至少现在是这样)
|
||||||
|
- 测试通过平台:Win/Ubuntu
|
||||||
|
|
||||||
## 食用方式
|
## 食用方式
|
||||||
|
|
||||||
1. `pip install -r requirements.txt`
|
1. `pip install -r requirements.txt`
|
||||||
2. `python typroa.py --help`
|
2. `python typora.py --help`
|
||||||
3. 阅读帮助文档及使用。
|
3. 阅读帮助文档及使用。
|
||||||
4. 修改导出的 License.js。
|
4. 做你想做的事。
|
||||||
5. 替换原目录下的 app.asar。
|
5. 打包并替换原目录下的 app.asar。
|
||||||
6. 运行KeyGen程序。
|
6. 享受成果。
|
||||||
7. 正常激活。
|
|
||||||
|
|
||||||
|
|
||||||
## 示例
|
## 示例
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
> python typroa.py --help
|
> python typora.py --help
|
||||||
usage: typora.py [-h] [-u] [-f] asarPath dirPath
|
usage: typora.py [-h] [-u] [-f] asarPath dirPath
|
||||||
|
|
||||||
[extract and decryption / pack and encryption] app.asar file from [Typora].
|
[extract and decryption / pack and encryption] app.asar file from [Typora].
|
||||||
@@ -44,12 +47,12 @@ If you have any questions, please contact [ MasonShi@88.com ]
|
|||||||
|
|
||||||
> python typora.py {installRoot}/Typora/resources/app.asar workstation/outfile/
|
> python typora.py {installRoot}/Typora/resources/app.asar workstation/outfile/
|
||||||
⋯
|
⋯
|
||||||
> python typora.py -u workstation/outfile/ workstation/outappasar
|
# (patch code by yourself in workstation/outfile/dec_app)
|
||||||
|
> python typora.py -u workstation/outfile/dec_app workstation/outappasar
|
||||||
⋯
|
⋯
|
||||||
> cp {installRoot}/Typora/resources/app.asar {installRoot}/Typora/resources/app.asar.bak
|
> cp {installRoot}/Typora/resources/app.asar {installRoot}/Typora/resources/app.asar.bak
|
||||||
> mv workstation/outappasar/app.asar {installRoot}/Typora/resources/app.asar
|
> mv workstation/outappasar/app.asar {installRoot}/Typora/resources/app.asar
|
||||||
# (patch code)
|
> node example/keygen.js
|
||||||
> node keygen.js
|
|
||||||
XXXXXX-XXXXXX-XXXXXX-XXXXXX
|
XXXXXX-XXXXXX-XXXXXX-XXXXXX
|
||||||
> typora
|
> typora
|
||||||
# (input info)
|
# (input info)
|
||||||
@@ -58,4 +61,4 @@ serial: XXXXXX-XXXXXX-XXXXXX-XXXXXX
|
|||||||
```
|
```
|
||||||
|
|
||||||
## LICENSE
|
## LICENSE
|
||||||
MIT LICENSE
|
MIT LICENSE
|
||||||
|
|||||||
12
example/README.md
Normal file
12
example/README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
## example
|
||||||
|
tested in version 1.0.2 only, it's means that you may need to make changes yourself if release the latest version.
|
||||||
|
|
||||||
|
v1.0.2 download:
|
||||||
|
- windows(64bit): https://download.typora.io/windows/typora-setup-x64-1.0.2.exe
|
||||||
|
- windows(32bit): https://download.typora.io/windows/typora-setup-ia32-1.0.2.exe
|
||||||
|
- windows(arm): https://download.typora.io/windows/typora-setup-arm64-1.0.2.exe
|
||||||
|
- linux(64bit|DEB): https://download.typora.io/linux/typora_1.0.2_amd64.deb
|
||||||
|
- linux(64bit|TAR): https://download.typora.io/linux/Typora-linux-x64-1.0.2.tar.gz
|
||||||
|
- linux(arm|DEB): https://download.typora.io/linux/typora_1.0.2_arm64.deb
|
||||||
|
- linux(arm|TAR): https://download.typora.io/linux/Typora-linux-arm64-1.0.2.tar.gz
|
||||||
|
|
||||||
1
example/patch/License.js
Normal file
1
example/patch/License.js
Normal file
File diff suppressed because one or more lines are too long
84
typora.py
84
typora.py
@@ -6,38 +6,50 @@
|
|||||||
@Desc: It's all about getting better.
|
@Desc: It's all about getting better.
|
||||||
"""
|
"""
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
from Crypto.Util.Padding import pad
|
from Crypto.Util.Padding import pad, unpad
|
||||||
from Crypto.Util.Padding import unpad
|
|
||||||
from base64 import b64decode, b64encode
|
from base64 import b64decode, b64encode
|
||||||
from jsbeautifier import beautify
|
from jsbeautifier import beautify
|
||||||
from jsmin import jsmin
|
from jsmin import jsmin
|
||||||
from os import listdir, urandom, makedirs
|
from os import listdir, urandom, makedirs
|
||||||
from os.path import isfile, isdir, join as pjoin, split as psplit
|
from os.path import isfile, isdir, join as pjoin, split as psplit, exists, abspath
|
||||||
from loguru import logger as log
|
from loguru import logger as log
|
||||||
from masar import extract_asar, pack_asar
|
from masar import extract_asar, pack_asar
|
||||||
import argparse
|
from shutil import rmtree
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
|
||||||
key = [0x4B029A9482B3E14E, 0xF157FEB4B4522F80, 0xE25692105308F4BE, 0x6DD58DDDA3EC0DC2]
|
# DEBUG
|
||||||
aesKey = b""
|
DEBUG = False
|
||||||
for akey in key:
|
|
||||||
aesKey += int.to_bytes(akey, byteorder="little", length=8)
|
log.remove()
|
||||||
|
if DEBUG:
|
||||||
|
log.add(sys.stderr, level="DEBUG")
|
||||||
|
else:
|
||||||
|
log.add(sys.stderr, level="INFO")
|
||||||
|
|
||||||
|
AES_KEY = struct.pack("<4Q", *[0x252A4C7BD0B85281, 0xA31BD92CE099F719, 0x13E283392646D82D, 0x118BDE501CF74120])
|
||||||
|
AES_IV = struct.pack("<4L", *[0x33706964, 0x5387CDD2, 0xD05F336D, 0x53F82468])
|
||||||
|
|
||||||
|
|
||||||
def _mkdir(_path):
|
def _mkDir(_path):
|
||||||
try:
|
if not exists(_path):
|
||||||
makedirs(_path)
|
makedirs(_path)
|
||||||
except FileExistsError:
|
else:
|
||||||
log.warning(f"May FolderExists: {_path}")
|
if _path == psplit(__file__)[0]:
|
||||||
|
log.warning("plz try not to use the root dir.")
|
||||||
|
else:
|
||||||
|
log.warning(f"May FolderExists: {_path}")
|
||||||
|
|
||||||
|
|
||||||
def decScript(b64: bytes, prettify: bool):
|
def decScript(b64: bytes, prettify: bool):
|
||||||
lCode = b64decode(b64)
|
lCode = b64decode(b64)
|
||||||
# iv: the first 16 bytes of the file
|
# iv
|
||||||
aesIv = lCode[0:16]
|
aesIv = AES_IV
|
||||||
# cipher text
|
# cipher text
|
||||||
cipherText = lCode[16:]
|
cipherText = lCode[:]
|
||||||
# AES 256 CBC
|
# AES 256 CBC
|
||||||
ins = AES.new(key=aesKey, iv=aesIv, mode=AES.MODE_CBC)
|
ins = AES.new(key=AES_KEY, iv=aesIv, mode=AES.MODE_CBC)
|
||||||
code = unpad(ins.decrypt(cipherText), 16, 'pkcs7')
|
code = unpad(ins.decrypt(cipherText), 16, 'pkcs7')
|
||||||
if prettify:
|
if prettify:
|
||||||
code = beautify(code.decode()).encode()
|
code = beautify(code.decode()).encode()
|
||||||
@@ -46,13 +58,18 @@ def decScript(b64: bytes, prettify: bool):
|
|||||||
|
|
||||||
def extractWdec(asarPath, path, prettify):
|
def extractWdec(asarPath, path, prettify):
|
||||||
"""
|
"""
|
||||||
|
:param prettify: bool
|
||||||
:param asarPath: asar out dir
|
:param asarPath: asar out dir
|
||||||
:param path: out dir
|
:param path: out dir
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
# try to create empty dir to save extract files
|
# try to create empty dir to save extract files
|
||||||
path = pjoin(path, "tmp_app")
|
path = pjoin(path, "typoraCrackerTemp")
|
||||||
_mkdir(path)
|
|
||||||
|
if exists(path):
|
||||||
|
rmtree(path)
|
||||||
|
_mkDir(path)
|
||||||
|
|
||||||
log.info(f"extract asar file: {asarPath}")
|
log.info(f"extract asar file: {asarPath}")
|
||||||
# extract app.asar to {path}/*
|
# extract app.asar to {path}/*
|
||||||
extract_asar(asarPath, path)
|
extract_asar(asarPath, path)
|
||||||
@@ -62,7 +79,10 @@ def extractWdec(asarPath, path, prettify):
|
|||||||
# construct the save directory {pathRoot}/dec_app
|
# construct the save directory {pathRoot}/dec_app
|
||||||
outPath = pjoin(psplit(path)[0], "dec_app")
|
outPath = pjoin(psplit(path)[0], "dec_app")
|
||||||
# try to create empty dir to save decryption files
|
# try to create empty dir to save decryption files
|
||||||
_mkdir(outPath)
|
if exists(outPath):
|
||||||
|
rmtree(outPath)
|
||||||
|
_mkDir(outPath)
|
||||||
|
|
||||||
log.info(f"set Directory: {outPath}")
|
log.info(f"set Directory: {outPath}")
|
||||||
# enumerate extract files
|
# enumerate extract files
|
||||||
fileArr = listdir(path)
|
fileArr = listdir(path)
|
||||||
@@ -80,13 +100,16 @@ def extractWdec(asarPath, path, prettify):
|
|||||||
open(pjoin(outPath, name), "wb").write(scode)
|
open(pjoin(outPath, name), "wb").write(scode)
|
||||||
log.success(f"decrypt and save file: {name}")
|
log.success(f"decrypt and save file: {name}")
|
||||||
|
|
||||||
|
rmtree(path)
|
||||||
|
log.debug("remove temp dir")
|
||||||
|
|
||||||
|
|
||||||
def encScript(_code: bytes, compress):
|
def encScript(_code: bytes, compress):
|
||||||
if compress:
|
if compress:
|
||||||
_code = jsmin(_code.decode(), quote_chars="'\"`").encode()
|
_code = jsmin(_code.decode(), quote_chars="'\"`").encode()
|
||||||
aesIv = urandom(16)
|
aesIv = AES_IV
|
||||||
cipherText = aesIv + _code
|
cipherText = _code
|
||||||
ins = AES.new(key=aesKey, iv=aesIv, mode=AES.MODE_CBC)
|
ins = AES.new(key=AES_KEY, iv=aesIv, mode=AES.MODE_CBC)
|
||||||
enc = ins.encrypt(pad(cipherText, 16, 'pkcs7'))
|
enc = ins.encrypt(pad(cipherText, 16, 'pkcs7'))
|
||||||
lCode = b64encode(enc)
|
lCode = b64encode(enc)
|
||||||
return lCode
|
return lCode
|
||||||
@@ -99,11 +122,17 @@ def packWenc(path, outPath, compress):
|
|||||||
:param compress: Bool
|
:param compress: Bool
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if not isdir(outPath):
|
# check out path
|
||||||
|
if isfile(outPath):
|
||||||
log.error("plz input Directory for app.asar")
|
log.error("plz input Directory for app.asar")
|
||||||
raise NotADirectoryError
|
raise NotADirectoryError
|
||||||
encFilePath = pjoin(psplit(outPath)[0], "enc_app")
|
|
||||||
_mkdir(encFilePath)
|
_mkDir(outPath)
|
||||||
|
|
||||||
|
encFilePath = pjoin(psplit(outPath)[0], "typoraCrackerTemp")
|
||||||
|
if exists(encFilePath):
|
||||||
|
rmtree(encFilePath)
|
||||||
|
_mkDir(encFilePath)
|
||||||
|
|
||||||
outFilePath = pjoin(outPath, "app.asar")
|
outFilePath = pjoin(outPath, "app.asar")
|
||||||
log.info(f"set outFilePath: {outFilePath}")
|
log.info(f"set outFilePath: {outFilePath}")
|
||||||
@@ -127,9 +156,12 @@ def packWenc(path, outPath, compress):
|
|||||||
pack_asar(encFilePath, outFilePath)
|
pack_asar(encFilePath, outFilePath)
|
||||||
log.success("pack done")
|
log.success("pack done")
|
||||||
|
|
||||||
|
rmtree(encFilePath)
|
||||||
|
log.debug("remove temp dir")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
argParser = argparse.ArgumentParser(
|
argParser = ArgumentParser(
|
||||||
description="[extract and decryption / pack and encryption] app.asar file from [Typora].",
|
description="[extract and decryption / pack and encryption] app.asar file from [Typora].",
|
||||||
epilog="If you have any questions, please contact [ MasonShi@88.com ]")
|
epilog="If you have any questions, please contact [ MasonShi@88.com ]")
|
||||||
argParser.add_argument("asarPath", type=str, help="app.asar file path/dir [input/ouput]")
|
argParser.add_argument("asarPath", type=str, help="app.asar file path/dir [input/ouput]")
|
||||||
|
|||||||
Reference in New Issue
Block a user