吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 76|回复: 1
上一主题 下一主题
收起左侧

[资源求助] 能帮忙把PY打包成EXE使用么

[复制链接]
跳转到指定楼层
楼主
asspoo 发表于 2026-7-25 17:13 回帖奖励
100吾爱币


别人分享个工具 但是PY的 没环境 请帮忙打包成可运行的EXE

他这个里面有一个BAT 内容如下

@echo off
setlocal EnableExtensions DisableDelayedExpansion

set "SCRIPT=%~dp0SmartDecrypt.py"

if not exist "%SCRIPT%" goto script_missing

set "INPUT=%~1"

if not defined INPUT (
    echo Drag a file or folder onto this BAT file.
    echo Or enter the full path below.
    echo.
    set /p "INPUT=Input path: "
)

if not defined INPUT goto no_input
if not exist "%INPUT%" goto input_missing

where py >nul 2>&1
if errorlevel 1 goto use_python

py -3 "%SCRIPT%" "%INPUT%" --overwrite
set "CODE=%ERRORLEVEL%"
goto finished

:use_python
where python >nul 2>&1
if errorlevel 1 goto python_missing

python "%SCRIPT%" "%INPUT%" --overwrite
set "CODE=%ERRORLEVEL%"
goto finished

:script_missing
echo [ERROR] SmartDecrypt_Batch_Keep413.py was not found next to this BAT file.
set "CODE=1"
goto finished

:no_input
echo [ERROR] No input file or folder was specified.
set "CODE=1"
goto finished

:input_missing
echo [ERROR] Input path does not exist:
echo "%INPUT%"
set "CODE=1"
goto finished

:python_missing
echo [ERROR] Python was not found.
echo Install Python 3 and enable "Add Python to PATH".
set "CODE=1"
goto finished

:finished
echo.
if "%CODE%"=="0" (
    echo Completed successfully.
    echo The result is stored next to the source with the suffix _smart_removed.
) else (
    echo Failed with exit code %CODE%.
)
echo.
pause
exit /b %CODE%


然后是PY文件
#!/usr/bin/env python3
"""Batch-remove SmartCrypt FF ED FA CE while preserving Lineage2Ver encryption.

This script replaces the original rename-to-SysString-e.dat workflow:

* recursively scans a file or directory;
* recognizes SmartCrypt containers by FF ED FA CE, regardless of filename;
* removes only the outer SmartCrypt layer;
* rebuilds the standard inner Lineage II container:
    mode 1 -> Lineage2Ver111 (XOR 0xAC remains encrypted)
    mode 3 -> Lineage2Ver413 (RSA + zlib remains encrypted)
* keeps original filenames and directory structure;
* copies non-SmartCrypt files unchanged by default.

The output is suitable for tools that expect the original Lineage2Ver111/413
container instead of a fully decoded raw DAT/Unreal package.
"""

from __future__ import annotations

import argparse
import csv
import os
import shutil
import struct
import sys
import tempfile
import zlib
from dataclasses import dataclass
from pathlib import Path
from typing import BinaryIO, Iterable

SMART_MAGIC = bytes.fromhex("FF ED FA CE")
SMART_HEADER_SIZE = 28
SMART_TAIL_SIZE = 20
LINEAGE_TAIL_SIZE = 20
LINEAGE_CRC_OFFSET = 12
STREAM_PERIOD = 768  # lcm(6, 16, 256)
DEFAULT_CHUNK_SIZE = 4 * 1024 * 1024

MODE_TO_PROTOCOL = {
    1: 111,
    3: 413,
}


class SmartDecryptError(RuntimeError):
    """Expected input/format error."""


@dataclass(frozen=True)
class SmartHeader:
    mode: int
    protocol: int
    key6: bytes
    key16: bytes


@dataclass
class ReportRow:
    status: str
    mode: str
    protocol: str
    source: str
    destination: str
    size: int
    message: str = ""


def lineage_header(protocol: int) -> bytes:
    """Build UTF-16LE Lineage2VerXXX header (28 bytes for 3-digit protocols)."""
    text = f"Lineage2Ver{protocol}"
    encoded = text.encode("utf-16le")
    if len(encoded) != SMART_HEADER_SIZE:
        raise SmartDecryptError(
            f"Unexpected Lineage header size for protocol {protocol}: {len(encoded)}"
        )
    return encoded


def lineage_tail(crc32_value: int) -> bytes:
    """Build the standard 20-byte Lineage tail with CRC32 at offset 12."""
    tail = bytearray(LINEAGE_TAIL_SIZE)
    struct.pack_into("<I", tail, LINEAGE_CRC_OFFSET, crc32_value & 0xFFFFFFFF)
    return bytes(tail)


