From 79752cfa02258878144b09dea48083f41cacbe90 Mon Sep 17 00:00:00 2001 From: cxykevin Date: Thu, 8 Feb 2024 19:04:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=99=A4shortcut=E7=AD=89?= =?UTF-8?q?=E7=9A=84=E5=9F=BA=E6=9C=AC=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 161 +++++++++++++++++++++- .vscode/launch.json | 21 +++ .vscode/settings.json | 5 + Makefile | 32 +++++ env/keep | 0 installer/install.py | 106 +++++++++++++++ package/cli/cli/helloworld | 0 package/cli/cli/test.txt | 1 + package/cli/manifest.json | 55 ++++++++ root/VentoyAutoRun.bat | 10 ++ src/action.py | 152 +++++++++++++++++++++ src/config.py | 17 +++ src/hook.py | 42 ++++++ src/loader.py | 267 +++++++++++++++++++++++++++++++++++++ src/log.py | 61 +++++++++ src/main.py | 22 +++ src/utils.py | 15 +++ tool/.keep | 0 version | 1 + 19 files changed, 967 insertions(+), 1 deletion(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 env/keep create mode 100644 installer/install.py create mode 100644 package/cli/cli/helloworld create mode 100644 package/cli/cli/test.txt create mode 100644 package/cli/manifest.json create mode 100644 src/action.py create mode 100644 src/config.py create mode 100644 src/hook.py create mode 100644 src/loader.py create mode 100644 src/log.py create mode 100644 src/main.py create mode 100644 src/utils.py create mode 100644 tool/.keep create mode 100644 version diff --git a/.gitignore b/.gitignore index 7293713..f2cec82 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,161 @@ +# Download/build cache tmp -dist \ No newline at end of file +# Distribution file +dist +# Auto download python env +env/*.* +# VM debug file +start_vm.cmd +# Debug file +src/debug.py + + +# -------- Python igrone --------- +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.venv +venv/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d0b6d27 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python 调试程序", + "type": "debugpy", + "request": "launch", + "program": "src/debug.py", + "console": "integratedTerminal" + }, + { + "command": "make debug", + "name": "打包并在虚拟机中运行", + "request": "launch", + "type": "node-terminal" + }, + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a9be085 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "yaml.schemas": { + "https://json.schemastore.org/yamllint.json": "file:///c%3A/Users/Administrator/Desktop/PEinjector/package/cli/manifest.yml" + } +} \ No newline at end of file diff --git a/Makefile b/Makefile index e69de29..d4611c9 100644 --- a/Makefile +++ b/Makefile @@ -0,0 +1,32 @@ +dist\PEinjector.7z: src\main.py src\log.py src\config.py src\loader.py src\utils.py root\VentoyAutoRun.bat + mkdir tmp\pkg\PEinjector\env + mkdir tmp\pkg\PEinjector\src + mkdir tmp\pkg\PEinjector\tool + xcopy root .\tmp\pkg /C /Y /E + xcopy env .\tmp\pkg\PEinjector\env /C /Y /E + xcopy src .\tmp\pkg\PEinjector\src /C /Y /E + xcopy tool .\tmp\pkg\PEinjector\tool /C /Y /E + rmdir /S /Q dist + mkdir dist + 7z a -t7z dist\PEinjector.7z .\tmp\pkg\PEinjector -r -m0=BCJ -m1=LZMA:d=21 -ms -mmt + 7z a -t7z dist\PEinjector.7z .\tmp\pkg\VentoyAutoRun.bat -m0=BCJ -m1=LZMA:d=21 -ms -mmt + rmdir /S /Q tmp +tmp\py\python.zip: + mkdir tmp\py + cd tmp\py + curl https://www.python.org/ftp/python/3.12.1/python-3.12.1-embed-amd64.zip -o tmp\py\python.zip +env\python.exe: tmp\py\python.zip + 7z x -y -aos -oenv\ tmp\py\python.zip +install: dist\PEinjector.7z installer/install.py + python installer\install.py +build: dist\PEinjector.7z +prepare: env\python.exe +clean: + rmdir /S /Q tmp + rmdir /S /Q dist + mkdir dist +debug: dist\PEinjector.7z + python installer\install.py + start_vm.cmd +start: + start_vm.cmd \ No newline at end of file diff --git a/env/keep b/env/keep new file mode 100644 index 0000000..e69de29 diff --git a/installer/install.py b/installer/install.py new file mode 100644 index 0000000..bf541fe --- /dev/null +++ b/installer/install.py @@ -0,0 +1,106 @@ +##################################### +## PEinjector/installer ## +##################################### + +# This moudle is a part of PEinjector. +# Please comply with the LICENSE. + +import os +import shutil +import json + +############ Config ############ +KEYWORD = "winpe" +PYTHON = "python" +DISK = "{disk}" +################################ + +# Linux please run: mount /dev/sdX /mnt/disk --mkdir +# DISK = "/mnt/disk" + + +def find_disk(): # This code from dashedgeless + disk_list = "CDEFGHIJKABLMNOPQRSTUVWYZ" + for i in disk_list: + this_disk = i + ":" + if os.path.exists(this_disk + "/ventoy/ventoy.json"): + return this_disk + raise OSError( + "Cannot find the Ventoy disk!(try to run ventoyPlugson once)") + + +DISK = DISK.replace("{disk}", find_disk()) + +print("use disk: "+DISK) +with open(DISK+"/ventoy/ventoy.json", "r") as file: + vtoycfg = json.load(file) +searchroot = "" +searchlevel = 3 +if "control" in vtoycfg: + for i in vtoycfg["control"]: + if "VTOY_DEFAULT_SEARCH_ROOT" in i: + searchroot = i["VTOY_DEFAULT_SEARCH_ROOT"] + if "VTOY_MAX_SEARCH_LEVEL" in i: + if i["VTOY_MAX_SEARCH_LEVEL"] != "max": + searchlevel = int(i["VTOY_MAX_SEARCH_LEVEL"]) +filelist = [] + + +def dfs(deep, dir): + if deep > searchlevel: + return + lists = os.listdir(DISK+dir) + for i in lists: + if os.path.isfile(DISK+dir+"/"+i): + if ".iso" in i.lower() and KEYWORD in i.lower(): + filelist.append(dir+"/"+i) + else: + dfs(deep+1, dir+"/"+i) + + +dfs(0, searchroot) + +if "injection" in vtoycfg: + for i in vtoycfg["injection"]: + if "image" in i: + if i["image"] in filelist: + filelist.remove(i["image"]) +else: + vtoycfg["injection"] = [] +print("find iso:", filelist) +for i in filelist: + vtoycfg["injection"].append({ + "image": i, + "archive": "/PEinjector/PEinjector.7z" + }) +print("write config") +with open(DISK+"/ventoy/ventoy.json", "w") as file: + file.write(json.dumps(vtoycfg)) + + +print("copy file") +if not os.path.exists(DISK+"/PEinjector"): + os.mkdir(DISK+"/PEinjector") +if os.path.exists(DISK+"/PEinjector/PEinjector.7z"): + os.remove(DISK+"/PEinjector/PEinjector.7z") +shutil.copyfile("dist/PEinjector.7z", DISK+"/PEinjector/PEinjector.7z") +if not os.path.exists(DISK+"/PEinjector/disable.txt"): + with open(DISK+"/PEinjector/disable.txt", "w") as file: + pass + +print("write version info") +shutil.copyfile("version", DISK+"/PEinjector/VERSION") + +print("make dir") +if not os.path.exists(DISK+"/PEinjector/install"): + os.mkdir(DISK+"/PEinjector/install") + +print("install basic package") +if not os.path.exists(DISK+"/PEinjector/package"): + os.mkdir(DISK+"/PEinjector/package") +for i in os.listdir("package"): + if os.path.exists(DISK+"/PEinjector/package/"+i): + shutil.rmtree(DISK+"/PEinjector/package/"+i) + shutil.copytree("package/"+i, DISK+"/PEinjector/package/"+i) + +print("done") diff --git a/package/cli/cli/helloworld b/package/cli/cli/helloworld new file mode 100644 index 0000000..e69de29 diff --git a/package/cli/cli/test.txt b/package/cli/cli/test.txt new file mode 100644 index 0000000..2d1e2a7 --- /dev/null +++ b/package/cli/cli/test.txt @@ -0,0 +1 @@ +nihaoshijie \ No newline at end of file diff --git a/package/cli/manifest.json b/package/cli/manifest.json new file mode 100644 index 0000000..7fb48e0 --- /dev/null +++ b/package/cli/manifest.json @@ -0,0 +1,55 @@ +{ + "version": "0.0.1", + "name": "cli-tools", + "author": "cxykevin", + "introduce": "PEinjector/命令行工具", + "compatibility": { + "injector": { + "min": "0.0.1", + "max": "0.0.1" + } + }, + "load": { + "symlink": true, + "mode": { + "onboot": [ + { + "type": "copy", + "from": "cli", + "to": "X:/Windows/system32" + } + ], + "onload": [ + { + "type": "start", + "command": "cmd" + } + ] + } + }, + "start": { + "icon": [ + { + "name": "CMD", + "command": "cmd", + "args": "", + "icon": "X:/Windows/system32/cmd.exe" + } + ], + "path": [ + "X:/Windows/system32/cli" + ] + }, + "keywords": [ + "cli", + "PEinjector" + ], + "dependence": [], + "datas": [ + { + "type": "dir", + "from": "cli/test.txt", + "to": "data1" + } + ] +} \ No newline at end of file diff --git a/root/VentoyAutoRun.bat b/root/VentoyAutoRun.bat index e69de29..b7bf6c9 100644 --- a/root/VentoyAutoRun.bat +++ b/root/VentoyAutoRun.bat @@ -0,0 +1,10 @@ +@echo off +@REM ##################################### +@REM ## PEinjector/vtoyAutorun ## +@REM ##################################### +@REM +@REM This file is loader for ventoy. +@REM +echo "PEinjector Start" +cd X:\PEinjector\src +X:\PEinjector\env\python X:\PEinjector\src\main.py diff --git a/src/action.py b/src/action.py new file mode 100644 index 0000000..2349891 --- /dev/null +++ b/src/action.py @@ -0,0 +1,152 @@ +##################################### +## PEinjector/action ## +##################################### + +# Actions ID Info: +# .----+--------------+--------------------------. +# | ID | Args | Actions | +# +====+==============+==========================+ +# | 0 | pkg_name | start load pkg (for log) | +# +----+--------------+--------------------------+ +# | 1 | path | mkdir | +# +----+--------------+--------------------------+ +# | 2 | from, to | copy | +# +----+--------------+--------------------------+ +# | 3 | from, to | link | +# +----+--------------+--------------------------+ +# | 4 | from, to | link | +# +----+--------------+--------------------------+ +# | 5 | command | start | +# '----+--------------+--------------------------' + + +import os +import config +import utils +import pickle +import log +import uuid +import shutil +import subprocess + + +def force_copy(pkg_path, pkg_name, data_list, froms, tos): + froms = froms.replace("\\", "/") + if len(froms) > 1 and froms[-1] == '/': + froms = froms[:-1] + tos = tos.replace("\\", "/") + if len(tos) > 1 and tos[-1] == '/': + tos = tos[:-1] + datas = [] + data_dir = config.DATAPATH.replace( + "{DISK}", utils.find_disk())+"/"+pkg_name + + data_check = [i["from"] for i in data_list] + + def search_dir(path): + if froms+path in data_check: + datas.append( + (4, pkg_path+"/"+froms+path, data_dir+"/"+data_list[data_check.index(froms+path)]["to"])) + else: + datas.append((1, tos+path)) + for i in os.listdir(pkg_path+"/"+froms+path): + if os.path.isfile(pkg_path+"/"+froms+path+"/"+i): + if froms+path+"/"+i in data_check: + datas.append( + (3, pkg_path+"/"+froms+path+"/"+i, data_dir+data_list[data_check.index(froms+path+"/"+i)]["to"])) + else: + datas.append( + (2, pkg_path+"/"+froms+path+"/"+i, tos+path+"/"+i)) + else: + search_dir(path+"/"+i) + search_dir("") + return datas + + +def copy(pkg_path, pkg_name, data_list, froms, tos): + froms = froms.replace("\\", "/") + if len(froms) > 1 and froms[-1] == '/': + froms = froms[:-1] + tos = tos.replace("\\", "/") + if len(tos) > 1 and tos[-1] == '/': + tos = tos[:-1] + datas = [] + data_dir = config.DATAPATH.replace( + "{DISK}", utils.find_disk())+"/"+pkg_name + + data_check = [i["from"] for i in data_list] + + def search_dir(path): + if froms+path in data_check: + datas.append( + (4, pkg_path+"/"+froms+path, data_dir+"/"+data_list[data_check.index(froms+path)]["to"])) + else: + datas.append((1, tos+path)) + for i in os.listdir(pkg_path+"/"+froms+path): + if os.path.isfile(pkg_path+"/"+froms+path+"/"+i): + if froms+path+"/"+i in data_check: + datas.append( + (3, pkg_path+"/"+froms+path+"/"+i, data_dir+data_list[data_check.index(froms+path+"/"+i)]["to"])) + else: + datas.append( + (3, pkg_path+"/"+froms+path+"/"+i, tos+path+"/"+i)) + else: + search_dir(path+"/"+i) + search_dir("") + return datas + + +def start(pkg_name, data_list, cmd): + return [(5, cmd)] + + +def save_action(actions_list): + tmp_filename = str(uuid.uuid1())+".tmp" # hind pickle file + log.info(f"save action list to {config.TEMP_DIR.replace( + '{TEMP}', os.environ['TEMP'].replace("\\", "/"))+'/'+tmp_filename}") + with open(config.TEMP_DIR.replace("{TEMP}", os.environ["TEMP"])+"/"+tmp_filename, "wb") as file: + pickle.dump(actions_list, file) + return tmp_filename + + +def do_action(actions_list): + actionlogs = "----- Action Log Start -----\r\n" + for i in actions_list: + if i[0] == 0: + actionlogs = actionlogs+f"Load [{i[1]}]\r\n" + elif i[0] == 1: + try: + os.mkdir(i[1], mode=0o777) + except Exception as exp: + actionlogs = actionlogs + \ + f" mkdir \"{i[1]}\" failed: {repr(exp)}\r\n" + elif i[0] == 2: + try: + shutil.copyfile(i[1], i[2]) + except Exception as exp: + actionlogs = actionlogs + \ + f" copy \"{i[1]}\" to " + \ + f"\"{i[2]}\" failed: {repr(exp)}\r\n" + elif i[0] == 3: + try: + os.symlink(i[1], i[2]) + except Exception as exp: + actionlogs = actionlogs + \ + f" link(S) \"{i[1]}\" to " + \ + f"\"{i[2]}\" failed: {repr(exp)}\r\n" + elif i[0] == 4: + try: + assert os.system(f"mklink /J {i[1].replace( + '/', '\\')} {i[2].replace('/', '\\')} > nul") == 0, "mklink return not 0" + except Exception as exp: + actionlogs = actionlogs + \ + f" link(J) \"{i[1]}\" to " + \ + f"\"{i[2]}\" failed: {repr(exp)}\r\n" + elif i[0] == 5: + try: + subprocess.Popen( + "start "+i[1], shell=True) + except Exception as exp: + actionlogs = actionlogs + \ + f" start \"{i[1]}\" failed: {repr(exp)}\r\n" + return actionlogs diff --git a/src/config.py b/src/config.py new file mode 100644 index 0000000..6a5fa9f --- /dev/null +++ b/src/config.py @@ -0,0 +1,17 @@ +##################################### +## PEinjector/config ## +##################################### + +# This file is the default settings and +# settings for developers. +# Do not change it. + + +LOGLEVEL = "debug" +OUTPUT_COLORFUL = True +LOGPATH = "{DISK}/PEinjector/log.txt" +ACTIONLOGPATH = "{DISK}/PEinjector/actionlog.txt" +USE_SYMLINK = True +DATAPATH = "{DISK}/PEinjector/data" +DISABLEPATH = "{DISK}/PEinjector/disable.txt" +TEMP_DIR = "{TEMP}" diff --git a/src/hook.py b/src/hook.py new file mode 100644 index 0000000..db4cccd --- /dev/null +++ b/src/hook.py @@ -0,0 +1,42 @@ +##################################### +## PEinjector/hook ## +##################################### + +# This moudle will wait PE loaded all +# things. + +# load moudles +import sys +import os +import time +import pickle +try: + sys.path.append("X:\\PEinjector\\src") + sys.path.append("X:\\PEinjector\\tool") + os.chdir("X:\\PEinjector\\src") +except: + sys.path.append(".") + sys.path.append("..\\tool") + +log = __import__("log") +config = __import__("config") +action = __import__("action") +utils = __import__("utils") + +log.init() +log.info("hook start") +if len(sys.argv) != 2: + log.break_err("args error") + sys.exit(1) + +# wait +time.sleep(10) + +# load action list +log.info("load action \"onload\"") +with open(config.TEMP_DIR.replace("{TEMP}", os.environ["TEMP"])+"/"+sys.argv[1], "rb") as file: + lists = pickle.load(file) +alog = action.do_action(lists) +with open(config.ACTIONLOGPATH.replace("{DISK}", utils.find_disk()), "w") as file: + file.write(alog) +log.info("done") diff --git a/src/loader.py b/src/loader.py new file mode 100644 index 0000000..307d4e6 --- /dev/null +++ b/src/loader.py @@ -0,0 +1,267 @@ +##################################### +## PEinjector/loader ## +##################################### + +import utils +import os +import shutil +import log +import json +import traceback +import config +import action + +loaded_package = [] +loaderr_pkgs = [] +disk = "" +lists = [] + + +def version_check(file_json, pkg_name): + try: + if "compatibility" in file_json: + if "injector" in file_json["compatibility"]: + with open(f"{disk}/PEinjector/VERSION", "r", encoding="utf-8") as file: + version = file.readlines()[0].rstrip("\n\r") + if "min" in file_json["compatibility"]["injector"]: + plugver = file_json["compatibility"]["injector"]["min"] + + def vererr(): + log.warn(f"load moudle [{pkg_name}] failed: " + + f"PEinjector version too low, need [{plugver}]") + if int(plugver.split(".")[0]) > int(version.split(".")[0]): + vererr() + return 5 + elif int(plugver.split(".")[0]) == int(version.split(".")[0]): + if plugver.split(".")[1] > version.split(".")[1]: + vererr() + return 5 + elif int(plugver.split(".")[1]) == int(version.split(".")[1]): + if int(plugver.split(".")[2]) > int(version.split(".")[2]): + vererr() + return 5 + if "max" in file_json["compatibility"]["injector"]: + plugver = file_json["compatibility"]["injector"]["max"] + + def vererr(): + log.warn(f"load moudle [{pkg_name}] failed: " + + f"PEinjector version too high, need [{plugver}]") + if int(plugver.split(".")[0]) < int(version.split(".")[0]): + vererr() + return 6 + elif int(plugver.split(".")[0]) == int(version.split(".")[0]): + if int(plugver.split(".")[1] < version.split(".")[1]): + vererr() + return 6 + elif plugver.split(".")[1] == version.split(".")[1]: + if int(plugver.split(".")[2] < version.split(".")[2]): + vererr() + return 6 + except: + log.warn(f"load moudle [{pkg_name}] failed: " + + "The version number is formatted incorrectly") + return 7 + return 0 + + +def file_check(file_json, pkg_name): + try: + if "compatibility" in file_json: + if "file" in file_json["compatibility"]: + if "must" in file_json["compatibility"]["file"]: + for i in file_json["compatibility"]["file"]["must"]: + if not os.path.exists(i): + log.warn(f"load moudle [{pkg_name}] failed: " + + f"Cannot find file: [{i}]") + return 8 + if "mustnot" in file_json["compatibility"]["file"]: + for i in file_json["compatibility"]["file"]["mustnot"]: + if os.path.exists(i): + log.warn(f"load moudle [{pkg_name}] failed: " + + f"Find incompatible file: [{i}]") + return 9 + + except: + log.warn(f"load moudle [{pkg_name}] failed: " + + "Unknown error in file check") + return 10 + return 0 + + +actions = {"onboot": [], "onload": []} + + +def load_package(pkg_name): + pkg_path = f"{disk}/PEinjector/package/{pkg_name}" + loaded_package.append(pkg_name) + if "manifest.json" not in os.listdir(pkg_path): + log.warn(f"load moudle [{pkg_name}] failed: " + + "Cannot find manifest.json") + return 1 + try: + with open(pkg_path+"/"+"manifest.json", "r", encoding="utf-8") as file: + file_str = file.read() + except Exception as exp: + log.warn(f"load moudle [{pkg_name}] failed: " + + "Unknown error in read file ("+repr(exp)+")") + return 2 + try: + file_json = json.loads(file_str) + except: + log.warn(f"load moudle [{pkg_name}] failed: " + + "Json syntax error") + return 3 + for i in ("version", "name", "author", "introduce"): + if i not in file_json: + log.warn(f"load moudle [{pkg_name}] failed: " + + f"\"{i}\" key not in manifest.json") + return 4 + retvar = version_check(file_json, pkg_name) + if retvar != 0: + return retvar + retvar = file_check(file_json, pkg_name) + if retvar != 0: + return retvar + if "dependence" in file_json: + try: + for i in file_json["dependence"]: + if i not in lists: + log.warn(f"load moudle [{pkg_name}] failed: " + + f"Cannot find dependence [{i}]") + return 11 + if retvar in loaderr_pkgs: + log.warn(f"load moudle [{pkg_name}] failed: " + + f"dependence [{i}] loaded failed") + return 12 + if retvar not in loaded_package: + log.info(f"load moudle [{i}] from [{pkg_name}]") + retvar = load_package(i) + if retvar != 0: + loaderr_pkgs.append(i) + log.warn(f"load moudle [{pkg_name}] failed: " + + f"dependence [{i}] loaded failed") + return 12 + except: + log.warn(f"load moudle [{pkg_name}] failed: " + + f"Cannot find dependence [{i}]") + data_list = [] + if "data" in file_json: + j = -1 + prep_flag = False + if pkg_name not in os.listdir(config.DATAPATH.replace("{DISK}", utils.find_disk())): + log.info(f"prep moudle [{pkg_name}] data") + prep_flag = True + for i in file_json["data"]: + j += 1 + flag = False + for event in ("from", "to"): + if event not in i or i[event] == "": + log.warn(f"load moudle [{pkg_name}] warning: " + + f"Load data syntax error on {event}[{j}] (lost \"{event}\"), igrone") + flag = True + break + if flag: + continue + data_list.append(i) + if prep_flag: + data_dir = config.DATAPATH.replace( + "{DISK}", utils.find_disk())+"/"+pkg_name + os.mkdir(data_dir) + if os.path.isfile(pkg_path+"/"+i["from"]): + shutil.copyfile(( + pkg_path+"/"+i["from"]).replace("/", "\\"), (data_dir+"/"+i["to"])) + else: + shutil.copytree( + pkg_path+"/"+i["from"], data_dir+"/"+i["to"]) + + if "load" in file_json: + open_symlink = config.USE_SYMLINK + if "symlink" in file_json["load"] and file_json["load"] == False: + open_symlink = False + if "mode" in file_json["load"]: + for event in ("onboot", "onload"): + if event not in file_json["load"]["mode"]: + continue + actions[event].append((0, pkg_name)) + if type(file_json["load"]["mode"][event]) != list: + log.warn(f"load moudle [{pkg_name}] failed: " + + f"Load commands syntax error on {event} (must be a list)") + return 13 + j = -1 + for i in file_json["load"]["mode"][event]: + j += 1 + if "type" not in i: + log.warn(f"load moudle [{pkg_name}] warning: " + + f"Load commands syntax error on {event}[{j+1}] (lost \"type\"), igrone") + continue + if i["type"] == "force_copy" or (i["type"] == "copy" and open_symlink == False): + flag = False + for check in ("from", "to"): + if check not in i: + flag = True + log.warn(f"load moudle [{pkg_name}] warning: " + + f"Load commands syntax error on {event}[{j+1}] (lost \"{check}\"), igrone") + break + if flag: + continue + if not os.path.exists(pkg_path+"/"+i["from"]): + log.warn(f"load moudle [{pkg_name}] warning: " + + f"Load commands file error on {event}[{j+1}] (cannot find \"{i['from']}\"), igrone") + continue + actions[event] += action.force_copy(pkg_path, + pkg_name, data_list, i["from"], i["to"]) + elif i["type"] == "copy": + flag = False + for check in ("from", "to"): + if check not in i: + flag = True + log.warn(f"load moudle [{pkg_name}] warning: " + + f"Load commands syntax error on {event}[{j+1}] (lost \"{check}\"), igrone") + break + if flag: + continue + if not os.path.exists(pkg_path+"/"+i["from"]): + log.warn(f"load moudle [{pkg_name}] warning: " + + f"Load commands file error on {event}[{j+1}] (cannot find \"{i['from']}\"), igrone") + continue + actions[event] += action.copy(pkg_path, pkg_name, data_list, + i["from"], i["to"]) + elif i["type"] == "start": + flag = False + for check in ("command", ): + if check not in i: + flag = True + log.warn(f"load moudle [{pkg_name}] warning: " + + f"Load commands syntax error on {event}[{j+1}] (lost \"{check}\"), igrone") + break + if flag: + continue + actions[event] += action.start( + pkg_name, data_list, i["command"]) + else: + log.warn(f"load moudle [{pkg_name}] warning: " + + f"Load commands syntax error on {event}[{j+1}] (unknown type), igrone") + + +def load(): + try: + global disk, lists + log.info("start load") + disk = utils.find_disk() + lists = os.listdir(f"{disk}/PEinjector/package") + with open(config.DISABLEPATH.replace("{DISK}", disk), "r") as file: + disable_packages = [i.rstrip("\n\r") for i in file.readlines()] + for packs in lists: + if packs not in loaded_package and packs not in disable_packages: + log.info(f"load moudle [{packs}]") + retvar = load_package(packs) + if retvar == 0: + loaderr_pkgs.append(packs) + filename = action.save_action(actions["onload"]) + alog = action.do_action(actions["onboot"]) + with open(config.ACTIONLOGPATH.replace("{DISK}", utils.find_disk()), "w") as file: + file.write(alog) + os.system(f'..\\env\\pythonw.exe hook.py "{filename}"') + except Exception as exp: + log.break_err("Exception \n"+str(traceback.format_exc(exp))) + raise exp diff --git a/src/log.py b/src/log.py new file mode 100644 index 0000000..f0dc75a --- /dev/null +++ b/src/log.py @@ -0,0 +1,61 @@ +# ------ cxykevin log moudle ------ +# This moudle is not a part of this project. +# This file is CopyNone. + + +import logging +import config +import utils +import sys +levels = { + "debug": logging.DEBUG, + 'info': logging.INFO, + 'warning': logging.WARN, + 'err': logging.ERROR +} + + +def newlog(): + with open(config.LOGPATH.replace("{DISK}", utils.find_disk()), "w") as _: + pass + + +def init(): + logging.basicConfig(filename=config.LOGPATH.replace("{DISK}", utils.find_disk()), + format='[%(asctime)s][%(levelname)s] %(message)s', + level=levels[config.LOGLEVEL]) + + +def info(msg): + if (20 >= levels[config.LOGLEVEL]): + sys.stdout.write( + ("[\033[34mINFO\033[0m]" if config.OUTPUT_COLORFUL else "[INFO]") + msg + "\n") + logging.info(msg) + + +def warn(msg): + if (30 >= levels[config.LOGLEVEL]): + sys.stdout.write( + ("[\033[33mWARNING\033[0m]" if config.OUTPUT_COLORFUL else "[WARNING]") + msg + "\n") + logging.warn(msg) + + +def err(msg): + if (40 >= levels[config.LOGLEVEL]): + sys.stdout.write( + ("[\033[31mERROR\033[0m]" if config.OUTPUT_COLORFUL else "[ERROR]") + msg + "\n") + logging.error(msg) + + +def break_err(msg): + if (40 >= levels[config.LOGLEVEL]): + sys.stdout.write( + ("[\033[31mERROR\033[0m]" if config.OUTPUT_COLORFUL else "[ERROR]") + msg + "\n") + logging.error(msg) + + +def print(*args, end="\n"): + msg = ' '.join(map(str, args)) + if (10 >= levels[config.LOGLEVEL]): + sys.stdout.write(msg + end) + logging.debug(msg) diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..269312d --- /dev/null +++ b/src/main.py @@ -0,0 +1,22 @@ +##################################### +## PEinjector/main ## +##################################### + +# This moudle will load other moudles. +# Do not set any functions in there. + +# load moudles +import sys +import os +sys.path.append("X:\\PEinjector\\src") +sys.path.append("X:\\PEinjector\\tool") +os.chdir("X:\\PEinjector\\src") + +# init log +log = __import__("log") +log.newlog() +log.init() + +# This is written to avoid bad formatting. +# Do not change it. +__import__("loader").load() diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..5df8acf --- /dev/null +++ b/src/utils.py @@ -0,0 +1,15 @@ +##################################### +## PEinjector/utils ## +##################################### + +import os + + +def find_disk(): # This code from dashedgeless + disk_list = "CDEFGHIJKABLMNOPQRSTUVWYZ" + for i in disk_list: + this_disk = i + ":" + if os.path.exists(this_disk + "/PEinjector"): + return this_disk + raise OSError( + "Cannot find the PEinjector disk!") diff --git a/tool/.keep b/tool/.keep new file mode 100644 index 0000000..e69de29 diff --git a/version b/version new file mode 100644 index 0000000..8acdd82 --- /dev/null +++ b/version @@ -0,0 +1 @@ +0.0.1