From ae82712c59758731437799398ddeb51ba32636b0 Mon Sep 17 00:00:00 2001 From: Lil-Ran Date: Sun, 12 Oct 2025 15:37:07 +0800 Subject: [PATCH] feat: prompt & version output; note for ctf challenge makers --- README.md | 6 +++++ oneshot/shot.py | 2 +- pycdc/pyarmor-1shot.cpp | 49 +++++++++++++++++++++++++++++++++++------ 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2351f7c..da59156 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,12 @@ Feel free to open an issue if you have any questions, suggestions, or problems. - [ ] Regenerate pyc for other backends - [ ] Documentation (Do not accept PR about this) +## For CTF Challenge Makers + +Please, don't make CTF (Capture The Flag) **REVERSE** challenges that are about finding and using existing **TOOLS**. It is not fun for anyone. It is more like a game of hide-and-seek, rather than a test of skill and ingenuity. + +It is more meaningful to understand how Pyarmor or this tool works, and then try to improve them. + ## Star Chart [![Stargazers over time](https://starchart.cc/Lil-House/Pyarmor-Static-Unpack-1shot.svg?variant=adaptive)](https://starchart.cc/Lil-House/Pyarmor-Static-Unpack-1shot) diff --git a/oneshot/shot.py b/oneshot/shot.py index a8cf376..b527cc2 100644 --- a/oneshot/shot.py +++ b/oneshot/shot.py @@ -288,7 +288,7 @@ def main(): | | |_| \_, |\__,_|_| |_||_||_|\___/|_| |_|___/|_||_|\___/ \__| | | | | |__/ | | |__|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|__| -(____) (____) +(____) v0.2.0+ (____) For technology exchange only. Use at your own risk. GitHub: https://github.com/Lil-House/Pyarmor-Static-Unpack-1shot diff --git a/pycdc/pyarmor-1shot.cpp b/pycdc/pyarmor-1shot.cpp index 501ec85..23126f1 100644 --- a/pycdc/pyarmor-1shot.cpp +++ b/pycdc/pyarmor-1shot.cpp @@ -7,6 +7,8 @@ #include "ASTree.h" +const char* VERSION = "v0.2.0+"; + int main(int argc, char* argv[]) { const char* infile = nullptr; @@ -75,9 +77,31 @@ int main(int argc, char* argv[]) const char* dispname = strrchr(infile, PATHSEP); dispname = (dispname == NULL) ? infile : dispname + 1; - formatted_print(das_out_file, "%s (Python %d.%d%s)\n", dispname, - mod.majorVer(), mod.minorVer(), - (mod.majorVer() < 3 && mod.isUnicode()) ? " -U" : ""); + formatted_print( + das_out_file, + R"(# Disassembly generated by Pyarmor-Static-Unpack-1shot (%s), powered by pycdas +# File: %s (Python %d.%d) + +# Pyarmor notes: +# - Pyarmor bytecode and code objects match standard Python, but special calls to Pyarmor runtime functions exist. +# - Calls on strings are not mistakes but markers, which are processed by Pyarmor at runtime. +# +# Decompilation guidance (without runtime): +# 1. Ignore encrypted bytes after `#`; use only the string before `#`. +# 2. Remove `"__pyarmor_enter_xxx__"(b"...")` and `"__pyarmor_leave_xxx__"(b"...")` (prologue/epilogue). +# 3. For `"__pyarmor_assert_xxx__"(A)`, it is not a real assert statement. +# - If `A` is a name or readable string: replace with `A`. +# - If `A` is `(X, "Y")`: replace with `X.Y`. +# - If `A` is `(X, "Y", Z)`: replace with `X.Y = Z`. +# - Otherwise: choose the most reasonable replacement. +# 4. `"__pyarmor_bcc_xxx__"(...)` indicates native code; function body is not available. Add a comment. + +)", + VERSION, + dispname, + mod.majorVer(), + mod.minorVer() + ); try { output_object(mod.code().try_cast(), &mod, 0, disasm_flags, das_out_file); @@ -89,10 +113,21 @@ int main(int argc, char* argv[]) das_out_file.flush(); das_out_file.close(); - dc_out_file << "# Source Generated with Decompyle++\n"; - formatted_print(dc_out_file, "# File: %s (Python %d.%d%s)\n\n", dispname, - mod.majorVer(), mod.minorVer(), - (mod.majorVer() < 3 && mod.isUnicode()) ? " Unicode" : ""); + formatted_print( + dc_out_file, + R"(# Source generated by Pyarmor-Static-Unpack-1shot (%s), powered by Decompyle++ (pycdc) +# File: %s (Python %d.%d) + +# Note: Decompiled code can be incomplete and incorrect. +# Please also check the correct and complete disassembly file: %s.das + +)", + VERSION, + dispname, + mod.majorVer(), + mod.minorVer(), + prefix_name.c_str() + ); try { decompyle(mod.code(), &mod, dc_out_file); } catch (std::exception& ex) {