Saltar a contenido

Cutter hoja de trucos

Overview

Cutter is a modern, free and open-source Ingeniería Inversa platform powered by the Rizin framework, designed to provide an intuitive and powerful graphical user interface for Análisis Binario and Ingeniería Inversa tasks. Developed as a Qt-based frontend to Rizin (formerly Radare2), Cutter combines the powerful analysis capabilities of comando-line Ingeniería Inversa tools with a user-friendly graphical interface that makes advanced Análisis Binario accessible to both beginners and experienced reverse engineers. The platform has gained significant adopción in the cybersecurity community as a viable alternative to expensive commercial Ingeniería Inversa tools, offering comparable functionality without licensing costs.

The core strength of Cutter lies in its comprehensive analysis engine that can handle multiple architectures including x86, x64, ARM, MIPS, PowerPC, and many others, making it suitable for analyzing binaries from various platforms including Windows, Linux, macOS, Android, and embedded systems. Cutter provides advanced features such as automatic function detection, control flow graph generation, cross-referencias analysis, string analysis, and cryptographic function identification. The platform's modular architecture allows for extensive customization through plugins and scripts, enabling users to extend its functionality for specialized analysis tasks.

Cutter's modern interface design focuses on workflow efficiency, featuring multiple synchronized views including disassembly, hexdump, graph view, and decompiler output that can be arranged and customized according to user preferencias. The platform integrates seamlessly with debugging capabilities, suppuertos various file formats including PE, ELF, Mach-O, and raw binaries, and provides collaborative features for team-based Ingeniería Inversa projects. Its active development community and extensive documentación make it an excellent choice for Análisis de Malware, vulnerabilidad research, software security assessment, and educational purposes in Ingeniería Inversa and Análisis Binario.

instalación

Windows instalación

Installing Cutter on Windows systems:

# 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: puertoable 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 instalación
cutter --version

Linux instalación

Installing Cutter on Linux distributions:

# Ubuntu/Debian instalación
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 instalación
sudo pacman -S cutter

# Fedora instalación
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 instalación

# 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 instalación

# 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 &
expuerto 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 uso

Opening and Loading Files

Basic file operations in Cutter:

# Launch Cutter
cutter

# Open file via comando line
cutter /path/to/binary

# Open file with specific opcións
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 opcións:
#   - 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" opcións

# Function navigation
# Functions panel (left sidebar)
# Click function name to navigate
# Use function list dropdown

# Cross-referencias
# Right-click on instruction
# "Show X-Refs" to see referencias
# "Show X-Refs to" to see what referencias this

# Bookmarks
# Right-click -> "Add bookmark"
# View -> Bookmarks panel
# Navigate to saved locations

Basic Analysis

Performing basic Análisis Binario:

# Automatic analysis
# Analysis -> Auto Analysis
# Choose analysis level:
#   - Level 0: Basic (fast)
#   - Level 1: Advanced (recommended)
#   - Level 2: Expert (slow but thorough)

# Manual analysis comandos (in console)
# View -> Console to open Rizin console

# Basic information
i          # File information
ii         # Impuertos
ie         # Expuertos
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~contraseña  # Search for strings containing "contraseña"

# Cross-referencias
axt        # Cross-referencias to current address
axf        # Cross-referencias 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 opcións
# Right-click in graph area
# Layout opcións:
#   - 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
# Expuerto 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 opcións
# Right-click in decompiler view
# opcións:
#   - Rename variables
#   - Change variable types
#   - Add comments
#   - Expuerto decompiled code

# Decompiler backends
# Preferencias -> 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

# Expuerto decompiled code
# Right-click -> Expuerto
# Save as C source file
# Include comments and annotations

Debugging Integration

Debugging capabilities in Cutter:

# Start debugging sesión
# Debug -> Start Debug sesión
# 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 -> Preferencias -> 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

# ejemplo Python script
impuerto 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 Análisis de Malware

#!/usr/bin/env python3
# Automated Análisis de Malware with Cutter

