35 Commits

Author SHA1 Message Date
MasOnShi
3ac472a198 fix bugs. 2022-04-06 20:21:30 +08:00
MasOnShi
c3ed1499cc more details. 2022-04-05 15:07:08 +08:00
MasOnShi
637bc99b44 recommits 2022-04-04 21:39:12 +08:00
MasOnShi
d294746a36 adds test unit 2022-04-04 21:28:59 +08:00
MasOnShi
db41e7942c adds test unit 2022-04-04 21:28:02 +08:00
MasOnShi
d8f253e0c8 adds test unit 2022-04-04 21:26:15 +08:00
MasOnShi
19e73b6c79 adds support for linux-x64 2022-04-04 20:26:45 +08:00
MasOnShi
e6b6d7a9e1 Merge remote-tracking branch 'origin/master' 2022-04-04 20:12:28 +08:00
MasOnShi
ea2e2b479c adds support for linux-x64 2022-04-04 20:12:16 +08:00
MasOnShi
e562f37282 Merge branch 'auto-analysis-dev' 2022-04-04 20:09:59 +08:00
Mason Shi
b8726b62ae Merge pull request #58 from Mas0nShi/auto-analysis-dev
#57: add support for linux-x64
2022-04-04 20:08:12 +08:00
MasOnShi
e6d3d5aaff resolved 2022-04-04 20:07:57 +08:00
MasOnShi
c1beef1a98 #57: add support for linux-x64 2022-04-04 20:04:52 +08:00
MasOnShi
2e5bfcfb50 change readme content 2022-04-04 19:21:01 +08:00
MasOnShi
bab9df1f5f Merge remote-tracking branch 'origin/master'
# Conflicts:
#	README.md
2022-04-04 19:10:00 +08:00
Mason Shi
1c701eb7ae Update README.md 2022-04-04 17:24:24 +08:00
Mason Shi
df4320c481 Merge pull request #56 from Mas0nShi/auto-analysis-dev
adds badge
2022-04-04 17:08:55 +08:00
MasOnShi
d16428a8b2 change readme content 2022-04-04 17:08:18 +08:00
Mason Shi
37cb084073 Update manual.yml 2022-04-04 17:06:01 +08:00
Mason Shi
ce93881acd Merge pull request #54 from Mas0nShi/auto-analysis-dev
change readme content
2022-04-04 16:32:32 +08:00
MasOnShi
d13b7df457 change readme content 2022-04-04 16:31:58 +08:00
Mason Shi
8659ad77d8 Merge pull request #52 from Mas0nShi/auto-analysis-dev
add win x86 supports.
2022-04-04 16:11:30 +08:00
MasOnShi
f09cf7a8b5 add win x86 supports. 2022-04-04 16:11:04 +08:00
MasOnShi
591853fd67 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	auto-analysis/utils.py
2022-04-04 16:09:27 +08:00
MasOnShi
8df8b7f18e add win x86 supports. 2022-04-04 16:08:36 +08:00
Mason Shi
6968976033 Update manual.yml 2022-04-04 15:30:10 +08:00
MasOnShi
b582671923 add win x86 supports. 2022-04-04 15:11:01 +08:00
MasOnShi
ff414f6d79 add win x86 supports. 2022-04-04 15:11:01 +08:00
MasOnShi
3643ec2de3 dev commits. 2022-04-04 15:11:01 +08:00
MasOnShi
a312537aa2 dev commits. 2022-04-04 15:11:01 +08:00
Mason Shi
97a4f578b6 Merge pull request #50 from Mas0nShi/auto-analysis-dev
add win x86 supports.
2022-04-04 15:10:15 +08:00
MasOnShi
43b858c3ce add win x86 supports. 2022-04-04 15:09:07 +08:00
Mason Shi
df5bb4473f Update manual.yml 2022-04-04 15:03:18 +08:00
Mason Shi
facaed285a Merge pull request #49 from Mas0nShi/auto-analysis-dev
add win x86 supports.
2022-04-04 14:58:00 +08:00
MasOnShi
937e3aa178 add win x86 supports. 2022-04-04 14:55:19 +08:00
13 changed files with 257 additions and 90 deletions

View File

