Cutter Cheat Sheet
Überblick
Cutter ist eine moderne, kostenlose und Open-Source-Reverse-Engineering-Plattform, die vom Rizin-Framework betrieben wird, um eine intuitive und leistungsstarke grafische Benutzeroberfläche für binäre Analyse- und Reverse-Engineering-Aufgaben bereitzustellen. Cutter entwickelt als Qt-basiertes Frontend zu Rizin (früher Radare2), kombiniert die leistungsstarken Analysefähigkeiten von Kommandozeilen-Reverse-Engineering-Tools mit einer benutzerfreundlichen grafischen Schnittstelle, die fortgeschrittene binäre Analyse sowohl Anfänger als auch erfahrene Reverse-Ingenieure zugänglich macht. Die Plattform hat in der Cyber-Sicherheits-Community eine wichtige Alternative zu teuren kommerziellen Reverse Engineering-Tools gewonnen, die vergleichbare Funktionalität ohne Lizenzkosten bietet.
Die Kernkraft von Cutter liegt in seiner umfassenden Analyse-Engine, die mehrere Architekturen wie x86, x64, ARM, MIPS, PowerPC und viele andere handhaben kann, so dass es für die Analyse von Binaries aus verschiedenen Plattformen wie Windows, Linux, macOS, Android und eingebetteten Systemen geeignet ist. Cutter bietet erweiterte Funktionen wie automatische Funktionserkennung, Steuerungsflussdiagramm-Generierung, Querreferenzanalyse, Stringanalyse und kryptographische Funktionserkennung. Die modulare Architektur der Plattform ermöglicht eine umfangreiche Anpassung durch Plugins und Skripte, sodass Anwender ihre Funktionalität für spezialisierte Analyseaufgaben erweitern können.
Cutters modernes Interface Design konzentriert sich auf Workflow-Effizienz, mit mehreren synchronisierten Ansichten einschließlich Demontage, Hexdump, Diagrammansicht und Dekompiler-Ausgang, die nach Benutzereinstellungen arrangiert und angepasst werden können. Die Plattform integriert sich nahtlos mit Debugging-Funktionen, unterstützt verschiedene Dateiformate wie PE, ELF, Mach-O und Roh-Binaries und bietet kollaborative Funktionen für teambasierte Reverse Engineering-Projekte. Seine aktive Entwicklung Gemeinschaft und umfangreiche Dokumentation machen es zu einer ausgezeichneten Wahl für Malware-Analyse, Sicherheitsforschung, Software-Sicherheitsbewertung und Bildungszwecke in der Reverse Engineering und binären Analyse.
Installation
Windows Installation
Installation von Cutter auf Windows-Systemen:
```bash
Download from GitHub releases
Visit: https://github.com/rizinorg/cutter/releases
Download Windows installer
cutter-v2.3.4-Windows-x86_64.exe
Run installer as administrator
cutter-v2.3.4-Windows-x86_64.exe
Alternative: Portable version
Download: cutter-v2.3.4-Windows-x86_64.zip
Extract to desired location
Run cutter.exe
Install via Chocolatey
choco install cutter
Install via Scoop
scoop bucket add extras scoop install cutter
Verify installation
cutter --version ```_
Linux Installation
Cutter auf Linux Distributionen installieren:
```bash
Ubuntu/Debian installation
sudo apt update sudo apt install cutter
Alternative: Download AppImage
wget https://github.com/rizinorg/cutter/releases/download/v2.3.4/Cutter-v2.3.4-Linux-x86_64.AppImage chmod +x Cutter-v2.3.4-Linux-x86_64.AppImage ./Cutter-v2.3.4-Linux-x86_64.AppImage
Arch Linux installation
sudo pacman -S cutter
Fedora installation
sudo dnf install cutter
Build from source
git clone https://github.com/rizinorg/cutter.git cd cutter git submodule update --init --recursive
Install dependencies
sudo apt install qt5-default libqt5svg5-dev qttools5-dev qttools5-dev-tools
Build
mkdir build && cd build cmake .. make -j$(nproc) sudo make install ```_
macOS Installation
```bash
Install via Homebrew
brew install --cask cutter
Alternative: Download DMG
Visit: https://github.com/rizinorg/cutter/releases
Download: Cutter-v2.3.4-macOS-x86_64.dmg
Install by dragging to Applications
Build from source
git clone https://github.com/rizinorg/cutter.git cd cutter git submodule update --init --recursive
Install dependencies
brew install qt5 cmake
Build
mkdir build && cd build cmake .. make -j$(sysctl -n hw.ncpu) ```_
Docker Installation
```bash
Create Cutter Docker environment
cat > Dockerfile << 'EOF' FROM ubuntu:20.04 ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \ cutter \ xvfb x11vnc fluxbox \ wget curl
Setup VNC for GUI access
EXPOSE 5900
Start script
COPY start.sh /start.sh RUN chmod +x /start.sh
CMD ["/start.sh"] EOF
Create start script
cat > start.sh << 'EOF'
!/bin/bash
Xvfb :1 -screen 0 1024x768x16 & export DISPLAY=:1 fluxbox & x11vnc -display :1 -nopw -listen localhost -xkb & cutter EOF
Build and run
docker build -t cutter-re . docker run -p 5900:5900 -v $(pwd)/samples:/samples cutter-re ```_
Basisnutzung
Dateien öffnen und laden
Basisdateioperationen in Cutter:
```bash
Launch Cutter
cutter
Open file via command line
cutter /path/to/binary
Open file with specific options
cutter -A /path/to/binary # Auto-analysis cutter -e bin.cache=true /path/to/binary # Enable caching
Load file in Cutter GUI
File -> Open File
Select binary file
Choose analysis options:
- Auto-analysis level (0-4)
- Architecture (if not auto-detected)
- Bits (32/64)
- Endianness
- Base address
Load raw binary
File -> Open File
Select "Raw binary" format
Specify architecture and base address
Load from URL
File -> Open URL
Enter URL to binary file
```_
Hauptnavigation
Navigieren durch das Binär:
```bash
Navigation shortcuts
G - Go to address/function
Space - Switch between graph and linear view
Tab - Switch between panels
Ctrl+F - Search
Ctrl+G - Go to address
Address navigation
Click on addresses in disassembly
Use address bar at top
Right-click -> "Go to" options
Function navigation
Functions panel (left sidebar)
Click function name to navigate
Use function list dropdown
Cross-references
Right-click on instruction
"Show X-Refs" to see references
"Show X-Refs to" to see what references this
Bookmarks
Right-click -> "Add bookmark"
View -> Bookmarks panel
Navigate to saved locations
```_
Basisanalyse
Grundlegende binäre Analyse durchführen:
```bash
Automatic analysis
Analysis -> Auto Analysis
Choose analysis level:
- Level 0: Basic (fast)
- Level 1: Advanced (recommended)
- Level 2: Expert (slow but thorough)
Manual analysis commands (in console)
View -> Console to open Rizin console
Basic information
i # File information ii # Imports ie # Exports is # Symbols iz # Strings iS # Sections
Function analysis
afl # List functions af # Analyze function at current address afi # Function information afv # Function variables
String analysis
izz # All strings iz~password # Search for strings containing "password"
Cross-references
axt # Cross-references to current address axf # Cross-references from current address ```_
Erweiterte Funktionen
Analyse von Diagrammen
Anhand der Diagrammansicht zur Steuerungsflussanalyse:
```bash
Switch to graph view
Press Space or View -> Graph
Graph navigation
Mouse wheel - Zoom in/out
Middle mouse drag - Pan
Click nodes to navigate
Double-click to enter function
Graph layout options
Right-click in graph area
Layout options:
- Hierarchical
- Radial
- Force-directed
Minimap
View -> Show Minimap
Navigate large graphs quickly
Graph analysis features
Highlight paths between nodes
Identify loops and branches
Analyze function complexity
Export graph as image
Custom graph views
Create custom graphs for specific analysis
Filter nodes by criteria
Focus on specific code paths
```_
Decompils Integration
Mit dem eingebauten Dekompiler:
```bash
Enable decompiler view
View -> Decompiler
Or press F5 in function
Decompiler options
Right-click in decompiler view
Options:
- Rename variables
- Change variable types
- Add comments
- Export decompiled code
Decompiler backends
Preferences -> Decompiler
Available backends:
- Ghidra decompiler (r2ghidra)
- RetDec
- Snowman
Synchronization
Decompiler view syncs with disassembly
Click in decompiler to highlight assembly
Modifications reflect in both views
Export decompiled code
Right-click -> Export
Save as C source file
Include comments and annotations
```_
Integration Debugging
Debugging-Funktionen in Cutter:
```bash
Start debugging session
Debug -> Start Debug Session
Choose debugger backend:
- Native debugger
- GDB
- WinDbg (Windows)
Set breakpoints
Click on line number in disassembly
Right-click -> Toggle breakpoint
Conditional breakpoints available
Debug controls
F9 - Continue
F10 - Step over
F11 - Step into
Shift+F11 - Step out
Ctrl+F2 - Restart
Watch variables
Debug -> Registers panel
Debug -> Stack panel
Debug -> Memory panel
Add custom watches
Memory examination
View -> Memory Map
Examine memory regions
Modify memory values
Search memory patterns
```_
Plugin System
Cutter mit Plugins erweitern:
```bash
Plugin management
Edit -> Preferences -> Plugins
Enable/disable plugins
Install new plugins
Popular plugins
r2ghidra - Ghidra decompiler integration
r2dec - Alternative decompiler
r2pipe - Python scripting
r2yara - YARA rule integration
Python scripting
Tools -> Python Console
Write custom analysis scripts
Automate repetitive tasks
Example Python script
import cutter
Get current function
func = cutter.cmdj("afij") print(f"Function: \\{func[0]['name']\\}")
Get strings
strings = cutter.cmdj("izj") for s in strings: print(f"String: \\{s['string']\\}")
Custom analysis
Create custom analysis plugins
Extend Cutter functionality
Share plugins with community
```_
Automatisierungsskripte
Automatisierte Malware-Analyse
```python
!/usr/bin/env python3
Automated malware analysis with Cutter
import cutter import json import os import hashlib from datetime import datetime
class CutterMalwareAnalyzer: def init(self, sample_path): self.sample_path = sample_path self.analysis_results = \\{\\} self.indicators = []
# Calculate file hash
with open(sample_path, 'rb') as f:
self.file_hash = hashlib.sha256(f.read()).hexdigest()
def basic_analysis(self):
"""Perform basic static analysis"""
print("Performing basic analysis...")
# File information
file_info = cutter.cmdj("ij")
self.analysis_results["file_info"] = file_info
# Sections
sections = cutter.cmdj("iSj")
self.analysis_results["sections"] = sections
# Imports
imports = cutter.cmdj("iij")
self.analysis_results["imports"] = imports
# Exports
exports = cutter.cmdj("iej")
self.analysis_results["exports"] = exports
# Strings
strings = cutter.cmdj("izzj")
self.analysis_results["strings"] = strings
print(f"Found \\\\{len(imports)\\\\} imports, \\\\{len(exports)\\\\} exports, \\\\{len(strings)\\\\} strings")
def function_analysis(self):
"""Analyze functions in the binary"""
print("Analyzing functions...")
# Auto-analyze functions
cutter.cmd("aaa")
# Get function list
functions = cutter.cmdj("aflj")
self.analysis_results["functions"] = functions
# Analyze suspicious functions
suspicious_functions = []
for func in functions:
func_name = func.get("name", "")
# Check for suspicious function names
suspicious_keywords = [
"crypt", "encode", "decode", "obfus", "pack",
"inject", "hook", "patch", "shell", "exec",
"download", "upload", "connect", "socket"
]
if any(keyword in func_name.lower() for keyword in suspicious_keywords):
suspicious_functions.append(func)
self.indicators.append(\\\\{
"type": "suspicious_function",
"value": func_name,
"address": func.get("offset"),
"description": f"Suspicious function name: \\\\{func_name\\\\}"
\\\\})
self.analysis_results["suspicious_functions"] = suspicious_functions
print(f"Found \\\\{len(suspicious_functions)\\\\} suspicious functions")
def string_analysis(self):
"""Analyze strings for indicators"""
print("Analyzing strings...")
strings = self.analysis_results.get("strings", [])
# Suspicious string patterns
suspicious_patterns = [
r"http[s]?://", # URLs
r"\b\d\\\\{1,3\\\\}\.\d\\\\{1,3\\\\}\.\d\\\\{1,3\\\\}\.\d\\\\{1,3\\\\}\b", # IP addresses
r"[A-Za-z0-9+/]\\\\{20,\\\\}=\\\\{0,2\\\\}", # Base64
r"\\x[0-9a-fA-F]\\\\{2\\\\}", # Hex encoded
| r"cmd.exe | powershell | bash | sh", # Shell commands | | r"CreateProcess | ShellExecute | WinExec", # Process creation | | r"RegOpenKey | RegSetValue | RegDeleteKey", # Registry operations | | r"CreateFile | WriteFile | ReadFile", # File operations | | r"socket | connect | send | recv", # Network operations | ]
import re
suspicious_strings = []
for string_obj in strings:
string_value = string_obj.get("string", "")
for pattern in suspicious_patterns:
if re.search(pattern, string_value, re.IGNORECASE):
suspicious_strings.append(string_obj)
self.indicators.append(\\\\{
"type": "suspicious_string",
"value": string_value,
"address": string_obj.get("vaddr"),
"pattern": pattern,
"description": f"Suspicious string matching pattern: \\\\{pattern\\\\}"
\\\\})
break
self.analysis_results["suspicious_strings"] = suspicious_strings
print(f"Found \\\\{len(suspicious_strings)\\\\} suspicious strings")
def import_analysis(self):
"""Analyze imports for suspicious APIs"""
print("Analyzing imports...")
imports = self.analysis_results.get("imports", [])
# Suspicious API categories
suspicious_apis = \\\\{
"process_injection": [
"CreateRemoteThread", "WriteProcessMemory", "VirtualAllocEx",
"OpenProcess", "NtCreateThreadEx", "RtlCreateUserThread"
],
"persistence": [
"RegSetValueEx", "RegCreateKeyEx", "CreateService",
"SetWindowsHookEx", "SetTimer"
],
"evasion": [
"IsDebuggerPresent", "CheckRemoteDebuggerPresent",
"GetTickCount", "QueryPerformanceCounter", "Sleep"
],
"network": [
"WSAStartup", "socket", "connect", "send", "recv",
"InternetOpen", "HttpOpenRequest", "HttpSendRequest"
],
"crypto": [
"CryptAcquireContext", "CryptCreateHash", "CryptEncrypt",
"CryptDecrypt", "CryptGenKey"
]
\\\\}
suspicious_imports = []
for import_obj in imports:
import_name = import_obj.get("name", "")
for category, apis in suspicious_apis.items():
if import_name in apis:
suspicious_imports.append(\\\\{
"import": import_obj,
"category": category,
"api": import_name
\\\\})
self.indicators.append(\\\\{
"type": "suspicious_import",
"value": import_name,
"category": category,
"description": f"Suspicious API import: \\\\{import_name\\\\} (\\\\{category\\\\})"
\\\\})
self.analysis_results["suspicious_imports"] = suspicious_imports
print(f"Found \\\\{len(suspicious_imports)\\\\} suspicious imports")
def entropy_analysis(self):
"""Analyze entropy of sections"""
print("Analyzing entropy...")
sections = self.analysis_results.get("sections", [])
high_entropy_sections = []
for section in sections:
# Get section data
section_name = section.get("name", "")
section_addr = section.get("vaddr", 0)
section_size = section.get("vsize", 0)
if section_size > 0:
# Calculate entropy (simplified)
try:
data = cutter.cmd(f"p8 \\\\{section_size\\\\} @ \\\\{section_addr\\\\}")
if data:
entropy = self.calculate_entropy(bytes.fromhex(data))
section["entropy"] = entropy
# High entropy might indicate packed/encrypted data
if entropy > 7.0:
high_entropy_sections.append(section)
self.indicators.append(\\\\{
"type": "high_entropy_section",
"value": section_name,
"entropy": entropy,
"description": f"High entropy section: \\\\{section_name\\\\} (entropy: \\\\{entropy:.2f\\\\})"
\\\\})
except:
pass
self.analysis_results["high_entropy_sections"] = high_entropy_sections
print(f"Found \\\\{len(high_entropy_sections)\\\\} high entropy sections")
def calculate_entropy(self, data):
"""Calculate Shannon entropy of data"""
import math
from collections import Counter
if not data:
return 0
# Count byte frequencies
byte_counts = Counter(data)
data_len = len(data)
# Calculate entropy
entropy = 0
for count in byte_counts.values():
probability = count / data_len
entropy -= probability * math.log2(probability)
return entropy
def generate_report(self, output_file=None):
"""Generate analysis report"""
if not output_file:
output_file = f"malware_analysis_\\\\{self.file_hash[:8]\\\\}.json"
report = \\\\{
"analysis_info": \\\\{
"file_path": self.sample_path,
"file_hash": self.file_hash,
"timestamp": datetime.now().isoformat(),
"total_indicators": len(self.indicators)
\\\\},
"analysis_results": self.analysis_results,
"indicators": self.indicators,
"summary": \\\\{
"suspicious_functions": len(self.analysis_results.get("suspicious_functions", [])),
"suspicious_strings": len(self.analysis_results.get("suspicious_strings", [])),
"suspicious_imports": len(self.analysis_results.get("suspicious_imports", [])),
"high_entropy_sections": len(self.analysis_results.get("high_entropy_sections", []))
\\\\}
\\\\}
with open(output_file, 'w') as f:
json.dump(report, f, indent=2)
print(f"Analysis report saved: \\\\{output_file\\\\}")
return report
def run_full_analysis(self):
"""Run complete malware analysis"""
print(f"Starting malware analysis of: \\\\{self.sample_path\\\\}")
self.basic_analysis()
self.function_analysis()
self.string_analysis()
self.import_analysis()
self.entropy_analysis()
report = self.generate_report()
print(f"Analysis completed. Found \\\\{len(self.indicators)\\\\} indicators.")
return report
Usage in Cutter
if name == "main": # This script should be run within Cutter's Python console sample_path = "/path/to/malware/sample"
analyzer = CutterMalwareAnalyzer(sample_path)
report = analyzer.run_full_analysis()
```_
Batch Bindanalyse
```python
!/usr/bin/env python3
Batch binary analysis script
import os import json import subprocess import hashlib from datetime import datetime from pathlib import Path
class CutterBatchAnalyzer: def init(self, input_dir, output_dir): self.input_dir = Path(input_dir) self.output_dir = Path(output_dir) self.output_dir.mkdir(exist_ok=True) self.results = []
def analyze_binary(self, binary_path):
"""Analyze single binary with Cutter"""
print(f"Analyzing: \\\\{binary_path\\\\}")
# Calculate file hash
with open(binary_path, 'rb') as f:
file_hash = hashlib.sha256(f.read()).hexdigest()
# Create Cutter script for analysis
script_content = f"""
import cutter import json
Basic analysis
cutter.cmd("aaa")
Collect information
results = \\{\\{ "file_info": cutter.cmdj("ij"), "functions": cutter.cmdj("aflj"), "imports": cutter.cmdj("iij"), "exports": cutter.cmdj("iej"), "strings": cutter.cmdj("izzj"), "sections": cutter.cmdj("iSj") \\}\\}
Save results
with open("/tmp/cutter_results_\\{file_hash\\}.json", "w") as f: json.dump(results, f, indent=2)
Exit Cutter
cutter.cmd("q") """
script_path = f"/tmp/cutter_script_\\\\{file_hash\\\\}.py"
with open(script_path, 'w') as f:
f.write(script_content)
try:
# Run Cutter with script
cmd = [
"cutter",
"-A", # Auto-analysis
"-i", script_path, # Run script
str(binary_path)
]
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=300 # 5 minute timeout
)
# Load results
results_file = f"/tmp/cutter_results_\\\\{file_hash\\\\}.json"
if os.path.exists(results_file):
with open(results_file, 'r') as f:
analysis_results = json.load(f)
# Clean up temporary files
os.remove(script_path)
os.remove(results_file)
return \\\\{
"file_path": str(binary_path),
"file_hash": file_hash,
"status": "success",
"analysis_results": analysis_results,
"timestamp": datetime.now().isoformat()
\\\\}
else:
return \\\\{
"file_path": str(binary_path),
"file_hash": file_hash,
"status": "failed",
"error": "No results file generated",
"timestamp": datetime.now().isoformat()
\\\\}
except subprocess.TimeoutExpired:
return \\\\{
"file_path": str(binary_path),
"file_hash": file_hash,
"status": "timeout",
"error": "Analysis timed out",
"timestamp": datetime.now().isoformat()
\\\\}
except Exception as e:
return \\\\{
"file_path": str(binary_path),
"file_hash": file_hash,
"status": "error",
"error": str(e),
"timestamp": datetime.now().isoformat()
\\\\}
def find_binaries(self):
"""Find binary files in input directory"""
binary_extensions = ['.exe', '.dll', '.so', '.dylib', '.bin']
binaries = []
for file_path in self.input_dir.rglob('*'):
if file_path.is_file():
# Check by extension
if file_path.suffix.lower() in binary_extensions:
binaries.append(file_path)
# Check by file command
elif self.is_binary_file(file_path):
binaries.append(file_path)
return binaries
def is_binary_file(self, file_path):
"""Check if file is binary using file command"""
try:
result = subprocess.run(
['file', str(file_path)],
capture_output=True,
text=True
)
binary_indicators = [
'executable', 'ELF', 'PE32', 'Mach-O',
'shared object', 'dynamic library'
]
return any(indicator in result.stdout for indicator in binary_indicators)
except:
return False
def run_batch_analysis(self):
"""Run analysis on all binaries"""
binaries = self.find_binaries()
print(f"Found \\\\{len(binaries)\\\\} binary files to analyze")
for i, binary_path in enumerate(binaries, 1):
print(f"Progress: \\\\{i\\\\}/\\\\{len(binaries)\\\\}")
result = self.analyze_binary(binary_path)
self.results.append(result)
# Save individual result
result_file = self.output_dir / f"result_\\\\{result['file_hash'][:8]\\\\}.json"
with open(result_file, 'w') as f:
json.dump(result, f, indent=2)
# Generate summary report
self.generate_summary_report()
print(f"Batch analysis completed. Results saved in: \\\\{self.output_dir\\\\}")
def generate_summary_report(self):
"""Generate summary report"""
successful = len([r for r in self.results if r['status'] == 'success'])
failed = len([r for r in self.results if r['status'] == 'failed'])
timeout = len([r for r in self.results if r['status'] == 'timeout'])
error = len([r for r in self.results if r['status'] == 'error'])
summary = \\\\{
"batch_analysis_summary": \\\\{
"total_files": len(self.results),
"successful": successful,
"failed": failed,
"timeout": timeout,
"error": error,
"success_rate": (successful / len(self.results)) * 100 if self.results else 0
\\\\},
"results": self.results,
"timestamp": datetime.now().isoformat()
\\\\}
summary_file = self.output_dir / "batch_analysis_summary.json"
with open(summary_file, 'w') as f:
json.dump(summary, f, indent=2)
# Generate HTML report
self.generate_html_report(summary)
def generate_html_report(self, summary):
"""Generate HTML summary report"""
html_template = """
Cutter Batch Analysis Report
Generated: \\\\{timestamp\\\\}
Summary
Total Files: \\\\{total_files\\\\}
Successful: \\\\{successful\\\\}
Failed: \\\\{failed\\\\}
Timeout: \\\\{timeout\\\\}
Error: \\\\{error\\\\}
Success Rate: \\\\{success_rate:.1f\\\\}%
Results
\\\\{results_html\\\\} """
results_html = ""
for result in summary["results"]:
status_class = result["status"]
results_html += f"""
<div class="result \\\\{status_class\\\\}">
<h3>\\\\{os.path.basename(result['file_path'])\\\\}</h3>
<p>Status: \\\\{result['status'].upper()\\\\}</p>
<p>Hash: \\\\{result['file_hash']\\\\}</p>
<p>Timestamp: \\\\{result['timestamp']\\\\}</p>
\\\\{f"<p>Error: \\\\{result.get('error', '')\\\\}</p>" if 'error' in result else ""\\\\}
</div>
"""
html_content = html_template.format(
timestamp=summary["timestamp"],
total_files=summary["batch_analysis_summary"]["total_files"],
successful=summary["batch_analysis_summary"]["successful"],
failed=summary["batch_analysis_summary"]["failed"],
timeout=summary["batch_analysis_summary"]["timeout"],
error=summary["batch_analysis_summary"]["error"],
success_rate=summary["batch_analysis_summary"]["success_rate"],
results_html=results_html
)
html_file = self.output_dir / "batch_analysis_report.html"
with open(html_file, 'w') as f:
f.write(html_content)
Usage
if name == "main": input_directory = "/path/to/binaries" output_directory = "/path/to/results"
analyzer = CutterBatchAnalyzer(input_directory, output_directory)
analyzer.run_batch_analysis()
```_
Funktion Signaturanalyse
```python
!/usr/bin/env python3
Function signature analysis and matching
import cutter import json import hashlib
class FunctionSignatureAnalyzer: def init(self): self.function_signatures = \\{\\} self.known_signatures = self.load_known_signatures()
def load_known_signatures(self):
"""Load known function signatures database"""
# This would typically load from a database or file
# For demo purposes, we'll use a small set
return \\\\{
"crypto_functions": \\\\{
"md5_init": \\\\{
"pattern": "mov.*0x67452301",
"description": "MD5 initialization constant"
\\\\},
"sha1_init": \\\\{
"pattern": "mov.*0x67452301.*0xefcdab89",
"description": "SHA1 initialization constants"
\\\\},
"aes_sbox": \\\\{
"pattern": "0x63.*0x7c.*0x77.*0x7b",
"description": "AES S-box constants"
\\\\}
\\\\},
"compression": \\\\{
"zlib_header": \\\\{
"pattern": "0x78.*0x9c",
"description": "ZLIB header magic"
\\\\}
\\\\},
"network": \\\\{
"socket_init": \\\\{
"pattern": "WSAStartup.*0x0202",
"description": "Winsock initialization"
\\\\}
\\\\}
\\\\}
def extract_function_signature(self, func_addr):
"""Extract signature from function"""
# Get function information
func_info = cutter.cmdj(f"afij @ \\\\{func_addr\\\\}")
if not func_info:
return None
func_info = func_info[0]
func_size = func_info.get("size", 0)
if func_size == 0:
return None
# Get function bytes
func_bytes = cutter.cmd(f"p8 \\\\{func_size\\\\} @ \\\\{func_addr\\\\}")
# Calculate hash
func_hash = hashlib.md5(bytes.fromhex(func_bytes)).hexdigest()
# Get disassembly
disasm = cutter.cmd(f"pdf @ \\\\{func_addr\\\\}")
# Extract constants and patterns
constants = self.extract_constants(disasm)
patterns = self.extract_patterns(disasm)
signature = \\\\{
"address": func_addr,
"name": func_info.get("name", f"fcn.\\\\{func_addr:08x\\\\}"),
"size": func_size,
"hash": func_hash,
"constants": constants,
"patterns": patterns,
"disassembly": disasm
\\\\}
return signature
def extract_constants(self, disassembly):
"""Extract constants from disassembly"""
import re
constants = []
# Look for immediate values
const_patterns = [
r'0x[0-9a-fA-F]+', # Hex constants
r'\b\d+\b', # Decimal constants
]
for pattern in const_patterns:
matches = re.findall(pattern, disassembly)
constants.extend(matches)
# Remove duplicates and sort
return sorted(list(set(constants)))
def extract_patterns(self, disassembly):
"""Extract instruction patterns from disassembly"""
lines = disassembly.split('\n')
patterns = []
for line in lines:
# Extract instruction mnemonic
parts = line.strip().split()
if len(parts) >= 2:
instruction = parts[1] # Skip address
patterns.append(instruction)
return patterns
def match_signature(self, signature):
"""Match signature against known signatures"""
matches = []
for category, signatures in self.known_signatures.items():
for sig_name, sig_data in signatures.items():
pattern = sig_data["pattern"]
description = sig_data["description"]
# Check if pattern matches in disassembly
if pattern in signature["disassembly"]:
matches.append(\\\\{
"category": category,
"name": sig_name,
"description": description,
"confidence": "high"
\\\\})
# Check constants
for const in signature["constants"]:
if const in pattern:
matches.append(\\\\{
"category": category,
"name": sig_name,
"description": f"Constant match: \\\\{const\\\\}",
"confidence": "medium"
\\\\})
return matches
def analyze_all_functions(self):
"""Analyze all functions in the binary"""
print("Analyzing function signatures...")
# Get all functions
functions = cutter.cmdj("aflj")
results = []
for func in functions:
func_addr = func.get("offset")
func_name = func.get("name", "")
print(f"Analyzing function: \\\\{func_name\\\\} @ 0x\\\\{func_addr:x\\\\}")
# Extract signature
signature = self.extract_function_signature(func_addr)
if signature:
# Match against known signatures
matches = self.match_signature(signature)
result = \\\\{
"function": signature,
"matches": matches
\\\\}
results.append(result)
if matches:
print(f" Found \\\\{len(matches)\\\\} signature matches")
return results
def generate_signature_report(self, results, output_file="signature_analysis.json"):
"""Generate signature analysis report"""
# Count matches by category
category_counts = \\\\{\\\\}
total_matches = 0
for result in results:
for match in result["matches"]:
category = match["category"]
category_counts[category] = category_counts.get(category, 0) + 1
total_matches += 1
report = \\\\{
"signature_analysis": \\\\{
"total_functions": len(results),
"total_matches": total_matches,
"category_counts": category_counts
\\\\},
"results": results
\\\\}
with open(output_file, 'w') as f:
json.dump(report, f, indent=2)
print(f"Signature analysis report saved: \\\\{output_file\\\\}")
print(f"Total functions analyzed: \\\\{len(results)\\\\}")
print(f"Total signature matches: \\\\{total_matches\\\\}")
return report
Usage in Cutter
if name == "main": analyzer = FunctionSignatureAnalyzer() results = analyzer.analyze_all_functions() report = analyzer.generate_signature_report(results) ```_
Integrationsbeispiele
IDA Pro Migration
```python
!/usr/bin/env python3
IDA Pro to Cutter migration helper
import cutter import json
class IDACutterMigration: def init(self): self.ida_commands = \\{ # IDA command -> Cutter equivalent "MakeCode": "af", "MakeFunction": "af", "MakeName": "afn", "MakeComm": "CC", "Jump": "s", "GetFunctionName": "afi~name", "GetString": "ps", "FindBinary": "/x", "GetBytes": "p8", "PatchByte": "wx", "ScreenEA": "s", "here": "s", "BADADDR": "0xffffffff" \\}
def convert_ida_script(self, ida_script):
"""Convert IDA Python script to Cutter"""
# Basic conversion patterns
conversions = [
("idc.MakeCode", "cutter.cmd('af')"),
("idc.MakeFunction", "cutter.cmd('af')"),
("idc.GetFunctionName", "cutter.cmdj('afi')['name']"),
("idc.Jump", "cutter.cmd('s')"),
("idaapi.get_bytes", "cutter.cmd('p8')"),
("idc.here()", "cutter.cmd('s')"),
("print", "print") # Keep print statements
]
converted_script = ida_script
for ida_pattern, cutter_pattern in conversions:
converted_script = converted_script.replace(ida_pattern, cutter_pattern)
return converted_script
def export_ida_database(self, output_file="ida_export.json"):
"""Export IDA-like database information"""
# Collect information similar to IDA database
database = \\\\{
"functions": cutter.cmdj("aflj"),
"segments": cutter.cmdj("iSj"),
"imports": cutter.cmdj("iij"),
"exports": cutter.cmdj("iej"),
"strings": cutter.cmdj("izzj"),
"comments": self.get_all_comments(),
"names": self.get_all_names()
\\\\}
with open(output_file, 'w') as f:
json.dump(database, f, indent=2)
print(f"Database exported to: \\\\{output_file\\\\}")
return database
def get_all_comments(self):
"""Get all comments in the binary"""
# This would collect all comments
# Implementation depends on Cutter's comment system
return []
def get_all_names(self):
"""Get all named locations"""
# This would collect all named locations
# Implementation depends on Cutter's naming system
return []
Usage
migration = IDACutterMigration() database = migration.export_ida_database() ```_
Ghidra Integration
```python
!/usr/bin/env python3
Ghidra and Cutter integration
import cutter import json import subprocess import tempfile
class GhidraCutterIntegration: def init(self, ghidra_path="/opt/ghidra"): self.ghidra_path = ghidra_path
def export_to_ghidra(self, binary_path, project_name):
"""Export binary to Ghidra project"""
# Create Ghidra headless script
script_content = f"""
import ghidra.app.util.importer.MessageLog; import ghidra.app.util.Option; import ghidra.app.util.bin.format.pe.PortableExecutable; import ghidra.program.model.listing.Program; import ghidra.util.task.TaskMonitor;
// Import binary File binaryFile = new File("\\{binary_path\\}"); Program program = importProgram(binaryFile);
// Auto-analyze analyzeProgram(program, TaskMonitor.DUMMY);
// Export analysis results exportAnalysisResults(program, "\\{project_name\\}_analysis.json"); """
# Run Ghidra headless
with tempfile.NamedTemporaryFile(mode='w', suffix='.java', delete=False) as f:
f.write(script_content)
script_path = f.name
cmd = [
f"\\\\{self.ghidra_path\\\\}/support/analyzeHeadless",
"/tmp/ghidra_projects",
project_name,
"-import", binary_path,
"-postScript", script_path
]
try:
result = subprocess.run(cmd, capture_output=True, text=True)
return result.returncode == 0
except Exception as e:
print(f"Error running Ghidra: \\\\{e\\\\}")
return False
def import_ghidra_analysis(self, analysis_file):
"""Import Ghidra analysis results into Cutter"""
try:
with open(analysis_file, 'r') as f:
ghidra_data = json.load(f)
# Import functions
if "functions" in ghidra_data:
for func in ghidra_data["functions"]:
addr = func.get("address")
name = func.get("name")
if addr and name:
cutter.cmd(f"af @ \\\\{addr\\\\}")
cutter.cmd(f"afn \\\\{name\\\\} @ \\\\{addr\\\\}")
# Import comments
if "comments" in ghidra_data:
for comment in ghidra_data["comments"]:
addr = comment.get("address")
text = comment.get("text")
if addr and text:
cutter.cmd(f"CC \\\\{text\\\\} @ \\\\{addr\\\\}")
print("Ghidra analysis imported successfully")
return True
except Exception as e:
print(f"Error importing Ghidra analysis: \\\\{e\\\\}")
return False
Usage
ghidra_integration = GhidraCutterIntegration() ghidra_integration.export_to_ghidra("/path/to/binary", "analysis_project") ```_
Fehlerbehebung
Gemeinsame Themen
Installationsprobleme: ```bash
Qt dependency issues
sudo apt install qt5-default libqt5svg5-dev
Build dependency issues
sudo apt install cmake build-essential git
Python plugin issues
pip install r2pipe
AppImage execution issues
chmod +x Cutter-.AppImage ./Cutter-.AppImage --appimage-extract-and-run ```_
Leistungsfragen: ```bash
Large binary analysis
Disable auto-analysis for large files
cutter -A 0 large_binary.exe
Memory usage optimization
Limit analysis depth
Use project files to save state
Close unused views
Graph rendering issues
Reduce graph complexity
Use linear view for large functions
Adjust graph layout settings
```_
** Analysethemen:** ```bash
Function detection problems
Manual function creation: af @ address
Adjust analysis settings
Use different analysis levels
Decompiler issues
Try different decompiler backends
Check function boundaries
Verify architecture detection
Import/export problems
Check file format support
Verify file permissions
Use appropriate import options
```_
Debugging
Debugging und Fehlerbehebung aktivieren:
```bash
Verbose output
cutter -v binary_file
Debug mode
cutter -d binary_file
Console debugging
View -> Console
Use Rizin commands for debugging
Log file analysis
Check ~/.local/share/RadareOrg/Cutter/
Review log files for errors
Plugin debugging
Check plugin loading in preferences
Verify plugin compatibility
Review plugin logs
```_
Sicherheitsüberlegungen
Sichere Analysepraktiken
Malware Analyse Sicherheit: - Verwenden Sie isolierte virtuelle Maschinen für Malware-Analyse - Deaktivieren Sie Netzwerk-Konnektivität bei der Analyse von Malware - Verwenden Sie Snapshots, um sauberen Zustand wiederherzustellen - Durchführung richtiger Eindämmungsmaßnahmen - Systemverhalten während der Analyse überwachen
Datenschutz: - Verschlüsselung sensibler Analyseergebnisse - Sichere Speicherung binärer Proben - Implementierung der Zugangskontrollen - Regelmäßige Sicherung von Analysedaten - Sichere Entsorgung temporärer Dateien
Rechtliche und ethische Überlegungen
Reverse Engineering Ethics: - Respektieren von Softwarelizenzen und Nutzungsbedingungen - Erfüllung geltender Gesetze und Vorschriften - Reverse Engineering für legitime Zwecke verwenden - Vermeiden Sie Urheberrechtsverletzung - Verantwortliche Offenlegungspraktiken
Beste Praktiken: - Methodik der Analyse von Dokumenten - Bewahren Sie die Kette der Sorge für Beweise - Umsetzung von Qualitätssicherungsprozessen - Regelmäßige Ausbildung und Qualifikationsentwicklung - Aktualisiert bleiben mit gesetzlichen Anforderungen
Referenzen
- [Cutter Offizielle Website](https://_LINK_5___
- [Cutter GitHub Repository](__LINK_5___
- Rizin-Dokumentation
- Reverse Engineering für Anfänger
- (__LINK_5___)