impuerto cutter
impuerto json
impuerto os
impuerto hashlib
from datetime impuerto 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

        # Impuertos
        impuertos = cutter.cmdj("iij")
        self.analysis_results["impuertos"] = impuertos

        # Expuertos
        expuertos = cutter.cmdj("iej")
        self.analysis_results["expuertos"] = expuertos

        # Strings
        strings = cutter.cmdj("izzj")
        self.analysis_results["strings"] = strings

        print(f"Found \\\\{len(impuertos)\\\\} impuertos, \\\\{len(expuertos)\\\\} expuertos, \\\\{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_clavewords = [
                "crypt", "encode", "decode", "obfus", "pack",
                "inject", "hook", "patch", "shell", "exec",
                "download", "upload", "connect", "socket"
            ]

            if any(claveword in func_name.lower() for claveword in suspicious_clavewords):
                suspicious_functions.append(func)
                self.indicators.append(\\\\{
                    "type": "suspicious_function",
                    "value": func_name,
                    "address": func.get("offset"),
                    "Descripción": 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 comandos |
| r"Createproceso | ShellExecute | WinExec",  # proceso creation |
| r"RegOpenclave | RegSetValue | RegDeleteclave",  # Registry operations |
| r"CreateFile | WriteFile | ReadFile",  # File operations |
| r"socket | connect | send | recv",  # Network operations |
        ]

        impuerto 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,
                        "Descripción": f"Suspicious string matching pattern: \\\\{pattern\\\\}"
                    \\\\})
                    break

        self.analysis_results["suspicious_strings"] = suspicious_strings
        print(f"Found \\\\{len(suspicious_strings)\\\\} suspicious strings")

    def impuerto_analysis(self):
        """Analyze impuertos for suspicious APIs"""
        print("Analyzing impuertos...")

        impuertos = self.analysis_results.get("impuertos", [])

        # Suspicious API categories
        suspicious_apis = \\\\{
            "proceso_injection": [
                "CreateRemotehilo", "WriteprocesoMemory", "VirtualAllocEx",
                "Openproceso", "NtCreatehiloEx", "RtlCreateUserhilo"
            ],
            "persistencia": [
                "RegSetValueEx", "RegCreateclaveEx", "Createservicio",
                "SetWindowsHookEx", "SetTimer"
            ],
            "evasion": [
                "IsDebuggerPresent", "CheckRemoteDebuggerPresent",
                "GetTickCount", "QueryPerformanceCounter", "Sleep"
            ],
            "network": [
                "WSAStartup", "socket", "connect", "send", "recv",
                "InternetOpen", "HttpOpenRequest", "HttpSendRequest"
            ],
            "crypto": [
                "CryptAcquireContext", "CryptCreatehash", "CryptEncrypt",
                "CryptDecrypt", "CryptGenclave"
            ]
        \\\\}

        suspicious_impuertos = []

        for impuerto_obj in impuertos:
            impuerto_name = impuerto_obj.get("name", "")

            for category, apis in suspicious_apis.items():
                if impuerto_name in apis:
                    suspicious_impuertos.append(\\\\{
                        "impuerto": impuerto_obj,
                        "category": category,
                        "api": impuerto_name
                    \\\\})

                    self.indicators.append(\\\\{
                        "type": "suspicious_impuerto",
                        "value": impuerto_name,
                        "category": category,
                        "Descripción": f"Suspicious API impuerto: \\\\{impuerto_name\\\\} (\\\\{category\\\\})"
                    \\\\})

        self.analysis_results["suspicious_impuertos"] = suspicious_impuertos
        print(f"Found \\\\{len(suspicious_impuertos)\\\\} suspicious impuertos")

    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,
                                "Descripción": 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"""
        impuerto math
        from collections impuerto 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_repuerto(self, output_file=None):
        """Generate analysis repuerto"""

        if not output_file:
            output_file = f"malware_analysis_\\\\{self.file_hash[:8]\\\\}.json"

        repuerto = \\\\{
            "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_impuertos": len(self.analysis_results.get("suspicious_impuertos", [])),
                "high_entropy_sections": len(self.analysis_results.get("high_entropy_sections", []))
            \\\\}
        \\\\}

        with open(output_file, 'w') as f:
            json.dump(repuerto, f, indent=2)

        print(f"Analysis repuerto saved: \\\\{output_file\\\\}")
        return repuerto

    def run_full_analysis(self):
        """Run complete Análisis de Malware"""
        print(f"Starting Análisis de Malware of: \\\\{self.sample_path\\\\}")

        self.basic_analysis()
        self.function_analysis()
        self.string_analysis()
        self.impuerto_analysis()
        self.entropy_analysis()

        repuerto = self.generate_repuerto()

        print(f"Analysis completed. Found \\\\{len(self.indicators)\\\\} indicators.")
        return repuerto

# uso 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)
    repuerto = analyzer.run_full_analysis()

Batch Análisis Binario

#!/usr/bin/env python3
# Batch Análisis Binario script

impuerto os
impuerto json
impuerto subproceso
impuerto hashlib
from datetime impuerto datetime
from pathlib impuerto 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"""
impuerto cutter
impuerto json

# Basic analysis
cutter.cmd("aaa")

