Initial public release: dockerized reverse-engineering workbench
ChipBench packages Ghidra, radare2, binwalk, chip-programming tools,
simulators, and firmware-unpacking utilities into one reproducible container
for analyzing raw chip dumps entirely from the command line or an AI CLI.
Headless Jython scripts drive import, forced-disassembly sweeps, live
queries, and bulk decompilation exports without any GUI.
Derived from a private engagement environment, generalized for public
release under AGPLv3. No engagement-specific artifacts are included.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Part of ChipBench (AGPLv3). SPDX-FileCopyrightText: 2026 Starting Line Productions LLC
|
||||
# AutoFuncs.py -- create functions at every LCALL/LJMP target + scheduler
|
||||
# jumptable entries, iterating until stable. Handles call tables (JMP @A+DPTR)
|
||||
# where the table entries are LJMPs by treating table bodies as code.
|
||||
from ghidra.program.model.address import AddressSet
|
||||
from ghidra.app.cmd.function import CreateFunctionCmd
|
||||
from ghidra.app.cmd.disassemble import DisassembleCommand
|
||||
from ghidra.app.plugin.core.analysis import AutoAnalysisManager
|
||||
|
||||
prog = currentProgram
|
||||
af = prog.getAddressFactory()
|
||||
cs = af.getDefaultAddressSpace()
|
||||
fm = prog.getFunctionManager()
|
||||
mem = prog.getMemory()
|
||||
|
||||
def A(x): return cs.getAddress(x)
|
||||
|
||||
def mk(a):
|
||||
if a < 0x10000 and fm.getFunctionAt(a) is None:
|
||||
CreateFunctionCmd(a).applyTo(prog, monitor)
|
||||
|
||||
rounds = 0
|
||||
prev = -1
|
||||
while rounds < 4:
|
||||
n = 0
|
||||
for i in range(0x0000, 0xEE00):
|
||||
try:
|
||||
b = mem.getByte(A(i)) & 0xFF
|
||||
except:
|
||||
continue
|
||||
if b == 0x12 or b == 0x02: # LCALL/LJMP
|
||||
try:
|
||||
hi = mem.getByte(A(i+1)) & 0xFF
|
||||
lo = mem.getByte(A(i+2)) & 0xFF
|
||||
except:
|
||||
continue
|
||||
t = (hi << 8) | lo
|
||||
if 0x0008 <= t < 0xEE00:
|
||||
if fm.getFunctionAt(A(t)) is None:
|
||||
if CreateFunctionCmd(A(t)).applyTo(prog, monitor):
|
||||
n += 1
|
||||
# reanalyze
|
||||
mgr = AutoAnalysisManager.getAnalysisManager(prog)
|
||||
mgr.reAnalyzeAll(None)
|
||||
mgr.startAnalysis(monitor)
|
||||
cur = fm.getFunctionCount()
|
||||
print("round %d: +%d new, total %d" % (rounds, n, cur))
|
||||
if cur == prev:
|
||||
break
|
||||
prev = cur
|
||||
rounds += 1
|
||||
|
||||
print("AutoFuncs done: %d functions, %d instructions" % (
|
||||
fm.getFunctionCount(), prog.getListing().getNumInstructions()))
|
||||
Reference in New Issue
Block a user