Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

malconsole

A single msfconsole-style terminal for static reverse-engineering and malware triage — sandboxed by default, with a one-command report at the end.

License: MIT

A single, msfconsole-style terminal for static reverse-engineering / malware-triage work, so you're not juggling strings, pefile scripts, yara, objdump, and a hash calculator across five terminal tabs.

mal> load /path/to/sample.exe
✓ loaded /path/to/sample.exe

╭─────────────────────────── ACTIVE SAMPLE ────────────────────────────╮
│   file  /path/to/sample.exe          type  PE (Windows executable)   │
│   size  142,312 bytes             entropy  6.94                      │
│    md5  3d483dcf565eca2fc27...      sha1  e6da1ac2ebc3946c8d...      │
│ sha256  53a9c0557a948069d5...    loaded  2026-08-05 07:03:39 UTC     │
╰──────────────────────────────────────────────────────────────────────╯
mal> use static/pe_info
✓ using static/pe_info
mal(static/pe_info)> run
...

The sample card is reprinted right above the prompt after every command, so you can scroll back through pages of module output and still glance up to see exactly what you're working on — no full-screen TUI, no lost scrollback.

Install & run

Recommended: run it sandboxed (Docker). This is the path to use whenever you're pointing malconsole at an actual untrusted sample — see Sandboxing below for exactly what isolation this gives you and why it matters.

./scripts/run-sandboxed.sh                      # builds the image on first run, drops you into mal>
./scripts/run-sandboxed.sh /path/to/sample.exe   # same, with the sample bind-mounted read-only

Local install, for module development or trusted samples only:

pip install -r requirements.txt
# or, editable install with a `malconsole` command on your PATH:
pip install -e .[full]

python -m malconsole.main
# or, if installed: malconsole

Every analysis module degrades gracefully: if pefile, pyelftools, capstone, yara-python, or fpdf2 isn't installed, that module (or the PDF half of report save) simply won't be available (or will tell you what to pip install if you try to use it). The core console only needs rich and prompt_toolkit.

Command reference (msf-style)

