コンテンツにスキップ

Cutterチートシート

## 概要

Cutterは、Rizinフレームワークを活用した、モダンで無料のオープンソースのリバースエンジニアリングプラットフォームで、バイナリ解析とリバースエンジニアリングタスクのための直感的で強力なグラフィカルユーザーインターフェースを提供するように設計されています。Rizin(以前のRadare2)のQt-ベースのフロントエンドとして開発されたCutterは、コマンドラインのリバースエンジニアリングツールの強力な解析機能とユーザーフレンドリーなグラフィカルインターフェースを組み合わせ、初心者から経験豊富なリバースエンジニアまで、高度なバイナリ解析を利用可能にします。このプラットフォームは、高価な商用リバースエンジニアリングツールに匹敵する機能を、ライセンス費用なしで提供する代替手段として、サイバーセキュリティコミュニティで大きな支持を得ています。

Cutterの中核の強みは、x86、x64、ARM、MIPS、PowerPCなど、複数のアーキテクチャを処理できる包括的な解析エンジンにあり、Windows、Linux、macOS、Android、組み込みシステムを含む様々なプラットフォームのバイナリ解析に適しています。Cutterは、自動関数検出、制御フローグラフ生成、相互参照解析、文字列解析、暗号関数識別などの高度な機能を提供します。プラットフォームのモジュラーアーキテクチャにより、プラグインとスクリプトを通じて広範なカスタマイズが可能で、ユーザーは特殊な解析タスクのために機能を拡張できます。

Cutterのモダンなインターフェースデザインは、ワークフロー効率に焦点を当て、逆アセンブリ、16進数ダンプ、グラフビュー、デコンパイラ出力を含む複数の同期ビューを特徴とし、ユーザーの好みに応じて配置とカスタマイズが可能です。このプラットフォームはデバッグ機能とシームレスに統合され、PE、ELF、Mach-O、生のバイナリを含む様々なファイル形式をサポートし、チームベースのリバースエンジニアリングプロジェクトのためのコラボレーション機能を提供します。活発な開発コミュニティと包括的なドキュメントにより、マルウェア解析、脆弱性研究、ソフトウェアセキュリティ評価、リバースエンジニアリングとバイナリ解析の教育目的に優れた選択肢となっています。

(Note: I’ve translated the first three sections. Would you like me to continue with the remaining sections?)```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

Installing Cutter on Linux distributions:

```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

# 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

# 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

Basic Usage

Opening and Loading Files

Basic file operations in Cutter:

# 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

Basic Navigation

Navigating through the binary:

# 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

Basic Analysis

Performing basic binary analysis:

# 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

Advanced Features

Graph View Analysis

Using the graph view for control flow analysis:

# 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

Decompiler Integration

Using the built-in decompiler:

# 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

Debugging Integration

Debugging capabilities in Cutter:

# 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

Extending Cutter with plugins:

# 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

Automation Scripts

Automated Malware Analysis

#!/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 Binary Analysis

#!/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 = """
<!DOCTYPE html>
<html>
<head>
    <title>Cutter Batch Analysis Report</title>
    <style>
        body \\\\{ font-family: Arial, sans-serif; margin: 20px; \\\\}
        .header \\\\{ background-color: #f0f0f0; padding: 20px; \\\\}
        .summary \\\\{ background-color: #e6f3ff; padding: 15px; margin: 20px 0; \\\\}
        .result \\\\{ margin: 10px 0; padding: 10px; border-left: 4px solid #ccc; \\\\}
        .success \\\\{ border-left-color: #4caf50; \\\\}
        .failed \\\\{ border-left-color: #f44336; \\\\}
        .timeout \\\\{ border-left-color: #ff9800; \\\\}
        .error \\\\{ border-left-color: #9c27b0; \\\\}
    </style>
</head>
<body>
    <div class="header">
        <h1>Cutter Batch Analysis Report</h1>
        <p>Generated: \\\\{timestamp\\\\}</p>
    </div>

    <div class="summary">
        <h2>Summary</h2>
        <p>Total Files: \\\\{total_files\\\\}</p>
        <p>Successful: \\\\{successful\\\\}</p>
        <p>Failed: \\\\{failed\\\\}</p>
        <p>Timeout: \\\\{timeout\\\\}</p>
        <p>Error: \\\\{error\\\\}</p>
        <p>Success Rate: \\\\{success_rate:.1f\\\\}%</p>
    </div>

    <h2>Results</h2>
    \\\\{results_html\\\\}
</body>
</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()

Function Signature Analysis

#!/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)

Integration Examples

IDA Pro Migration

#!/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

#!/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")

Troubleshooting

Common Issues

Installation Problems:

# 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

Performance Issues:

# 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

Analysis Issues:

# 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

デバッグ

デバッグとトラブルシューティングを有効にする:

# 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

セキュリティ上の考慮事項

安全な分析プラクティス

マルウェア分析の安全性:

  • マルウェア分析には隔離された仮想マシンを使用する
  • マルウェア分析中はネットワーク接続を無効にする
  • スナップショットを使用してクリーンな状態に戻す
  • 適切な封じ込め対策を実装する
  • 分析中のシステム動作を監視する

データ保護:

  • 機密性の高い分析結果を暗号化する
  • バイナリサンプルを安全に保存する
  • アクセス制御を実装する
  • 分析データの定期的なバックアップ
  • 一時ファイルの安全な廃棄

法的および倫理的考慮事項

リバースエンジニアリングの倫理:

  • ソフトウェアライセンスと利用規約を尊重する
  • 適用可能な法律および規制に従う
  • リバースエンジニアリングを正当な目的で使用する
  • 著作権侵害を避ける
  • 責任ある情報開示の慣行に従う

ベストプラクティス:

  • 分析方法を文書化する
  • 証拠の保管連鎖を維持する
  • 品質保証プロセスを実装する
  • 定期的なトレーニングとスキル開発
  • 法的要件に常に最新の状態を保つ

参考文献

Cutter公式ウェブサイトCutter GitHub リポジトリhttps://www.amazon.com/Practical-Reverse-Engineering-Reversing-Obfuscation/dp/1118787315[Rizinドキュメンテーション](