def parse_smart_header(header: bytes) -> SmartHeader:
    """Decode the 28-byte FF ED FA CE header and recover its two stream keys."""
    if len(header) != SMART_HEADER_SIZE:
        raise SmartDecryptError(
            f"Short SmartCrypt header: expected {SMART_HEADER_SIZE}, got {len(header)}"
        )
    if header[:4] != SMART_MAGIC:
        raise SmartDecryptError("Not an FF ED FA CE SmartCrypt file")

    mode = int.from_bytes(header[4:6], "little")
    protocol = MODE_TO_PROTOCOL.get(mode)
    if protocol is None:
        raise SmartDecryptError(f"Unsupported SmartCrypt mode: {mode}")

    mode_byte = mode & 0xFF
    key6 = bytes(value ^ mode_byte for value in header[6:12])
    key16 = bytes(header[12 + i] ^ key6[i % 6] for i in range(16))
    return SmartHeader(mode=mode, protocol=protocol, key6=key6, key16=key16)


def make_stream_table(key6: bytes, key16: bytes) -> bytes:
    """Precompute one full period of the positional SmartCrypt XOR stream."""
    if len(key6) != 6 or len(key16) != 16:
        raise SmartDecryptError("Invalid SmartCrypt key lengths")

    return bytes(
        key6[pos % 6]
        ^ key16[pos & 0x0F]
        ^ ((((pos & 0xFF) ^ 0x65) * 0x93) & 0xFF)
        for pos in range(STREAM_PERIOD)
    )


def xor_stream_chunk(chunk: bytes, absolute_position: int, table: bytes) -> bytes:
    """Apply the SmartCrypt stream to a chunk at its absolute file position."""
    period = len(table)
    start = absolute_position % period
    rotated = table[start:] + table[:start]
    repeats, remainder = divmod(len(chunk), period)
    key_stream = rotated * repeats + rotated[:remainder]
    return bytes(value ^ key for value, key in zip(chunk, key_stream))


def smart_file_info(path: Path) -> SmartHeader | None:
    """Return parsed SmartCrypt metadata, or None for a non-SmartCrypt file."""
    try:
        with path.open("rb") as stream:
            header = stream.read(SMART_HEADER_SIZE)
    except OSError as exc:
        raise SmartDecryptError(f"Cannot read {path}: {exc}") from exc

    if len(header) < 4 or header[:4] != SMART_MAGIC:
        return None
    return parse_smart_header(header)


def atomic_destination(destination: Path) -> tuple[Path, BinaryIO]:
    """Create a temporary file beside destination for atomic replacement."""
    destination.parent.mkdir(parents=True, exist_ok=True)
    fd, temporary_name = tempfile.mkstemp(
        prefix=f".{destination.name}.", suffix=".tmp", dir=destination.parent
    )
    return Path(temporary_name), os.fdopen(fd, "wb")


def remove_smartcrypt(
    source: Path,
    destination: Path,
    *,
    overwrite: bool = False,
    chunk_size: int = DEFAULT_CHUNK_SIZE,
) -> SmartHeader:
    """Remove only FFEDFACE and rebuild Lineage2Ver111/413 around the inner body."""
    file_size = source.stat().st_size
    minimum_size = SMART_HEADER_SIZE + SMART_TAIL_SIZE
    if file_size < minimum_size:
        raise SmartDecryptError(
            f"File is too small: {file_size} bytes, expected at least {minimum_size}"
        )
    if destination.exists() and not overwrite:
        raise SmartDecryptError(f"Destination already exists: {destination}")
    if chunk_size <= 0:
        raise SmartDecryptError("Chunk size must be positive")

    temporary_path: Path | None = None
    try:
        with source.open("rb") as input_stream:
            smart_header_raw = input_stream.read(SMART_HEADER_SIZE)
            smart_header = parse_smart_header(smart_header_raw)
            table = make_stream_table(smart_header.key6, smart_header.key16)

            body_size = file_size - SMART_HEADER_SIZE - SMART_TAIL_SIZE
            standard_header = lineage_header(smart_header.protocol)
            crc = zlib.crc32(standard_header)

            temporary_path, output_stream = atomic_destination(destination)
            with output_stream:
                output_stream.write(standard_header)

                remaining = body_size
                absolute_position = SMART_HEADER_SIZE
                while remaining:
                    encrypted_chunk = input_stream.read(min(chunk_size, remaining))
                    if not encrypted_chunk:
                        raise SmartDecryptError(
                            f"Unexpected end of file while reading {source}"
                        )
                    decrypted_chunk = xor_stream_chunk(
                        encrypted_chunk, absolute_position, table
                    )
                    output_stream.write(decrypted_chunk)
                    crc = zlib.crc32(decrypted_chunk, crc)
                    absolute_position += len(encrypted_chunk)
                    remaining -= len(encrypted_chunk)

                smart_tail = input_stream.read(SMART_TAIL_SIZE)
                if len(smart_tail) != SMART_TAIL_SIZE:
                    raise SmartDecryptError(
                        f"Missing {SMART_TAIL_SIZE}-byte SmartCrypt tail"
                    )
                if input_stream.read(1):
                    raise SmartDecryptError("Unexpected data after SmartCrypt tail")

                output_stream.write(lineage_tail(crc))
                output_stream.flush()
                os.fsync(output_stream.fileno())

        if destination.exists() and overwrite:
            destination.unlink()
        os.replace(temporary_path, destination)
        temporary_path = None

        # Preserve source timestamps where possible.
        try:
            shutil.copystat(source, destination)
        except OSError:
            pass

        return smart_header
    finally:
        if temporary_path is not None:
            try:
                temporary_path.unlink(missing_ok=True)
            except OSError:
                pass