command what it does
load <path> load a sample into the active session (hashes it, sniffs filetype, computes entropy)
use <module/path> select a module — tab-complete works
show modules list every available module
show options / options show the current module's options
show info / info details about the current module
set <OPT> <value> set an option on the current module
unset <OPT> clear an option
run (alias exploit, if you're feeling nostalgic) execute the current module
back leave the current module
search <term> search modules by name/description
sandbox check whether this session looks isolated (VM/container)
report status show what's been collected for the report so far
report save <path> write the report — .md or .pdf, inferred from the extension
card / status reprint the sample card on demand
clear clear the scrollback
exit / quit leave

Tab completion covers commands, module paths (use ), option names (set /unset ), and filesystem paths (load ).

Modules that ship in v1

  • static/pe_info — PE headers, sections (with per-section entropy, handy for spotting packed sections), imports, exports.
  • static/elf_info — ELF headers, sections, program headers, DT_NEEDED libraries.
  • hashing/hashes — md5/sha1/sha256/sha512, PE imphash, and ssdeep fuzzy hashing if installed.
  • strings/extract — ASCII + UTF-16LE string extraction with an IOC pass (IPv4s, URLs, domains, emails, registry paths, Windows file paths).
  • yara_scan/scan — compiles and runs YARA rules against the loaded sample. Ships with no bundled signatures — point RULES at your own rule file/directory.
  • disasm/capstone_view — read-only Capstone disassembly of a named PE/ELF section, or a manual offset/length/arch. Same category of tool as objdump -d; it never executes the bytes it decodes.

Sandboxing

malconsole itself never executes a loaded sample — every module only reads it as bytes (hashing, header parsing, string extraction, disassembly for display). That keeps the tool's own behavior predictable, but the parsing libraries it calls (pefile, pyelftools, capstone, yara-python) are still processing attacker-controlled, potentially malformed files, and malformed-file parser bugs are a real, recurring class of issue across the industry (this tool and IDA/Ghidra/radare2 alike). So: isolate the environment, not just the code.

1. Run the console itself inside the provided container.

./scripts/run-sandboxed.sh /path/to/sample.exe

This builds Dockerfile (a non-root user, minimal base) and runs it with --network none --read-only --cap-drop ALL --security-opt no-new-privileges --pids-limit 256, your sample bind-mounted read-only at /samples, and only ./reports on the host writable (bind-mounted at /reports in the container). If you'd rather run docker yourself, copy the flags out of scripts/run-sandboxed.sh directly.

2. Or run it inside a dedicated analysis VM (REMnux, FLARE-VM, or your own snapshot-and-revert Linux/Windows VM) if you want to pair it with GUI RE tools — container isolation and VM isolation both work, containers are just faster to spin up.

3. Either way, check your isolation from inside the console:

mal> sandbox
✓ environment looks isolated
container: yes (/.dockerenv present)
virtual machine: unknown
running as root: no
platform: Linux-6.x-x86_64-with-glibc2.39

This runs automatically at startup too. It's a best-effort, read-only, no-network check (container markers, VM/DMI signals, root/uid 0) — a heads-up if something looks like bare metal, not a gate. It never blocks load or run.

Report generation

Every time you run a module, its structured findings (not just the printed tables — the underlying data) are captured into the session. When you're done poking around:

mal> report status                       # see what's been collected + running risk signal
mal> report save findings.md             # Markdown - always works, zero extra deps
mal> report save findings.pdf            # PDF - needs fpdf2 (pip install fpdf2)

Either format includes: sample metadata and hashes, a Key Evidence section (the concrete proof behind each finding — matched YARA rule names, watchlisted API imports, packed-section entropy values, IOC matches — the "PoC" a triage report needs), every module's full output table by table, a consolidated IOC list, an auto-generated risk signal + recommendations based on what was actually found, and an appendix with the full command log for reproducibility.

It's explicitly labeled as an automated static-analysis aid throughout — it flags signals and cites the evidence for each one, it doesn't hand you a verdict.

Adding your own module

Drop a file under malconsole/modules/<category>/your_module.py:

from ...core.module_base import BaseModule
from ...core import ui

class MyModule(BaseModule):
    name = "My Module"
    description = "One line describing what it does."
    category = "misc"

    def __init__(self):
        super().__init__()
        self.register_option("FILE", required=True, description="...")

    def run(self, session, out=ui):
        out.info("hello from my module")

MODULE = MyModule  # required - this is what the registry looks for

It'll show up automatically under show modules as misc/your_module next time you start the console — no registration step needed. If a module's real dependency is missing, it's simply skipped at discovery time rather than crashing the console.

Security notes

A few things worth knowing before you point this at live samples:

  • No exploit/malware-generation code anywhere in this project. Every module only reads a sample as bytes (hashing, header parsing, string extraction, disassembly for display) — nothing here shells out, evals, unpickles, or executes sample content. I grepped the whole tree for eval/exec/os.system/ subprocess/shell=True/pickle before calling this done — none are present.
  • The real residual risk is upstream, not in this tool's own code. pefile, pyelftools, and capstone all parse attacker-controlled, potentially malformed files — that class of parser has historically been where crashes and memory-safety bugs show up industry-wide. See Sandboxing above for how to isolate the environment this runs in, and keep dependencies updated. Never double-click or otherwise execute a loaded sample outside the console.
  • YARA rules are treated as trusted input. Only point RULES at rule sources you trust, the same way you'd trust any code you compile and run locally.
  • Large files are hashed in 1 MiB chunks (bounded memory) and string output is capped and paginated by default, to avoid a huge sample turning run into an unresponsive wall of text.
  • No sample is ever uploaded anywhere — there's no network activity in this tool at all. If you later want a VirusTotal-lookup module, that's an easy add, but it should be opt-in given samples are often confidential.

License

MIT — do whatever you want with it, no warranty. If you use this in production triage, run the sandboxing steps above; if you extend it with dynamic/execution capability, isolate that at least as strictly as the static side is here.

About

A single msfconsole-style terminal for static reverse-engineering and malware triage — unified hashing, PE/ELF analysis, string/IOC extraction, YARA, and disassembly, sandboxed by default, with a one-command Markdown/PDF report at the end.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages