
Reverse Engineering Malware With Ghidra
- 72 installs
- 27.3k repo stars
- Updated August 2, 2026
- mukul975/anthropic-cybersecurity-skills
Helps with ai & agent building tasks.
About
reverse-engineering-malware-with-ghidra is a Claude Code skill in the AI & Agent Building category.
- reverse-engineering-malware-with-ghidra
- AI & Agent Building
- AI-coding skill
Reverse Engineering Malware With Ghidra by the numbers
- 72 all-time installs (skills.sh)
- Ranked #5,635 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill reverse-engineering-malware-with-ghidraAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 72 |
|---|---|
| repo stars | ★ 27.3k |
| Last updated | August 2, 2026 |
| Repository | mukul975/anthropic-cybersecurity-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Reverse Engineering Malware with Ghidra
When to Use
- Static and dynamic analysis have identified suspicious functionality that requires deeper code-level understanding
- You need to reverse engineer C2 communication protocols, encryption algorithms, or custom obfuscation
- Understanding the exact exploit mechanism or vulnerability targeted by a malware sample
- Extracting hardcoded configuration data (C2 addresses, encryption keys, campaign IDs) embedded in compiled code
- Developing precise YARA rules or detection signatures based on unique code patterns
Do not use for initial triage of unknown samples; perform static analysis with PEStudio and behavioral analysis with Cuckoo first.
Prerequisites
- Ghidra 11.x installed (download from https://ghidra-sre.org/) with JDK 17+
- Analysis VM isolated from production network (Windows or Linux host)
- Familiarity with x86/x64 assembly language and Windows API conventions
- PDB symbol files for Windows system DLLs to improve decompilation accuracy
- Ghidra scripts repository (ghidra_scripts) for automated analysis tasks
- Secondary reference: IDA Free or Binary Ninja for cross-validation of analysis results
Workflow
Step 1: Create Project and Import Binary
Set up a Ghidra project and import the malware sample:
1. Launch Ghidra: ghidraRun (Linux) or ghidraRun.bat (Windows)
2. File -> New Project -> Non-Shared Project -> Select directory
3. File -> Import File -> Select malware binary
4. Ghidra auto-detects format (PE, ELF, Mach-O) and architecture
5. Accept default import options (or specify base address if known)
6. Double-click imported file to open in CodeBrowser
7. When prompted, run Auto Analysis with default analyzers enabledHeadless analysis for automation:
# Run Ghidra headless analysis with decompiler
/opt/ghidra/support/analyzeHeadless /tmp/ghidra_project MalwareProject \
-import suspect.exe \
-postScript ExportDecompilation.py \
-scriptPath /opt/ghidra/scripts/ \
-deleteProjectStep 2: Identify Key Functions and Entry Points
Navigate the binary to locate critical code sections:
Navigation Strategy:
━━━━━━━━━━━━━━━━━━━
1. Start at entry point (OEP) - follow execution from _start/WinMain
2. Check Symbol Tree for imported functions (Window -> Symbol Tree)
3. Search for cross-references to suspicious APIs:
- VirtualAlloc/VirtualAllocEx (memory allocation for injection)
- CreateRemoteThread (remote thread injection)
- CryptEncrypt/CryptDecrypt (encryption operations)
- InternetOpen/HttpSendRequest (C2 communication)
- RegSetValueEx (persistence via registry)
4. Use Search -> For Strings to find embedded URLs, IPs, and paths
5. Check the Functions window sorted by size (large functions often contain core logic)Ghidra keyboard shortcuts for efficient navigation:
G - Go to address
Ctrl+E - Search for strings
X - Show cross-references to current location
Ctrl+Shift+F - Search memory for byte patterns
L - Rename label/function
; - Add comment
T - Retype variable
Ctrl+L - Retype return valueStep 3: Analyze Decompiled Code
Use Ghidra's decompiler to understand function logic:
// Example: Ghidra decompiler output for a decryption routine
// Analyst renames variables and adds types for clarity
void decrypt_config(BYTE *encrypted_data, int data_len, BYTE *key, int key_len) {
// XOR decryption with rolling key
for (int i = 0; i < data_len; i++) {
encrypted_data[i] = encrypted_data[i] ^ key[i % key_len];
}
return;
}
// Analyst actions in Ghidra:
// 1. Right-click parameters -> Retype to correct types (BYTE*, int)
// 2. Right-click variables -> Rename to meaningful names
// 3. Add comments explaining the algorithm
// 4. Set function signature to propagate types to callersStep 4: Trace C2 Communication Logic
Follow the network communication code path:
Analysis Steps for C2 Protocol Reverse Engineering:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Find InternetOpenA/WinHttpOpen call -> trace to wrapper function
2. Follow data flow from encrypted config -> URL construction
3. Identify HTTP method (GET/POST), headers, and body format
4. Locate response parsing logic (JSON parsing, custom binary protocol)
5. Map the C2 command dispatcher (switch/case or jump table)
6. Document the command set (download, execute, exfiltrate, update, uninstall)Ghidra Script for extracting C2 configuration:
# Ghidra Python script: extract_c2_config.py
# Run via Script Manager in Ghidra
from ghidra.program.model.data import StringDataType
from ghidra.program.model.symbol import SourceType
# Search for XOR decryption patterns
listing = currentProgram.getListing()
memory = currentProgram.getMemory()
# Find references to InternetOpenA
symbol_table = currentProgram.getSymbolTable()
for symbol in symbol_table.getExternalSymbols():
if "InternetOpen" in symbol.getName():
refs = getReferencesTo(symbol.getAddress())
for ref in refs:
print("C2 init at: {}".format(ref.getFromAddress()))Step 5: Analyze Encryption and Obfuscation
Identify and document cryptographic routines:
Common Malware Encryption Patterns:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
XOR Cipher: Loop with XOR operation, often single-byte or rolling key
RC4: Two loops (KSA + PRGA), 256-byte S-box initialization
AES: Look for S-box constants (0x63, 0x7C, 0x77...) or calls to CryptEncrypt
Base64: Lookup table with A-Za-z0-9+/= characters
Custom: Combination of arithmetic operations (ADD, SUB, ROL, ROR with XOR)
Identification Tips:
- Search for constants: AES S-box, CRC32 table, MD5 init values
- Look for loop structures operating on byte arrays
- Check for Windows Crypto API usage (CryptAcquireContext -> CryptCreateHash -> CryptEncrypt)
- FindCrypt Ghidra plugin automatically identifies crypto constantsStep 6: Document Findings and Create Detection Signatures
Produce actionable intelligence from reverse engineering:
# Generate YARA rule from unique code patterns found in Ghidra
cat << 'EOF' > malware_family_x.yar
rule MalwareFamilyX_Decryptor {
meta:
description = "Detects MalwareX decryption routine"
author = "analyst"
date = "2025-09-15"
strings:
// XOR decryption loop with hardcoded key
$decrypt = { 8A 04 0E 32 04 0F 88 04 0E 41 3B CA 7C F3 }
// C2 URL pattern after decryption
$c2_pattern = "/gate.php?id=" ascii
condition:
uint16(0) == 0x5A4D and $decrypt and $c2_pattern
}
EOFKey Concepts
| Term | Definition |
|---|---|
| Disassembly | Converting machine code bytes into human-readable assembly language instructions; Ghidra's Listing view shows disassembled code |
| Decompilation | Lifting assembly code to pseudo-C representation for easier analysis; Ghidra's Decompile window provides this view |
| Cross-Reference (XREF) | Reference showing where a function or data address is called from or used; essential for tracing code execution flow |
| Control Flow Graph (CFG) | Visual representation of all possible execution paths through a function; reveals branching logic and loops |
| Original Entry Point (OEP) | The actual start address of the malware code after unpacking; packers redirect execution through an unpacking stub first |
| Function Signature | The return type, name, and parameter types of a function; applying correct signatures improves decompiler output quality |
| Ghidra Script | Python or Java automation script executed within Ghidra to perform batch analysis, pattern searching, or data extraction |
Tools & Systems
- Ghidra: NSA's open-source software reverse engineering suite with disassembler, decompiler, and scripting support for multiple architectures
- IDA Pro/Free: Industry-standard interactive disassembler; IDA Free provides x86/x64 cloud-based decompilation
- Binary Ninja: Commercial reverse engineering platform with modern UI and extensive API for plugin development
- x64dbg: Open-source x64/x32 debugger for Windows used alongside Ghidra for dynamic debugging of malware
- FindCrypt (Ghidra Plugin): Plugin that identifies cryptographic constants and algorithms in binary code
Common Scenarios
Scenario: Reversing Custom C2 Protocol
Context: Behavioral analysis shows encrypted traffic to an external IP on a non-standard port. Network signatures cannot detect variants because the protocol is proprietary. Deep reverse engineering is needed to understand the protocol structure.
Approach: 1. Import the unpacked sample into Ghidra and run full auto-analysis 2. Locate socket/WinHTTP API calls and trace backwards to the calling function 3. Identify the encryption routine called before data is sent (follow data flow from send/HttpSendRequest) 4. Reverse the encryption (XOR key extraction, RC4 key derivation, AES key location) 5. Map the command structure by analyzing the response parsing function (switch/case on command IDs) 6. Document the protocol format (header structure, command bytes, encryption method) 7. Create a protocol decoder script for network monitoring tools
Pitfalls:
- Not running the full auto-analysis before starting manual analysis (missing function boundaries and type propagation)
- Ignoring indirect calls through function pointers or vtables (use cross-references to data holding function addresses)
- Spending time on library code that Ghidra's Function ID (FID) or FLIRT signatures should have identified
- Not saving Ghidra project progress frequently (analysis state can be lost on crashes)
Output Format
REVERSE ENGINEERING ANALYSIS REPORT
=====================================
Sample: unpacked_payload.exe
SHA-256: abc123def456...
Architecture: x86 (32-bit PE)
Ghidra Project: MalwareX_Analysis
FUNCTION MAP
0x00401000 main() - Entry point, initializes config
0x00401200 decrypt_config() - XOR decryption with 16-byte key
0x00401400 init_c2() - WinHTTP initialization, URL construction
0x00401800 c2_beacon() - HTTP POST beacon with system info
0x00401C00 cmd_dispatcher() - Switch on 12 command codes
0x00402000 inject_process() - Process hollowing into svchost.exe
0x00402400 persist_registry() - HKCU Run key persistence
0x00402800 exfil_data() - File collection and encrypted upload
C2 PROTOCOL
Method: HTTPS POST to /gate.php
Encryption: RC4 with derived key (MD5 of bot_id + campaign_key)
Bot ID Format: MD5(hostname + username + volume_serial)
Beacon Interval: 60 seconds with 10% jitter
Command Set:
0x01 - Download and execute file
0x02 - Execute shell command
0x03 - Upload file to C2
0x04 - Update configuration
0x05 - Uninstall and remove traces
ENCRYPTION DETAILS
Algorithm: RC4
Key Derivation: MD5(bot_id + "campaign_2025_q3")
Hardcoded Seed: "campaign_2025_q3" at offset 0x00405A00
EXTRACTED IOCs
C2 URLs: hxxps://update.malicious[.]com/gate.php
hxxps://backup.evil[.]net/gate.php (failover)
Campaign ID: campaign_2025_q3
RC4 Key Material: [see encryption details above]
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
API Reference: Malware Reverse Engineering with Ghidra Agent
Overview
Combines Ghidra headless analysis with r2pipe (radare2) for automated malware binary analysis: function enumeration, import classification, section entropy, cryptographic constant detection, and network indicator extraction.
Dependencies
| Package | Version | Purpose |
|---|---|---|
| r2pipe | >= 1.8 | Radare2 scripting interface for binary analysis |
| hashlib | stdlib | File hash computation |
External Tools
| Tool | Purpose |
|---|---|
| Ghidra (analyzeHeadless) | Automated disassembly and decompilation |
| radare2 | Binary analysis, function detection, string extraction |
Core Functions
run_ghidra_headless(ghidra_path, project_dir, project_name, binary_path, script)
Executes Ghidra in headless mode with optional post-analysis script.
- Timeout: 600 seconds
- Returns:
dictwith command, returncode, stdout/stderr
export_functions_ghidra(...)
Generates and runs a Ghidra script to export function list as JSON.
- Exports: name, address, size, calling convention, is_thunk
analyze_with_radare2(filepath)
Full r2pipe analysis: binary info, functions, imports, strings, sections, entry points.
- Classifies imports: injection, network, evasion, crypto, persistence
- Extracts: network indicators (URLs, IPs) from strings
- Returns:
dictwith info, function_count, suspicious_imports, sections, etc.
extract_crypto_constants(filepath)
Searches binary for known cryptographic constants: AES S-box, RC4 init table, SHA-256 init vector, RSA magic bytes.
- Returns:
list[dict]with constant name and file offset
analyze_malware(filepath, ghidra_path, output_dir)
Full pipeline: hashes -> crypto constants -> radare2 analysis -> Ghidra headless.
Suspicious Import Categories
| Category | Example Functions |
|---|---|
| injection | VirtualAllocEx, WriteProcessMemory, CreateRemoteThread |
| network | InternetOpenA, WSAStartup, URLDownloadToFileA |
| evasion | IsDebuggerPresent, NtQueryInformationProcess |
| crypto | CryptEncrypt, CryptDecrypt |
| persistence | RegSetValueExA, CreateServiceA |
Radare2 Commands Used
| Command | Purpose |
|---|---|
aaa | Full auto-analysis |
ij | Binary info as JSON |
aflj | Function list as JSON |
iij | Import list as JSON |
izj | String list as JSON |
iSj | Section list as JSON |
iej | Entry points as JSON |
Usage
# With radare2 only
python agent.py malware.exe
# With Ghidra headless analysis
python agent.py malware.exe /opt/ghidra#!/usr/bin/env python3
"""Malware reverse engineering agent using Ghidra headless analyzer and r2pipe."""
import subprocess
import os
import sys
import json
import re
import hashlib
try:
import r2pipe
except ImportError:
r2pipe = None
def compute_hashes(filepath):
"""Compute file hashes for identification."""
with open(filepath, "rb") as f:
data = f.read()
return {
"md5": hashlib.md5(data).hexdigest(),
"sha1": hashlib.sha1(data).hexdigest(),
"sha256": hashlib.sha256(data).hexdigest(),
"size": len(data),
}
def run_ghidra_headless(ghidra_path, project_dir, project_name, binary_path,
script=None, script_args=None):
"""Run Ghidra in headless mode for automated analysis."""
os.makedirs(project_dir, exist_ok=True)
cmd = [
os.path.join(ghidra_path, "support", "analyzeHeadless"),
project_dir, project_name,
"-import", binary_path,
"-overwrite",
]
if script:
cmd.extend(["-postScript", script])
if script_args:
cmd.extend(script_args)
result = subprocess.run(
cmd, capture_output=True, text=True, timeout=600
)
return {
"command": " ".join(cmd),
"returncode": result.returncode,
"stdout": result.stdout[-2000:] if result.stdout else "",
"stderr": result.stderr[-1000:] if result.stderr else "",
}
def export_functions_ghidra(ghidra_path, project_dir, project_name, binary_path,
output_file):
"""Export function list using Ghidra headless with a script."""
script_content = """
import ghidra.program.model.listing.FunctionIterator
import json
output = []
fm = currentProgram.getFunctionManager()
funcs = fm.getFunctions(True)
for func in funcs:
entry = {
"name": func.getName(),
"address": str(func.getEntryPoint()),
"size": func.getBody().getNumAddresses(),
"calling_convention": func.getCallingConventionName(),
"is_thunk": func.isThunk(),
}
output.append(entry)
with open("{output}", "w") as f:
json.dump(output, f, indent=2)
""".replace("{output}", output_file.replace("\\", "\\\\"))
script_path = os.path.join(project_dir, "export_functions.py")
with open(script_path, "w") as f:
f.write(script_content)
return run_ghidra_headless(
ghidra_path, project_dir, project_name, binary_path,
script="export_functions.py"
)
def analyze_with_radare2(filepath):
"""Analyze binary with radare2 via r2pipe for quick triage."""
if r2pipe is None:
return {"error": "r2pipe not installed (pip install r2pipe)"}
r2 = r2pipe.open(filepath, flags=["-2"])
r2.cmd("aaa")
info = r2.cmdj("ij")
functions = r2.cmdj("aflj") or []
imports = r2.cmdj("iij") or []
strings = r2.cmdj("izj") or []
sections = r2.cmdj("iSj") or []
entry_points = r2.cmdj("iej") or []
suspicious_imports = {
"injection": ["VirtualAllocEx", "WriteProcessMemory", "CreateRemoteThread",
"NtCreateThreadEx"],
"network": ["InternetOpenA", "HttpSendRequestA", "WSAStartup",
"URLDownloadToFileA"],
"evasion": ["IsDebuggerPresent", "CheckRemoteDebuggerPresent",
"NtQueryInformationProcess"],
"crypto": ["CryptEncrypt", "CryptDecrypt", "CryptAcquireContextA"],
"persistence": ["RegSetValueExA", "CreateServiceA"],
}
import_findings = []
for imp in imports:
name = imp.get("name", "")
for category, funcs in suspicious_imports.items():
if name in funcs:
import_findings.append({
"category": category,
"function": name,
"library": imp.get("lib", ""),
})
network_strings = []
for s in strings:
val = s.get("string", "")
if re.search(r"https?://", val) or re.search(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", val):
network_strings.append(val[:200])
section_analysis = []
for sec in sections:
entropy = sec.get("entropy", 0)
flags = []
if entropy and entropy > 7.0:
flags.append("HIGH_ENTROPY")
section_analysis.append({
"name": sec.get("name", ""),
"size": sec.get("size", 0),
"vsize": sec.get("vsize", 0),
"entropy": entropy,
"flags": flags,
})
r2.quit()
return {
"info": {
"arch": info.get("bin", {}).get("arch", ""),
"bits": info.get("bin", {}).get("bits", 0),
"os": info.get("bin", {}).get("os", ""),
"type": info.get("bin", {}).get("bintype", ""),
"compiler": info.get("bin", {}).get("compiler", ""),
},
"function_count": len(functions),
"import_count": len(imports),
"string_count": len(strings),
"suspicious_imports": import_findings,
"network_indicators": network_strings[:20],
"sections": section_analysis,
"entry_points": [{"vaddr": e.get("vaddr"), "type": e.get("type")} for e in entry_points],
}
def extract_crypto_constants(filepath):
"""Search binary for known cryptographic constants."""
with open(filepath, "rb") as f:
data = f.read()
constants = {
"AES_SBOX": bytes([0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5]),
"RC4_INIT": bytes(range(256)),
"SHA256_INIT": bytes.fromhex("6a09e667bb67ae853c6ef372a54ff53a"),
"RSA_MAGIC": b"RSA1",
}
found = []
for name, pattern in constants.items():
offset = data.find(pattern)
if offset >= 0:
found.append({"constant": name, "offset": hex(offset)})
return found
def analyze_malware(filepath, ghidra_path=None, output_dir="/tmp/ghidra_analysis"):
"""Full malware analysis pipeline."""
os.makedirs(output_dir, exist_ok=True)
report = {"file": os.path.basename(filepath)}
report["hashes"] = compute_hashes(filepath)
report["crypto_constants"] = extract_crypto_constants(filepath)
if r2pipe:
report["radare2"] = analyze_with_radare2(filepath)
if ghidra_path and os.path.exists(ghidra_path):
ghidra_result = run_ghidra_headless(
ghidra_path, output_dir, "malware_project", filepath
)
report["ghidra"] = {
"analysis_complete": ghidra_result["returncode"] == 0,
"output": ghidra_result["stdout"][-500:],
}
return report
def print_report(report):
print("Malware Reverse Engineering Report")
print("=" * 50)
print(f"File: {report['file']}")
print(f"SHA-256: {report['hashes']['sha256']}")
print(f"Size: {report['hashes']['size']} bytes")
if report.get("crypto_constants"):
print(f"\nCrypto Constants Found:")
for c in report["crypto_constants"]:
print(f" {c['constant']} at {c['offset']}")
r2 = report.get("radare2", {})
if r2 and "error" not in r2:
info = r2.get("info", {})
print(f"\nBinary Info: {info.get('arch', '?')}/{info.get('bits', '?')}bit "
f"({info.get('os', '?')}) [{info.get('type', '?')}]")
print(f"Functions: {r2.get('function_count', 0)}")
print(f"Imports: {r2.get('import_count', 0)}")
if r2.get("suspicious_imports"):
print(f"\nSuspicious Imports:")
for imp in r2["suspicious_imports"]:
print(f" [{imp['category']}] {imp['library']} -> {imp['function']}")
if r2.get("network_indicators"):
print(f"\nNetwork Indicators:")
for ni in r2["network_indicators"][:10]:
print(f" {ni}")
print(f"\nSections:")
for sec in r2.get("sections", []):
flags = f" [{', '.join(sec['flags'])}]" if sec.get("flags") else ""
print(f" {sec['name']:10s} size={sec['size']:>8} entropy={sec.get('entropy', 0):.2f}{flags}")
if report.get("ghidra", {}).get("analysis_complete"):
print(f"\nGhidra: Analysis complete")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python agent.py <binary> [ghidra_install_path]")
sys.exit(1)
binary = sys.argv[1]
ghidra = sys.argv[2] if len(sys.argv) > 2 else None
result = analyze_malware(binary, ghidra_path=ghidra)
print_report(result)