def verify_lineage_container(path: Path, expected_protocol: int | None = None) -> None:
    """Verify rebuilt header, total size and CRC32 without removing inner encryption."""
    size = path.stat().st_size
    if size < SMART_HEADER_SIZE + LINEAGE_TAIL_SIZE:
        raise SmartDecryptError(f"Output is too small: {path}")

    with path.open("rb") as stream:
        header = stream.read(SMART_HEADER_SIZE)
        try:
            header_text = header.decode("utf-16le")
        except UnicodeDecodeError as exc:
            raise SmartDecryptError(f"Invalid Lineage header in {path}") from exc

        if not header_text.startswith("Lineage2Ver"):
            raise SmartDecryptError(f"Missing Lineage2Ver header in {path}")
        try:
            protocol = int(header_text[len("Lineage2Ver") :])
        except ValueError as exc:
            raise SmartDecryptError(f"Invalid protocol in {path}: {header_text!r}") from exc
        if expected_protocol is not None and protocol != expected_protocol:
            raise SmartDecryptError(
                f"Protocol mismatch in {path}: expected {expected_protocol}, got {protocol}"
            )

        remaining_without_tail = size - SMART_HEADER_SIZE - LINEAGE_TAIL_SIZE
        crc = zlib.crc32(header)
        while remaining_without_tail:
            chunk = stream.read(min(DEFAULT_CHUNK_SIZE, remaining_without_tail))
            if not chunk:
                raise SmartDecryptError(f"Unexpected end of rebuilt file: {path}")
            crc = zlib.crc32(chunk, crc)
            remaining_without_tail -= len(chunk)

        tail = stream.read(LINEAGE_TAIL_SIZE)
        stored_crc = struct.unpack_from("<I", tail, LINEAGE_CRC_OFFSET)[0]
        if stored_crc != (crc & 0xFFFFFFFF):
            raise SmartDecryptError(
                f"CRC mismatch in {path}: stored {stored_crc:08X}, calculated {crc:08X}"
            )


def iter_files(root: Path, recursive: bool) -> Iterable[Path]:
    if root.is_file():
        yield root
        return
    iterator = root.rglob("*") if recursive else root.glob("*")
    for path in sorted(iterator):
        if path.is_file():
            yield path


def default_output_path(input_path: Path) -> Path:
    if input_path.is_file():
        return input_path.with_name(f"{input_path.stem}_smart_removed{input_path.suffix}")
    return input_path.with_name(f"{input_path.name}_smart_removed")


def write_report(output_root: Path, rows: list[ReportRow]) -> Path:
    report_path = output_root / "SmartDecrypt_report.csv"
    report_path.parent.mkdir(parents=True, exist_ok=True)
    with report_path.open("w", encoding="utf-8-sig", newline="") as stream:
        writer = csv.writer(stream, delimiter=";")
        writer.writerow(
            ["status", "mode", "protocol", "source", "destination", "size", "message"]
        )
        for row in rows:
            writer.writerow(
                [
                    row.status,
                    row.mode,
                    row.protocol,
                    row.source,
                    row.destination,
                    row.size,
                    row.message,
                ]
            )
    return report_path