@@ -1,6 +1,6 @@
# This is a basic workflow that is manually triggered
name: Manual workflow
name: Automatic analysis
# Controls when the action will run. Workflow runs when manually triggered using the UI
# or API.
@@ -45,7 +45,7 @@ jobs:
sudo apt-get update && DEBIAN_FRONTEND=noninteractive sudo apt-get install innoextract -y
python3 -m pip install loguru
- name: Check Latest Version
- name: Check Latest Version (use win-x64)
id: checkVersion
run: |
python3 auto-analysis/check_version.py
@@ -65,7 +65,7 @@ jobs:
uses: actions/create-release@v1
id: createRelease
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: '${{ needs.check_version.outputs.LATEST_VERSION }}'
release_name: '${{ needs.check_version.outputs.LATEST_VERSION }}'
@@ -76,28 +76,29 @@ jobs:
needs: [check_version, create_release]
runs-on: ubuntu-20.04
if: needs.check_version.outputs.RELEASE_VERSION != needs.check_version.outputs.LATEST_VERSION
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
with:
python-version: '3.8' # Version range or exact version of a Python version to use, using SemVer's version range syntax
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
python-version: '3.8'
architecture: 'x64'
- name: install dependencies
run: |
sudo apt-get update && DEBIAN_FRONTEND=noninteractive sudo apt-get install innoextract cmake -y
sudo apt-get update && DEBIAN_FRONTEND=noninteractive sudo apt-get install innoextract zip -y
python3 -m pip install r2pipe loguru
- name: build radare2
shell: bash
run: |
git clone https://github.com/radareorg/radare2
radare2/sys/install.sh
- name: patch version
run: |
python3 auto-analysis/patch.py
tar -zcvf auto-analysis/win/x64/build/typoraCracker.tar.gz auto-analysis/win/x64/build/*
zip -rjq auto-analysis/win/x64/build/typoraCracker.zip auto-analysis/win/x64/build/*
zip -rjq auto-analysis/win/x86/build/typoraCracker.zip auto-analysis/win/x86/build/*
zip -rjq auto-analysis/linux/x64/build/typoraCracker.zip auto-analysis/linux/x64/build/*
- name: Check release version
id: checkReleaseVersion
@@ -123,13 +124,43 @@ jobs:
core.setFailed(e.message);
}
- name: Upload win x64 typora.py for typoraCracker
- name: Upload win-x64
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: '${{ steps.checkReleaseVersion.outputs.upload_url }}'
asset_path: '${{ github.workspace }}/auto-analysis/win/x64/build/typoraCracker.tar.gz'
asset_name: 'typoraCracker-${{ needs.check_version.outputs.LATEST_VERSION }}-win-x64.tar.gz'
asset_content_type: application/x-tgz
asset_path: '${{ github.workspace }}/auto-analysis/win/x64/build/typoraCracker.zip'
asset_name: 'typoraCracker-${{ needs.check_version.outputs.LATEST_VERSION }}-win-x64.zip'
asset_content_type: application/zip
- name: Upload win-x86
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: '${{ steps.checkReleaseVersion.outputs.upload_url }}'
asset_path: '${{ github.workspace }}/auto-analysis/win/x86/build/typoraCracker.zip'
asset_name: 'typoraCracker-${{ needs.check_version.outputs.LATEST_VERSION }}-win-x86.zip'
asset_content_type: application/zip
- name: Upload linux-x64
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: '${{ steps.checkReleaseVersion.outputs.upload_url }}'
asset_path: '${{ github.workspace }}/auto-analysis/linux/x64/build/typoraCracker.zip'
asset_name: 'typoraCracker-${{ needs.check_version.outputs.LATEST_VERSION }}-linux-x64.zip'
asset_content_type: application/zip
- name: verify scripts
run: |
python3 -m pip install -r auto-analysis/win/x64/build/requirements.txt
python3 auto-analysis/win/x64/build/typora.py auto-analysis/win/x64/app/resources/app.asar auto-analysis/win/x64
echo "win x64 test completed"
python3 auto-analysis/win/x86/build/typora.py auto-analysis/win/x86/app/resources/app.asar auto-analysis/win/x86
echo "win x86 test completed"
python3 auto-analysis/linux/x64/build/typora.py auto-analysis/linux/x64/bin/Typora-linux-x64/resources/app.asar auto-analysis/linux/x64
echo "linux x64 test completed"

View File

@@ -3,8 +3,18 @@
# typora Cracker
![GitHub Repo stars](https://img.shields.io/github/stars/Mas0nshi/typoraCracker)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/Mas0nshi/typoraCracker)
![GitHub commit activity (branch)](https://img.shields.io/github/commit-activity/m/Mas0nshi/typoraCracker)
![GitHub Release Date](https://img.shields.io/github/release-date/Mas0nshi/typoraCracker)
![GitHub issues](https://img.shields.io/github/issues-raw/Mas0nshi/typoraCracker?color=ff69b4)
![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/Mas0nshi/typoraCracker)
![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FMas0nShi%2FtyporaCracker.svg?type=shield)
![GitHub](https://img.shields.io/github/license/Mas0nShi/typoraCracker)
[![Automatic analysis](https://github.com/Mas0nShi/typoraCracker/actions/workflows/manual.yml/badge.svg)](https://github.com/Mas0nShi/typoraCracker/actions/workflows/manual.yml)
A extract & decryption and pack & encryption tools for typora.
@@ -20,17 +30,28 @@ ANY PROBLEMS ARISING FROM THIS WILL BE BORNE BY THE USER (YOU).
```
## Features
- Supports Version 1.0.0+ (At least for now.)
- tested fine in Windows, Ubuntu
- Supports Version 1.0.0 - 1.2.0 [(old archive)](https://github.com/Mas0nShi/typoraCracker/tree/backup-raw)
- Supports Version 1.2.+ [(Experimental archive)](https://github.com/Mas0nShi/typoraCracker/tree/master)
## Support List
2022.4.4: Experimental support for automatic binary analysis to generate scripts. (v1.2.+)
| OS / ARCH | x86 | x64 | arm64 |
|:---------:|:---:|:---:|:-----:|
| win | ✅ | ✅ | ❌ |
| linux | ⛔ | ✅ | ❌ |
| macOS | ❌ | ❌ | ❌ |
## Usage
1. `pip install -r requirements.txt`
2. `python typora.py --help`
3. read and use.
4. do something.
5. pack and replace app.asar.
6. enjoy it.
1. download in [Release Pages](https://github.com/Mas0nShi/typoraCracker/releases)
2. unzip
3. `pip install -r requirements.txt`
4. `python typora.py --help`
5. read and use.
6. do something.
7. pack and replace app.asar.
8. enjoy it.
## Example

View File

@@ -15,18 +15,30 @@
```
## Features
- 版本 1.0.0 - 1.2.0 [(使用旧的存档)](https://github.com/Mas0nShi/typoraCracker/tree/backup-raw)
- 版本 1.2.+ [(使用测试存档)](https://github.com/Mas0nShi/typoraCracker/tree/master)
## Support List
2022.4.4: 支持自动化分析二进制文件并生成脚本(测试性功能 v1.2.+
| OS / ARCH | x86 | x64 | arm64 |
|:---------:|:---:|:---:|:-----:|
| win | ✅ | ✅ | ❌ |
| linux | ⛔ | ✅ | ❌ |
| macOS | ❌ | ❌ | ❌ |
- 支持版本1.0.0以上(至少现在是这样)
- 测试通过平台Win/Ubuntu
## 食用方式
1. `pip install -r requirements.txt`
2. `python typora.py --help`
3. 阅读帮助文档及使用。
4. 做你想做的事。
5. 打包并替换原目录下的 app.asar。
6. 享受成果
1. 前往[Release Pages](https://github.com/Mas0nShi/typoraCracker/releases) 下载对应版本
2. 解压
3. 安装依赖:`pip install -r requirements.txt`
4. 使用说明:`python typora.py --help`
5. 使用。
6. 做你想做的事
7. 打包并替换原目录下的 app.asar。
8. 享受成果。
## 示例

View File

@@ -1,22 +1,23 @@
from utils import get_version, download_file, extract_file, log, DOWNLOAD_LINK
from utils import get_version, download_file, extract_file, log
from config import DOWNLOAD_LINK
import os
BASE_DIR = os.path.dirname(__file__)
def win_x64_version():
url = DOWNLOAD_LINK["win"]["x64"]
dir = os.path.join(BASE_DIR, "win/x64")
def run_version(download_os, download_arch):
from_url = DOWNLOAD_LINK[download_os][download_arch]
to_dir = os.path.join(BASE_DIR, f"{download_os}/{download_arch}")
download_path = os.path.join(dir, os.path.basename(url))
download_file(url, download_path)
extract_file(download_path, dir)
version = get_version(dir)
open(os.path.join(dir, "LATEST_VERSION"), "w").write(version)
log.success(version)
download_path = os.path.join(to_dir, os.path.basename(from_url))
download_file(from_url, download_path)
extract_file(download_path, to_dir)
version = get_version(to_dir)
open(os.path.join(to_dir, "LATEST_VERSION"), "w").write(version)
log.success(f"{download_os}-{download_arch} the latest version is {version}")
if __name__ == '__main__':
win_x64_version()
run_version("win", "x64")
# run_version("win", "x86")
# run_version("linux", "x64")

25
auto-analysis/config.py Normal file
View File

@@ -0,0 +1,25 @@
# -*- coding:utf-8 -*-
"""
@Author: Mas0n
@File: config.py
@Time: 2022/4/4 19:50
@Desc: It's all about getting better.
"""
DOWNLOAD_LINK = {
"win": {
"x86": "https://typora.io/windows/typora-setup-ia32.exe",
"x64": "https://typora.io/windows/typora-setup-x64.exe",
"arm64": "https://typora.io/windows/typora-setup-arm64.exe",
},
"linux": {
"x64": "https://download.typora.io/linux/Typora-linux-x64.tar.gz",
"arm64": "https://download.typora.io/linux/Typora-linux-arm64.tar.gz",
},
}
EXTRACT_ROOT_PATH = {
"win": "app",
"linux": "bin/Typora-linux-x64"
}

View File

@@ -0,0 +1,32 @@
# -*- coding:utf-8 -*-
"""
@Author: Mas0n
@Name: typora_linux_x64_analysis
@Time: 2022/4/4 19:48
@Desc: It's all about getting better.
"""
import json
import r2pipe
def get_aes_key_and_iv(file_path):
r = r2pipe.open(file_path)
r.cmd("aaa")
regex = r.cmdj("axtj @@ str.base64")
assert len(regex) == 1
func = regex[0]["fcn_name"]
r.cmd(f"s {func}")
asm = r.cmdj("pdfj")['ops']
assert len(asm) != 0
if 'str.dip3' in json.dumps(asm):
r.cmd('s str.dip3 - 32')
data = r.cmdj('xj 48')
key = bytearray(data[0:32])
iv = bytearray(data[32:48])
else:
raise "need rewrite scripts for linux x64"
return key, iv

View File

@@ -8,5 +8,7 @@
import utils
if __name__ == '__main__':
utils.win_x86_run()
utils.win_x64_run()
utils.linux_x64_run()

View File

@@ -6,27 +6,13 @@
@Desc: It's all about getting better.
"""
from loguru import logger as log
from config import DOWNLOAD_LINK, EXTRACT_ROOT_PATH
import subprocess
import json
import os
# Usage:
# innoextract
#
BASE_DIR = os.path.dirname(__file__)
DOWNLOAD_LINK = {
"win": {
"x86": "https://typora.io/windows/typora-setup-ia32.exe",
"x64": "https://typora.io/windows/typora-setup-x64.exe",
"arm": "https://typora.io/windows/typora-setup-arm64.exe",
},
"linux": {
"x64": "https://download.typora.io/linux/Typora-linux-x64.tar.gz",
"arm": "https://download.typora.io/linux/Typora-linux-arm64.tar.gz",
},
}
def get_version(to_path):
package_file_path = os.path.join(to_path, "app/resources/package.json")
@@ -36,11 +22,14 @@ def get_version(to_path):
def download_file(from_link, to_path):
subprocess.check_call(["wget", from_link, "-O", to_path])
subprocess.check_call(["wget", "-q", from_link, "-O", to_path])
def extract_file(from_path, to_path):
subprocess.check_call(["innoextract", from_path, "-d", to_path])
if from_path.endswith(".exe"):
subprocess.check_call(["innoextract", "-q", from_path, "-d", to_path])
elif from_path.endswith(".tar.gz"):
subprocess.check_call(["tar", "-zxvf", from_path, "-C", to_path])
def patch_file(_key, _iv, to_dir):
@@ -57,11 +46,7 @@ def patch_file(_key, _iv, to_dir):
open(patch_file_path, "w").write(content)
def win_x64_run():
from win.x64 import analysis
basedir = os.path.join(BASE_DIR, "win/x64")
link = DOWNLOAD_LINK["win"]["x64"]
def scheduler(func, basedir, link, root_path):
download_path = os.path.join(basedir, os.path.basename(link))
log.info(f"downloading from {link}")
download_file(link, download_path)
@@ -69,26 +54,38 @@ def win_x64_run():
extract_file(download_path, basedir)
log.info("preparation stage completed")
main_node_path = os.path.join(basedir, "app/resources/app.asar.unpacked/main.node")
main_node_path = os.path.join(basedir, os.path.join(root_path, "resources/app.asar.unpacked/main.node"))
log.info("auto analysis start")
key, iv = analysis.get_aes_key_and_iv(main_node_path)
key, iv = func.get_aes_key_and_iv(main_node_path)
log.success("analysis done")
patch_file(key.hex(), iv.hex(), basedir)
log.success("patch done")
def win_x64_run():
from win.x64 import analysis
dirs = os.path.join(BASE_DIR, "win/x64")
url = DOWNLOAD_LINK["win"]["x64"]
scheduler(func=analysis, basedir=dirs, link=url, root_path=EXTRACT_ROOT_PATH["win"])
def win_x86_run():
from win.x86 import analysis
dirs = os.path.join(BASE_DIR, "win/x86")
url = DOWNLOAD_LINK["win"]["x86"]
scheduler(func=analysis, basedir=dirs, link=url, root_path=EXTRACT_ROOT_PATH["win"])
def linux_x64_run():
from linux.x64 import analysis
dirs = os.path.join(BASE_DIR, "linux/x64")
url = DOWNLOAD_LINK["linux"]["x64"]
scheduler(func=analysis, basedir=dirs, link=url, root_path=EXTRACT_ROOT_PATH["linux"])
if __name__ == '__main__':
win_x86_run()
win_x64_run()
# hashString = open("LATEST_VERSION", "r").read()
# if hashString == "":
# log.info("not history for typora version")
# exit()
# basedir = os.path.dirname(__file__)
# for h1 in DOWNLOAD_LINK.keys():
# h1dir = os.path.join(basedir, h1)
# for h2 in DOWNLOAD_LINK.get(h1).keys():
# h2dir = os.path.join(h1dir, h2)
# print(h2dir)
linux_x64_run()

View File

@@ -9,29 +9,30 @@ import struct
import r2pipe
def regex_key_iv(asm_obj):
asm_regex = []
for body in asm_obj:
if "=[4]" in body["esil"] and body['type'] == 'mov':
opcode, value = body["disasm"].split(", ")
if "0x" in value:
asm_regex.append({"opcode": opcode, "value": value})
return asm_regex
def get_aes_key_and_iv(file_path):
r = r2pipe.open(file_path)
# auto analysis
r.cmd("aaa")
# string "base64" x-cross reference
regex = r.cmdj("axtj @@ str.base64")
assert len(regex) == 1
func = regex[0]["fcn_name"]
# disasm func
r.cmd(f"s {func}")
asm = r.cmdj("pdfj")['ops']
assert len(asm) != 0
asm_regex = []
for body in asm:
if "=[4]" in body["esil"] and body['type'] == 'mov':
opcode, value = body["disasm"].split(", ")
asm_regex.append({"opcode": opcode, "value": value})
asm_regex = regex_key_iv(asm)
assert len(asm_regex) == 12
iv = struct.pack("<4L", *[int(asm_regex[i]['value'], 16) for i in range(4)])
key = struct.pack("<8L", *[int(asm_regex[i]['value'], 16) for i in range(4, 12)])
# print(key, iv)
return key, iv

View File

@@ -0,0 +1,45 @@
# -*- coding:utf-8 -*-
"""
@Author: Mas0n
@Name: typora_win_x86_analysis
@Time: 2022/4/3 18:36
@Desc: It's all about getting better.
"""
import struct
import r2pipe
def regex_key_iv(asm_obj):
asm_regex = []
for body in asm_obj:
if "=[4]" in body["esil"] and body['type'] == 'mov':
opcode, value = body["disasm"].split(", ")
if "0x" in value:
asm_regex.append({"opcode": opcode, "value": value})
return asm_regex
def get_aes_key_and_iv(file_path):
r = r2pipe.open(file_path)
r.cmd("aaa")
regex = r.cmdj("axtj @@ str.base64")
assert len(regex) == 1
func = regex[0]["fcn_name"]
r.cmd(f"s {func}")
asm = r.cmdj("pdfj")['ops']
assert len(asm) != 0
asm_regex = regex_key_iv(asm)
iv = struct.pack("<4L", *[int(asm_regex[i]['value'], 16) for i in range(4)])
# find the set key func
call_regex = [i for i in asm if i['size'] == 5 and i['type'] == 'call']
r.cmd(f"s {call_regex[1]['jump']}")
asm = r.cmdj("pdfj")["ops"]
asm_regex = regex_key_iv(asm)
assert len(asm_regex) == 8
key = struct.pack("<8L", *[int(asm_regex[i]['value'], 16) for i in range(8)])
return key, iv

Binary file not shown.