From ff414f6d791e1b8151c3c33add23fcfc4dc696fb Mon Sep 17 00:00:00 2001 From: MasOnShi Date: Mon, 4 Apr 2022 14:55:19 +0800 Subject: [PATCH] add win x86 supports. --- auto-analysis/utils.py | 39 +++++++++++++-------------- auto-analysis/win/x64/analysis.py | 21 ++++++++------- auto-analysis/win/x86/analysis.py | 45 +++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 31 deletions(-) create mode 100644 auto-analysis/win/x86/analysis.py diff --git a/auto-analysis/utils.py b/auto-analysis/utils.py index 5007f6b..4061821 100644 --- a/auto-analysis/utils.py +++ b/auto-analysis/utils.py @@ -10,11 +10,8 @@ import subprocess import json import os -# Usage: -# innoextract -# -BASE_DIR = os.path.dirname(__file__) +BASE_DIR = os.path.dirname(__file__) DOWNLOAD_LINK = { "win": { "x86": "https://typora.io/windows/typora-setup-ia32.exe", @@ -57,10 +54,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): download_path = os.path.join(basedir, os.path.basename(link)) log.info(f"downloading from {link}") @@ -71,24 +65,27 @@ def win_x64_run(): log.info("preparation stage completed") main_node_path = os.path.join(basedir, "app/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) + + +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) + + 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) diff --git a/auto-analysis/win/x64/analysis.py b/auto-analysis/win/x64/analysis.py index 2390071..d9e3596 100644 --- a/auto-analysis/win/x64/analysis.py +++ b/auto-analysis/win/x64/analysis.py @@ -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 \ No newline at end of file diff --git a/auto-analysis/win/x86/analysis.py b/auto-analysis/win/x86/analysis.py new file mode 100644 index 0000000..7ef28ef --- /dev/null +++ b/auto-analysis/win/x86/analysis.py @@ -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