def process(
    input_path: Path,
    output_path: Path,
    *,
    recursive: bool,
    copy_plain: bool,
    overwrite: bool,
    verify: bool,
) -> tuple[list[ReportRow], int]:
    rows: list[ReportRow] = []
    errors = 0

    input_resolved = input_path.resolve()
    output_resolved = output_path.resolve()
    if input_resolved == output_resolved:
        raise SmartDecryptError("Input and output paths must be different")

    is_single_file = input_path.is_file()
    if not is_single_file:
        output_path.mkdir(parents=True, exist_ok=True)

    for source in iter_files(input_path, recursive):
        # Protect against an output folder located inside the scanned input tree.
        try:
            source.resolve().relative_to(output_resolved)
            continue
        except ValueError:
            pass

        relative = Path(source.name) if is_single_file else source.relative_to(input_path)
        destination = output_path if is_single_file else output_path / relative

        try:
            info = smart_file_info(source)
            if info is not None:
                result = remove_smartcrypt(
                    source, destination, overwrite=overwrite
                )
                if verify:
                    verify_lineage_container(destination, result.protocol)
                print(
                    f"[SMART] mode={result.mode} -> Lineage2Ver{result.protocol}: "
                    f"{relative}"
                )
                rows.append(
                    ReportRow(
                        status="decrypted",
                        mode=str(result.mode),
                        protocol=str(result.protocol),
                        source=str(source),
                        destination=str(destination),
                        size=destination.stat().st_size,
                    )
                )
            elif copy_plain:
                destination.parent.mkdir(parents=True, exist_ok=True)
                if destination.exists() and not overwrite:
                    raise SmartDecryptError(f"Destination already exists: {destination}")
                shutil.copy2(source, destination)
                print(f"[COPY]  {relative}")
                rows.append(
                    ReportRow(
                        status="copied",
                        mode="",
                        protocol="",
                        source=str(source),
                        destination=str(destination),
                        size=destination.stat().st_size,
                    )
                )
            else:
                print(f"[SKIP]  {relative}")
                rows.append(
                    ReportRow(
                        status="skipped",
                        mode="",
                        protocol="",
                        source=str(source),
                        destination="",
                        size=source.stat().st_size,
                        message="Not an FF ED FA CE SmartCrypt file",
                    )
                )
        except (OSError, SmartDecryptError) as exc:
            errors += 1
            print(f"[ERROR] {relative}: {exc}", file=sys.stderr)
            rows.append(
                ReportRow(
                    status="error",
                    mode="",
                    protocol="",
                    source=str(source),
                    destination=str(destination),
                    size=source.stat().st_size if source.exists() else 0,
                    message=str(exc),
                )
            )

    return rows, errors


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        description=(
            "Recursively remove FFEDFACE SmartCrypt while preserving inner "
            "Lineage2Ver111/413 encryption and original filenames."
        )
    )
    parser.add_argument("input", type=Path, help="Input file or directory")
    parser.add_argument(
        "output",
        type=Path,
        nargs="?",
        help="Output file/directory; default: <input>_smart_removed",
    )
    parser.add_argument(
        "--no-recursive",
        action="store_true",
        help="Process only files directly inside the input directory",
    )
    parser.add_argument(
        "--smart-only",
        action="store_true",
        help="Do not copy files that are not FFEDFACE SmartCrypt",
    )
    parser.add_argument(
        "--overwrite",
        action="store_true",
        help="Overwrite existing output files",
    )
    parser.add_argument(
        "--no-verify",
        action="store_true",
        help="Skip output Lineage header/CRC verification",
    )
    return parser


def main() -> int:
    parser = build_parser()
    args = parser.parse_args()

    input_path = args.input.expanduser()
    if not input_path.exists():
        print(f"[ERROR] Input does not exist: {input_path}", file=sys.stderr)
        return 2

    output_path = (
        args.output.expanduser()
        if args.output is not None
        else default_output_path(input_path)
    )

    try:
        rows, errors = process(
            input_path,
            output_path,
            recursive=not args.no_recursive,
            copy_plain=not args.smart_only,
            overwrite=args.overwrite,
            verify=not args.no_verify,
        )

        if input_path.is_dir():
            report_path = write_report(output_path, rows)
            print(f"[REPORT] {report_path}")

        decrypted = sum(row.status == "decrypted" for row in rows)
        copied = sum(row.status == "copied" for row in rows)
        skipped = sum(row.status == "skipped" for row in rows)
        print(
            f"[DONE] decrypted={decrypted}, copied={copied}, "
            f"skipped={skipped}, errors={errors}"
        )
        return 1 if errors else 0
    except (OSError, SmartDecryptError) as exc:
        print(f"[ERROR] {exc}", file=sys.stderr)
        return 1


if __name__ == "__main__":
    raise SystemExit(main())



一起打包放在下面的地址里面




https://wwawu.lanzouu.com/i7Kxh3yl6ocb

最佳答案

查看完整内容

https://wwbaw.lanzoue.com/iGV3h3yma64f 密码:2hb1

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
shzjz123 发表于 2026-7-25 17:13

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
asspoo + 1 + 1 谢谢@Thanks!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-26 10:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表