Compare commits
4 Commits
ae82712c59
...
8c46b62352
| Author | SHA1 | Date | |
|---|---|---|---|
|
8c46b62352
|
|||
|
d0d3f74733
|
|||
|
ec8581104d
|
|||
|
236233bb17
|
@@ -85,6 +85,33 @@ class RuntimeInfo:
|
||||
def mix_str_aes_nonce(self) -> bytes:
|
||||
return self.part_3[:12]
|
||||
|
||||
@classmethod
|
||||
def default(cls) -> 'RuntimeInfo':
|
||||
instance = cls.__new__(cls)
|
||||
instance.file_path = '<default>'
|
||||
instance.part_1 = b'pyarmor-vax-000000\x00\x00'
|
||||
instance.part_2 = bytes.fromhex('''
|
||||
30 81 89 02 81 81 00 A8 ED 64 F4 83 49 13 FC 0F
|
||||
86 6F 00 5A 8F E4 91 AA ED 1C EA D4 BB 4C 3F 7C
|
||||
24 21 01 A8 D0 7D 93 F4 BF E7 FB 8C 06 57 88 6A
|
||||
2E 9B 54 53 D5 7B 8F F6 83 DF 72 00 42 A3 2D 18
|
||||
30 AD 3A E4 F1 E4 3A 3C 8C EA F5 46 F3 BB 75 62
|
||||
11 84 FB 3F 3B 4C 35 61 4E 46 A1 E0 9E 3C B6 7A
|
||||
BA 52 C5 B6 40 F6 AD AB BC D5 CF 5B 40 CB 8D 13
|
||||
C4 28 B8 90 93 C4 76 01 09 8E 05 1E 61 FA 90 4C
|
||||
BF 67 D4 A7 D5 82 C1 02 03 01 00 01
|
||||
''')
|
||||
instance.part_3 = bytes.fromhex('''
|
||||
69 2E 6E 6F 6E 2D 70 72 6F 66 69 74 73 E7 5A 41
|
||||
9B DC 77 53 CA 1D E7 04 EB EF DA C9 A3 6C 0F 7B
|
||||
00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00
|
||||
''')
|
||||
instance.serial_number = '000000'
|
||||
instance.runtime_aes_key = instance.calc_aes_key()
|
||||
return instance
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
@@ -122,7 +122,7 @@ async def decrypt_process_async(runtimes: Dict[str, RuntimeInfo], sequences: Lis
|
||||
bcc_architecture_id = int.from_bytes(bcc_aes_decrypted[8:12], 'little')
|
||||
bcc_next_segment_offset = int.from_bytes(bcc_aes_decrypted[12:16], 'little')
|
||||
bcc_architecture = bcc_architecture_mapping.get(bcc_architecture_id, f'0x{bcc_architecture_id:x}')
|
||||
bcc_file_path = f'{dest_path}.1shot.bcc.{bcc_architecture}.elf'
|
||||
bcc_file_path = f'{dest_path}.1shot.bcc.{bcc_architecture}.so'
|
||||
with open(bcc_file_path, 'wb') as f:
|
||||
f.write(bcc_aes_decrypted[bcc_segment_offset:bcc_segment_offset+bcc_segment_length])
|
||||
logger.info(f'{Fore.GREEN}Extracted BCC mode native part: {bcc_file_path}{Style.RESET_ALL}')
|
||||
@@ -288,7 +288,7 @@ def main():
|
||||
| | |_| \_, |\__,_|_| |_||_||_|\___/|_| |_|___/|_||_|\___/ \__| | |
|
||||
| | |__/ | |
|
||||
|__|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|__|
|
||||
(____) v0.2.0+ (____)
|
||||
(____) v0.2.1 (____)
|
||||
|
||||
For technology exchange only. Use at your own risk.
|
||||
GitHub: https://github.com/Lil-House/Pyarmor-Static-Unpack-1shot
|
||||
@@ -300,7 +300,7 @@ def main():
|
||||
runtimes = {specified_runtime.serial_number: specified_runtime}
|
||||
else:
|
||||
specified_runtime = None
|
||||
runtimes = {}
|
||||
runtimes = {'000000': RuntimeInfo.default()}
|
||||
|
||||
sequences: List[Tuple[str, bytes]] = []
|
||||
|
||||
|
||||
@@ -170,7 +170,11 @@ void CallOrPyarmorBuiltins(FastStack &stack, PycRef<ASTBlock> &curblock, PycModu
|
||||
return;
|
||||
|
||||
PycRef<PycString> func_name = call->func().cast<ASTObject>()->object().try_cast<PycString>();
|
||||
if (func_name == nullptr || !func_name->startsWith("__pyarmor_"))
|
||||
if (
|
||||
func_name == nullptr
|
||||
|| !func_name->startsWith("__pyarmor_")
|
||||
|| func_name->startsWith("__pyarmor_bcc_")
|
||||
)
|
||||
return;
|
||||
|
||||
const std::string& name = func_name->strValue();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "ASTree.h"
|
||||
|
||||
const char* VERSION = "v0.2.0+";
|
||||
const char* VERSION = "v0.2.1";
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
@@ -76,12 +76,15 @@ int main(int argc, char* argv[])
|
||||
|
||||
const char* dispname = strrchr(infile, PATHSEP);
|
||||
dispname = (dispname == NULL) ? infile : dispname + 1;
|
||||
const char* disp_prefix = strrchr(prefix_name.c_str(), PATHSEP);
|
||||
disp_prefix = (disp_prefix == NULL) ? prefix_name.c_str() : disp_prefix + 1;
|
||||
|
||||
formatted_print(
|
||||
das_out_file,
|
||||
R"(# Disassembly generated by Pyarmor-Static-Unpack-1shot (%s), powered by pycdas
|
||||
# File: %s (Python %d.%d)
|
||||
R"(# File: %s (Python %d.%d)
|
||||
# Disassembly generated by Pyarmor-Static-Unpack-1shot (%s), powered by pycdas
|
||||
|
||||
# ================================
|
||||
# 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.
|
||||
@@ -89,18 +92,19 @@ int main(int argc, char* argv[])
|
||||
# Decompilation guidance (without runtime):
|
||||
# 1. Ignore encrypted bytes after `#`; use only the string before `#`.
|
||||
# 2. Remove `"__pyarmor_enter_xxx__"(b"<COAddr>...")` and `"__pyarmor_leave_xxx__"(b"<COAddr>...")` (prologue/epilogue).
|
||||
# 3. For `"__pyarmor_assert_xxx__"(A)`, it is not a real assert statement.
|
||||
# 3. `"__pyarmor_assert_xxx__"(A)` 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()
|
||||
mod.minorVer(),
|
||||
VERSION
|
||||
);
|
||||
try {
|
||||
output_object(mod.code().try_cast<PycObject>(), &mod, 0, disasm_flags,
|
||||
@@ -115,18 +119,18 @@ int main(int argc, char* argv[])
|
||||
|
||||
formatted_print(
|
||||
dc_out_file,
|
||||
R"(# Source generated by Pyarmor-Static-Unpack-1shot (%s), powered by Decompyle++ (pycdc)
|
||||
# File: %s (Python %d.%d)
|
||||
R"(# File: %s (Python %d.%d)
|
||||
# Source generated by Pyarmor-Static-Unpack-1shot (%s), powered by Decompyle++ (pycdc)
|
||||
|
||||
# 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()
|
||||
VERSION,
|
||||
disp_prefix
|
||||
);
|
||||
try {
|
||||
decompyle(mod.code(), &mod, dc_out_file);
|
||||
|
||||
Reference in New Issue
Block a user