# Collect information
results = \\\\{\\\\{
    "file_info": cutter.cmdj("ij"),
    "functions": cutter.cmdj("aflj"),
    "impuertos": cutter.cmdj("iij"),
    "expuertos": 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 = subproceso.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 subproceso.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 comando
                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 comando"""
        try:
            result = subproceso.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 repuerto
        self.generate_summary_repuerto()

        print(f"Batch analysis completed. Results saved in: \\\\{self.output_dir\\\\}")

    def generate_summary_repuerto(self):
        """Generate summary repuerto"""

        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 repuerto
        self.generate_html_repuerto(summary)

    def generate_html_repuerto(self, summary):
        """Generate HTML summary repuerto"""

        html_template = """
<!DOCTYPE html>
<html>
<head>
    <title>Cutter Batch Analysis Repuerto</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 Repuerto</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_repuerto.html"
        with open(html_file, 'w') as f:
            f.write(html_content)

# uso
if __name__ == "__main__":
    input_directory = "/path/to/binaries"
    output_directory = "/path/to/results"

    analyzer = CutterBatchAnalyzer(input_directory, output_directory)
    analyzer.run_batch_analysis()

Function firma Analysis

#!/usr/bin/env python3
# Function firma analysis and matching

impuerto cutter
impuerto json
impuerto hashlib

class FunctionfirmaAnalyzer:
    def __init__(self):
        self.function_firmas = \\\\{\\\\}
        self.known_firmas = self.load_known_firmas()

    def load_known_firmas(self):
        """Load known function firmas 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",
                    "Descripción": "MD5 initialization constant"
                \\\\},
                "sha1_init": \\\\{
                    "pattern": "mov.*0x67452301.*0xefcdab89",
                    "Descripción": "SHA1 initialization constants"
                \\\\},
                "aes_sbox": \\\\{
                    "pattern": "0x63.*0x7c.*0x77.*0x7b",
                    "Descripción": "AES S-box constants"
                \\\\}
            \\\\},
            "compression": \\\\{
                "zlib_header": \\\\{
                    "pattern": "0x78.*0x9c",
                    "Descripción": "ZLIB header magic"
                \\\\}
            \\\\},
            "network": \\\\{
                "socket_init": \\\\{
                    "pattern": "WSAStartup.*0x0202",
                    "Descripción": "Winsock initialization"
                \\\\}
            \\\\}
        \\\\}

    def extract_function_firma(self, func_addr):
        """Extract firma 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)

        firma = \\\\{
            "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 firma

    def extract_constants(self, disassembly):
        """Extract constants from disassembly"""
        impuerto 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_firma(self, firma):
        """Match firma against known firmas"""

        matches = []

        for category, firmas in self.known_firmas.items():
            for sig_name, sig_data in firmas.items():
                pattern = sig_data["pattern"]
                Descripción = sig_data["Descripción"]

                # Check if pattern matches in disassembly
                if pattern in firma["disassembly"]:
                    matches.append(\\\\{
                        "category": category,
                        "name": sig_name,
                        "Descripción": Descripción,
                        "confidence": "high"
                    \\\\})

                # Check constants
                for const in firma["constants"]:
                    if const in pattern:
                        matches.append(\\\\{
                            "category": category,
                            "name": sig_name,
                            "Descripción": f"Constant match: \\\\{const\\\\}",
                            "confidence": "medium"
                        \\\\})

        return matches

    def analyze_all_functions(self):
        """Analyze all functions in the binary"""

        print("Analyzing function firmas...")

        # 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 firma
            firma = self.extract_function_firma(func_addr)

            if firma:
                # Match against known firmas
                matches = self.match_firma(firma)

                result = \\\\{
                    "function": firma,
                    "matches": matches
                \\\\}

                results.append(result)

                if matches:
                    print(f"  Found \\\\{len(matches)\\\\} firma matches")

        return results

    def generate_firma_repuerto(self, results, output_file="firma_analysis.json"):
        """Generate firma analysis repuerto"""

        # 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

        repuerto = \\\\{
            "firma_analysis": \\\\{
                "total_functions": len(results),
                "total_matches": total_matches,
                "category_counts": category_counts
            \\\\},
            "results": results
        \\\\}

        with open(output_file, 'w') as f:
            json.dump(repuerto, f, indent=2)

        print(f"firma analysis repuerto saved: \\\\{output_file\\\\}")
        print(f"Total functions analyzed: \\\\{len(results)\\\\}")
        print(f"Total firma matches: \\\\{total_matches\\\\}")

        return repuerto

# uso in Cutter
if __name__ == "__main__":
    analyzer = FunctionfirmaAnalyzer()
    results = analyzer.analyze_all_functions()
    repuerto = analyzer.generate_firma_repuerto(results)

Integration ejemplos

IDA Pro Migration

#!/usr/bin/env python3
# IDA Pro to Cutter migration helper

impuerto cutter
impuerto json

class IDACutterMigration:
    def __init__(self):
        self.ida_comandos = \\\\{
            # IDA comando -> 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 expuerto_ida_database(self, output_file="ida_expuerto.json"):
        """Expuerto IDA-like database information"""

        # Collect information similar to IDA database
        database = \\\\{
            "functions": cutter.cmdj("aflj"),
            "segments": cutter.cmdj("iSj"),
            "impuertos": cutter.cmdj("iij"),
            "expuertos": 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 expuertoed 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 []

# uso
migration = IDACutterMigration()
database = migration.expuerto_ida_database()

Ghidra Integration

#!/usr/bin/env python3
# Ghidra and Cutter integration

impuerto cutter
impuerto json
impuerto subproceso
impuerto tempfile

class GhidraCutterIntegration:
    def __init__(self, ghidra_path="/opt/ghidra"):
        self.ghidra_path = ghidra_path

    def expuerto_to_ghidra(self, binary_path, project_name):
        """Expuerto binary to Ghidra project"""

        # Create Ghidra headless script
        script_content = f"""
impuerto ghidra.app.util.impuertoer.MessageLog;
impuerto ghidra.app.util.opción;
impuerto ghidra.app.util.bin.format.pe.puertoableExecutable;
impuerto ghidra.program.model.listing.Program;
impuerto ghidra.util.task.TaskMonitor;

// Impuerto binary
File binaryFile = new File("\\\\{binary_path\\\\}");
Program program = impuertoProgram(binaryFile);

// Auto-analyze
analyzeProgram(program, TaskMonitor.DUMMY);

// Expuerto analysis results
expuertoAnalysisResults(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\\\\}/suppuerto/analyzeHeadless",
            "/tmp/ghidra_projects",
            project_name,
            "-impuerto", binary_path,
            "-postScript", script_path
        ]

        try:
            result = subproceso.run(cmd, capture_output=True, text=True)
            return result.returncode == 0
        except Exception as e:
            print(f"Error running Ghidra: \\\\{e\\\\}")
            return False

    def impuerto_ghidra_analysis(self, analysis_file):
        """Impuerto Ghidra analysis results into Cutter"""

        try:
            with open(analysis_file, 'r') as f:
                ghidra_data = json.load(f)

            # Impuerto 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\\\\}")

            # Impuerto 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 impuertoed successfully")
            return True

        except Exception as e:
            print(f"Error impuertoing Ghidra analysis: \\\\{e\\\\}")
            return False

# uso
ghidra_integration = GhidraCutterIntegration()
ghidra_integration.expuerto_to_ghidra("/path/to/binary", "analysis_project")

solución de problemas

Common Issues

instalación 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 Análisis Binario
# Disable auto-analysis for large files
cutter -A 0 large_binary.exe

# Memory uso 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

# Impuerto/expuerto problems
# Check file format suppuerto
# Verify file permissions
# Use appropriate impuerto opcións

Debugging

Enable debugging and solución de problemas:

# Verbose output
cutter -v binary_file

# Debug mode
cutter -d binary_file

# Console debugging
# View -> Console
# Use Rizin comandos for debugging

# Log file analysis
# Check ~/.local/share/RadareOrg/Cutter/
# Review log files for errors

# Plugin debugging
# Check plugin loading in preferencias
# Verify plugin compatibility
# Review plugin logs

Security Considerations

Safe Analysis Practices

Análisis de Malware Safety: - Use isolated virtual machines for Análisis de Malware - Disable network connectivity when analyzing malware - Use snapshots to restore clean state - Implement proper containment measures - Monitor system behavior during analysis

Data Protection: - Encrypt sensitive analysis results - Secure storage of binary samples - Implement Control de Accesos - Regular backup of analysis data - Secure disposal of temporary files

Ingeniería Inversa Ethics: - Respect software licenses and terms of servicio - Comply with applicable laws and regulations - Use Ingeniería Inversa for legitimate purposes - Avoid copyright infringement - Follow responsible disclosure practices

Best Practices: - Document analysis methodology - Maintain chain of custody for evidence - Implement quality assurance procesoes - Regular training and skill development - Stay updated with legal requirements

referencias

  1. Cutter Official Website
  2. Cutter GitHub Repository
  3. Rizin documentación
  4. Ingeniería Inversa for Beginners
  5. Practical Ingeniería Inversa