콘텐츠로 이동

Hopper Disassembler

Hopper Disassembler는 디스어셈블리, 디컴파일, 제어 흐름 그래핑 및 스크립팅 기능을 제공하는 macOS 및 Linux용 리버스 엔지니어링 도구입니다. Mach-O, ELF 및 PE 형식의 x86, x86_64, ARM 및 ARM64 바이너리를 지원합니다.

설치

# macOS - download from hopperapp.com or use Homebrew Cask
brew install --cask hopper-disassembler

# Linux - download .deb or .rpm from hopperapp.com
# Debian/Ubuntu
sudo dpkg -i hopper-v4-*.deb
sudo apt-get install -f

# Launch from command line
Hopper  # macOS
hopperv4  # Linux

# Open a binary directly
hopperv4 -e /usr/bin/ls

UI Navigation

Main Views

View shortcuts:
  Ctrl+1     Assembly / Disassembly view
  Ctrl+2     Hex view
  Ctrl+3     Control Flow Graph (CFG)
  Ctrl+4     Pseudo-code / Decompiler view

Navigation:
  G          Go to address or label
  N          Rename current label/function
  ;          Add comment at current address
  Tab        Switch between hex and assembly
  Space      Toggle between linear and graph view
  Esc        Navigate back

Searching

# Search for strings in the binary
Edit > Find > Search for Strings (Cmd+Shift+F / Ctrl+Shift+F)

# Search for a specific byte pattern
Edit > Find > Search Hex (Cmd+F / Ctrl+F)
Enter hex bytes: 48 8B 05 ?? ?? ?? ??

# Search for an address
Press 'G' and enter: 0x100001234

# Find references to current address
Right-click > References to this address (Ctrl+X)

Disassembly View

# Reading the disassembly
# Address    Bytes           Instruction
# 100001234: 55              push   rbp
# 100001235: 48 89 e5        mov    rbp, rsp
# 100001238: 48 83 ec 10     sub    rsp, 0x10

# Label functions
Select address > Press 'N' > Enter function name

# Mark data types
Select address > Right-click > Mark as:
  - Procedure (P)
  - Data (D)
  - ASCII String (A)
  - Code (C)
  - Undefined (U)

Hex View

# Navigate hex view
Ctrl+2          Switch to hex view
Ctrl+G          Go to offset
Ctrl+F          Find hex pattern

# Edit bytes (requires license)
Select bytes > Right-click > Modify > Assemble Instruction
# Or edit hex directly in hex view

Strings Analysis

# View all strings
Navigate > Strings panel (left sidebar)

# Filter strings
Type in filter box at top of strings panel

# Jump to string reference
Double-click string > shows cross-references
Click reference to jump to code using that string

Cross-References (Xrefs)

# Find all references to a function or address
Right-click on label > References to
Keyboard: Ctrl+X (or Cmd+X on macOS)

# Reference types shown:
# CALL - direct function call
# DATA - data reference (pointer, string)
# JUMP - branch/jump target

# Find what this function calls
Right-click > References from

Procedures and Functions

# List all detected procedures
Navigate > Procedures panel (left sidebar)

# Create a new procedure at cursor
Select address > Modify > Mark as Procedure (P)

# Define procedure boundaries
Right-click > Modify > Set Procedure Boundaries

# View procedure info
Right-click > Procedure Info
# Shows: entry point, size, stack frame, local variables

Control Flow Graph

# View CFG for current function
Ctrl+3 or Space (in disassembly view)

# CFG features:
# - Color-coded blocks (green=taken branch, red=not taken)
# - Zoom in/out with scroll wheel
# - Drag to pan
# - Double-click block to jump to it in disassembly

# Export CFG as image
File > Export CFG as PNG/SVG

Decompiler (Pseudo-code)

# View decompiled pseudo-code
Ctrl+4 or select Pseudo-code tab

# The decompiler generates C-like output:
# int _main(int arg0, char** arg1) {
#     var_10 = arg0;
#     rax = printf("Hello %s\n", *(arg1 + 0x8));
#     return 0;
# }

# Rename variables in decompiler view
Click variable > Press 'N' > Enter meaningful name

# Change variable types
Right-click variable > Set Type

Scripting API (Python)

# Hopper Python scripting (run via Script > Run Script)

# Get the current document
doc = Document

# Get a segment by name
segment = doc.getSegmentByName("__TEXT")

# Iterate over all procedures
for i in range(doc.getProcedureCount()):
    proc = doc.getProcedureAtIndex(i)
    entry = proc.getEntryPoint()
    name = doc.getNameAtAddress(entry)
    print(f"0x{entry:x}: {name}")

# Read bytes at address
addr = 0x100001234
byte = doc.readByte(addr)
word = doc.readUInt16LE(addr)
dword = doc.readUInt32LE(addr)

# Set a comment
doc.setCommentAtAddress(0x100001234, "Decryption routine starts here")

# Rename a label
doc.setNameAtAddress(0x100001234, "decrypt_config")

# Get cross-references
refs = doc.getReferencesOfAddress(0x100001234)
for ref in refs:
    print(f"Referenced from: 0x{ref:x}")

Scripting API (JavaScript)

// Hopper JavaScript scripting

// Get current document
var doc = Document;

// Iterate through segments
for (var i = 0; i < doc.getSegmentCount(); i++) {
    var seg = doc.getSegmentAtIndex(i);
    var name = seg.getName();
    var start = seg.getStartingAddress();
    var size = seg.getLength();
    log(name + " @ 0x" + start.toString(16) + " size: " + size);
}

// Find and rename functions matching a pattern
for (var i = 0; i < doc.getProcedureCount(); i++) {
    var proc = doc.getProcedureAtIndex(i);
    var entry = proc.getEntryPoint();
    var name = doc.getNameAtAddress(entry);
    if (name.indexOf("sub_") === 0) {
        log("Unnamed function at 0x" + entry.toString(16));
    }
}

GDB Integration

# Connect Hopper to a GDB remote session
# 1. Start GDB server on target
gdbserver :1234 ./target_binary

# 2. In Hopper: Debug > Connect to Remote GDB Server
# Enter: host:1234

# 3. Set breakpoints in Hopper
# Click the margin next to an instruction
# Or: Debug > Toggle Breakpoint (F2)

# 4. Debug controls
# F5    Continue
# F6    Step Over
# F7    Step Into
# F8    Step Out

File Format Support

Supported formats:
  - Mach-O (macOS/iOS binaries, dylibs, frameworks)
  - ELF (Linux binaries, shared objects)
  - PE/COFF (Windows executables, DLLs)
  - Raw binary files

Supported architectures:
  - x86 (32-bit)
  - x86_64 (64-bit)
  - ARM (32-bit)
  - ARM64 / AArch64

# Open raw binary with architecture hint
File > Open > Select file > Choose architecture and base address

Exporting

# Export disassembly as text
File > Produce > Assembly File

# Export modified binary (patching)
File > Produce > Executable
# Saves patched binary with your modifications

# Export pseudo-code
File > Produce > Pseudo-code File

# Save Hopper project
File > Save (preserves all labels, comments, types)
# Saves as .hop file