Master binary analysis patterns including disassembly

Master binary analysis patterns including disassembly, decompilation, control flow analysis, and code pattern recognition. Use when analyzing executables, understanding compiled code, or performing static analysis on binaries.
--- name: binary-analysis-patterns description: Master binary analysis patterns including disassembly, decompilation, control flow analysis, and code pattern recognition. Use when analyzing executables, understanding compiled code, or performing static analysis on binaries. --- # Binary Analysis Patterns Comprehensive patterns and techniques for analyzing compiled binaries, understanding assembly code, and reconstructing program logic. ## When to Use This Skill - Reverse-engineering an unknown executable to understand its behavior - Analyzing malware or obfuscated binaries with Ghidra / IDA Pro / Binary Ninja - Recognizing common assembly idioms (function prologues, switch tables, vtable dispatch) - Reconstructing high-level control flow from compiled code - Identifying compiler-introduced patterns (stack canaries, PIC trampolines) ## Detailed section: Disassembly Fundamentals
Overview
Comprehensive patterns and techniques for analyzing compiled binaries, understanding assembly code, and reconstructing program logic.
Manual install (npx, ZIP)
Claude Code
npx skills add wshobson/agents --skill binary-analysis-patterns -g -a claude-codeClaude Code (manual)
mkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/wshobson/agents/tar.gz/4236bb91f839 \
| tar -xz -C ~/.claude/skills --strip-components=4 agents-4236bb91f839/plugins/reverse-engineering/skills/binary-analysis-patternsWindows (PowerShell)
New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/a16ed9952961d86a2fa3/binary-analysis-patterns.zip" -OutFile "$env:TEMP\binary-analysis-patterns.zip"; Expand-Archive "$env:TEMP\binary-analysis-patterns.zip" -DestinationPath "$HOME\.claude\skills" -ForceClaude.ai / desktop
Codex, Cursor, other agents
Connects with Agent Alley MCP · agentalley.io/mcp
Files included
SKILL.md7.7 KBreferences/1 file · 2.0 KB
Read the files here
SKILL.md
Show the full text352 lines
Binary Analysis Patterns
Comprehensive patterns and techniques for analyzing compiled binaries, understanding assembly code, and reconstructing program logic.
When to Use This Skill
- Reverse-engineering an unknown executable to understand its behavior
- Analyzing malware or obfuscated binaries with Ghidra / IDA Pro / Binary Ninja
- Recognizing common assembly idioms (function prologues, switch tables, vtable dispatch)
- Reconstructing high-level control flow from compiled code
- Identifying compiler-introduced patterns (stack canaries, PIC trampolines)
Detailed section: Disassembly Fundamentals
Originally a 2047-byte section in this SKILL.md. Moved to references/details.md to fit Codex's 8 KB skill body cap.
Control Flow Patterns
Conditional Branches
; if (a == b)
cmp eax, ebx
jne skip_block
; ... if body ...
skip_block:
; if (a < b) - signed
cmp eax, ebx
jge skip_block ; Jump if greater or equal
; ... if body ...
skip_block:
; if (a < b) - unsigned
cmp eax, ebx
jae skip_block ; Jump if above or equal
; ... if body ...
skip_block:
Loop Patterns
; for (int i = 0; i < n; i++)
xor ecx, ecx ; i = 0
loop_start:
cmp ecx, [n] ; i < n
jge loop_end
; ... loop body ...
inc ecx ; i++
jmp loop_start
loop_end:
; while (condition)
jmp loop_check
loop_body:
; ... body ...
loop_check:
cmp eax, ebx
jl loop_body
; do-while
loop_body:
; ... body ...
cmp eax, ebx
jl loop_body
Switch Statement Patterns
; Jump table pattern
mov eax, [switch_var]
cmp eax, max_case
ja default_case
jmp [jump_table + eax*8]
; Sequential comparison (small switch)
cmp eax, 1
je case_1
cmp eax, 2
je case_2
cmp eax, 3
je case_3
jmp default_case
Data Structure Patterns
Array Access
; array[i] - 4-byte elements
mov eax, [rbx + rcx*4] ; rbx=base, rcx=index
; array[i] - 8-byte elements
mov rax, [rbx + rcx*8]
; Multi-dimensional array[i][j]
; arr[i][j] = base + (i * cols + j) * element_size
imul eax, [cols]
add eax, [j]
mov edx, [rbx + rax*4]
Structure Access
struct Example {
int a; // offset 0
char b; // offset 4
// padding // offset 5-7
long c; // offset 8
short d; // offset 16
};
; Accessing struct fields
mov rdi, [struct_ptr]
mov eax, [rdi] ; s->a (offset 0)
movzx eax, byte [rdi+4] ; s->b (offset 4)
mov rax, [rdi+8] ; s->c (offset 8)
movzx eax, word [rdi+16] ; s->d (offset 16)
Linked List Traversal
; while (node != NULL)
list_loop:
test rdi, rdi ; node == NULL?
jz list_done
; ... process node ...
mov rdi, [rdi+8] ; node = node->next (assuming next at offset 8)
jmp list_loop
list_done:
Common Code Patterns
String Operations
; strlen pattern
xor ecx, ecx
strlen_loop:
cmp byte [rdi + rcx], 0
je strlen_done
inc ecx
jmp strlen_loop
strlen_done:
; ecx contains length
; strcpy pattern
strcpy_loop:
mov al, [rsi]
mov [rdi], al
test al, al
jz strcpy_done
inc rsi
inc rdi
jmp strcpy_loop
strcpy_done:
; memcpy using rep movsb
mov rdi, dest
mov rsi, src
mov rcx, count
rep movsb
Arithmetic Patterns
; Multiplication by constant
; x * 3
lea eax, [rax + rax*2]
; x * 5
lea eax, [rax + rax*4]
; x * 10
lea eax, [rax + rax*4] ; x * 5
add eax, eax ; * 2
; Division by power of 2 (signed)
mov eax, [x]
cdq ; Sign extend to EDX:EAX
and edx, 7 ; For divide by 8
add eax, edx ; Adjust for negative
sar eax, 3 ; Arithmetic shift right
; Modulo power of 2
and eax, 7 ; x % 8
Bit Manipulation
; Test specific bit
test eax, 0x80 ; Test bit 7
jnz bit_set
; Set bit
or eax, 0x10 ; Set bit 4
; Clear bit
and eax, ~0x10 ; Clear bit 4
; Toggle bit
xor eax, 0x10 ; Toggle bit 4
; Count leading zeros
bsr eax, ecx ; Bit scan reverse
xor eax, 31 ; Convert to leading zeros
; Population count (popcnt)
popcnt eax, ecx ; Count set bits
Decompilation Patterns
Variable Recovery
; Local variable at rbp-8
mov qword [rbp-8], rax ; Store to local
mov rax, [rbp-8] ; Load from local
; Stack-allocated array
lea rax, [rbp-0x40] ; Array starts at rbp-0x40
mov [rax], edx ; array[0] = value
mov [rax+4], ecx ; array[1] = value
Function Signature Recovery
; Identify parameters by register usage
func:
; rdi used as first param (System V)
mov [rbp-8], rdi ; Save param to local
; rsi used as second param
mov [rbp-16], rsi
; Identify return by RAX at end
mov rax, [result]
ret
Type Recovery
; 1-byte operations suggest char/bool
movzx eax, byte [rdi] ; Zero-extend byte
movsx eax, byte [rdi] ; Sign-extend byte
; 2-byte operations suggest short
movzx eax, word [rdi]
movsx eax, word [rdi]
; 4-byte operations suggest int/float
mov eax, [rdi]
movss xmm0, [rdi] ; Float
; 8-byte operations suggest long/double/pointer
mov rax, [rdi]
movsd xmm0, [rdi] ; Double
Ghidra Analysis Tips
Improving Decompilation
// In Ghidra scripting
// Fix function signature
Function func = getFunctionAt(toAddr(0x401000));
func.setReturnType(IntegerDataType.dataType, SourceType.USER_DEFINED);
// Create structure type
StructureDataType struct = new StructureDataType("MyStruct", 0);
struct.add(IntegerDataType.dataType, "field_a", null);
struct.add(PointerDataType.dataType, "next", null);
// Apply to memory
createData(toAddr(0x601000), struct);
Pattern Matching Scripts
# Find all calls to dangerous functions
for func in currentProgram.getFunctionManager().getFunctions(True):
for ref in getReferencesTo(func.getEntryPoint()):
if func.getName() in ["strcpy", "sprintf", "gets"]:
print(f"Dangerous call at {ref.getFromAddress()}")
IDA Pro Patterns
IDAPython Analysis
import idaapi
import idautils
import idc
# Find all function calls
def find_calls(func_name):
for func_ea in idautils.Functions():
for head in idautils.Heads(func_ea, idc.find_func_end(func_ea)):
if idc.print_insn_mnem(head) == "call":
target = idc.get_operand_value(head, 0)
if idc.get_func_name(target) == func_name:
print(f"Call to {func_name} at {hex(head)}")
# Rename functions based on strings
def auto_rename():
for s in idautils.Strings():
for xref in idautils.XrefsTo(s.ea):
func = idaapi.get_func(xref.frm)
if func and "sub_" in idc.get_func_name(func.start_ea):
# Use string as hint for naming
pass
Best Practices
Analysis Workflow
- Initial triage: File type, architecture, imports/exports
- String analysis: Identify interesting strings, error messages
- Function identification: Entry points, exports, cross-references
- Control flow mapping: Understand program structure
- Data structure recovery: Identify structs, arrays, globals
- Algorithm identification: Crypto, hashing, compression
- Documentation: Comments, renamed symbols, type definitions
Common Pitfalls
- Optimizer artifacts: Code may not match source structure
- Inline functions: Functions may be expanded inline
- Tail call optimization:
jmpinstead ofcall+ret - Dead code: Unreachable code from optimization
- Position-independent code: RIP-relative addressing
| 1 | |
| 2 | name binary-analysis-patterns |
| 3 | description Master binary analysis patterns including disassembly, decompilation, control flow analysis, and code pattern recognition. Use when analyzing executables, understanding compiled code, or performing static analysis on binaries. |
| 4 | |
| 5 | |
| 6 | # Binary Analysis Patterns |
| 7 | |
| 8 | Comprehensive patterns and techniques for analyzing compiled binaries, understanding assembly code, and reconstructing program logic. |
| 9 | |
| 10 | ## When to Use This Skill |
| 11 | |
| 12 | Reverse-engineering an unknown executable to understand its behavior |
| 13 | Analyzing malware or obfuscated binaries with Ghidra / IDA Pro / Binary Ninja |
| 14 | Recognizing common assembly idioms (function prologues, switch tables, vtable dispatch) |
| 15 | Reconstructing high-level control flow from compiled code |
| 16 | Identifying compiler-introduced patterns (stack canaries, PIC trampolines) |
| 17 | |
| 18 | ## Detailed section: Disassembly Fundamentals |
| 19 | |
| 20 | Originally a 2047-byte section in this SKILL.md. Moved to `references/details.md` to fit Codex's 8 KB skill body cap. |
| 21 | |
| 22 | ## Control Flow Patterns |
| 23 | |
| 24 | ### Conditional Branches |
| 25 | |
| 26 | |
| 27 | ; if (a == b) |
| 28 | cmp eax, ebx |
| 29 | jne skip_block |
| 30 | ; ... if body ... |
| 31 | skip_block: |
| 32 | |
| 33 | ; if (a < b) - signed |
| 34 | cmp eax, ebx |
| 35 | jge skip_block ; Jump if greater or equal |
| 36 | ; ... if body ... |
| 37 | skip_block: |
| 38 | |
| 39 | ; if (a < b) - unsigned |
| 40 | cmp eax, ebx |
| 41 | jae skip_block ; Jump if above or equal |
| 42 | ; ... if body ... |
| 43 | skip_block: |
| 44 | |
| 45 | |
| 46 | ### Loop Patterns |
| 47 | |
| 48 | |
| 49 | ; for (int i = 0; i < n; i++) |
| 50 | xor ecx, ecx ; i = 0 |
| 51 | loop_start: |
| 52 | cmp ecx, [n] ; i < n |
| 53 | jge loop_end |
| 54 | ; ... loop body ... |
| 55 | inc ecx ; i++ |
| 56 | jmp loop_start |
| 57 | loop_end: |
| 58 | |
| 59 | ; while (condition) |
| 60 | jmp loop_check |
| 61 | loop_body: |
| 62 | ; ... body ... |
| 63 | loop_check: |
| 64 | cmp eax, ebx |
| 65 | jl loop_body |
| 66 | |
| 67 | ; do-while |
| 68 | loop_body: |
| 69 | ; ... body ... |
| 70 | cmp eax, ebx |
| 71 | jl loop_body |
| 72 | |
| 73 | |
| 74 | ### Switch Statement Patterns |
| 75 | |
| 76 | |
| 77 | ; Jump table pattern |
| 78 | mov eax, [switch_var] |
| 79 | cmp eax, max_case |
| 80 | ja default_case |
| 81 | jmp [jump_table + eax*8] |
| 82 | |
| 83 | ; Sequential comparison (small switch) |
| 84 | cmp eax, 1 |
| 85 | je case_1 |
| 86 | cmp eax, 2 |
| 87 | je case_2 |
| 88 | cmp eax, 3 |
| 89 | je case_3 |
| 90 | jmp default_case |
| 91 | |
| 92 | |
| 93 | ## Data Structure Patterns |
| 94 | |
| 95 | ### Array Access |
| 96 | |
| 97 | |
| 98 | ; array[i] - 4-byte elements |
| 99 | mov eax, [rbx + rcx*4] ; rbx=base, rcx=index |
| 100 | |
| 101 | ; array[i] - 8-byte elements |
| 102 | mov rax, [rbx + rcx*8] |
| 103 | |
| 104 | ; Multi-dimensional array[i][j] |
| 105 | ; arr[i][j] = base + (i * cols + j) * element_size |
| 106 | imul eax, [cols] |
| 107 | add eax, [j] |
| 108 | mov edx, [rbx + rax*4] |
| 109 | |
| 110 | |
| 111 | ### Structure Access |
| 112 | |
| 113 | |
| 114 | struct Example { |
| 115 | int a; // offset 0 |
| 116 | char b; // offset 4 |
| 117 | // padding // offset 5-7 |
| 118 | long c; // offset 8 |
| 119 | short d; // offset 16 |
| 120 | }; |
| 121 | |
| 122 | |
| 123 | |
| 124 | ; Accessing struct fields |
| 125 | mov rdi, [struct_ptr] |
| 126 | mov eax, [rdi] ; s->a (offset 0) |
| 127 | movzx eax, byte [rdi+4] ; s->b (offset 4) |
| 128 | mov rax, [rdi+8] ; s->c (offset 8) |
| 129 | movzx eax, word [rdi+16] ; s->d (offset 16) |
| 130 | |
| 131 | |
| 132 | ### Linked List Traversal |
| 133 | |
| 134 | |
| 135 | ; while (node != NULL) |
| 136 | list_loop: |
| 137 | test rdi, rdi ; node == NULL? |
| 138 | jz list_done |
| 139 | ; ... process node ... |
| 140 | mov rdi, [rdi+8] ; node = node->next (assuming next at offset 8) |
| 141 | jmp list_loop |
| 142 | list_done: |
| 143 | |
| 144 | |
| 145 | ## Common Code Patterns |
| 146 | |
| 147 | ### String Operations |
| 148 | |
| 149 | |
| 150 | ; strlen pattern |
| 151 | xor ecx, ecx |
| 152 | strlen_loop: |
| 153 | cmp byte [rdi + rcx], 0 |
| 154 | je strlen_done |
| 155 | inc ecx |
| 156 | jmp strlen_loop |
| 157 | strlen_done: |
| 158 | ; ecx contains length |
| 159 | |
| 160 | ; strcpy pattern |
| 161 | strcpy_loop: |
| 162 | mov al, [rsi] |
| 163 | mov [rdi], al |
| 164 | test al, al |
| 165 | jz strcpy_done |
| 166 | inc rsi |
| 167 | inc rdi |
| 168 | jmp strcpy_loop |
| 169 | strcpy_done: |
| 170 | |
| 171 | ; memcpy using rep movsb |
| 172 | mov rdi, dest |
| 173 | mov rsi, src |
| 174 | mov rcx, count |
| 175 | rep movsb |
| 176 | |
| 177 | |
| 178 | ### Arithmetic Patterns |
| 179 | |
| 180 | |
| 181 | ; Multiplication by constant |
| 182 | ; x * 3 |
| 183 | lea eax, [rax + rax*2] |
| 184 | |
| 185 | ; x * 5 |
| 186 | lea eax, [rax + rax*4] |
| 187 | |
| 188 | ; x * 10 |
| 189 | lea eax, [rax + rax*4] ; x * 5 |
| 190 | add eax, eax ; * 2 |
| 191 | |
| 192 | ; Division by power of 2 (signed) |
| 193 | mov eax, [x] |
| 194 | cdq ; Sign extend to EDX:EAX |
| 195 | and edx, 7 ; For divide by 8 |
| 196 | add eax, edx ; Adjust for negative |
| 197 | sar eax, 3 ; Arithmetic shift right |
| 198 | |
| 199 | ; Modulo power of 2 |
| 200 | and eax, 7 ; x % 8 |
| 201 | |
| 202 | |
| 203 | ### Bit Manipulation |
| 204 | |
| 205 | |
| 206 | ; Test specific bit |
| 207 | test eax, 0x80 ; Test bit 7 |
| 208 | jnz bit_set |
| 209 | |
| 210 | ; Set bit |
| 211 | or eax, 0x10 ; Set bit 4 |
| 212 | |
| 213 | ; Clear bit |
| 214 | and eax, ~0x10 ; Clear bit 4 |
| 215 | |
| 216 | ; Toggle bit |
| 217 | xor eax, 0x10 ; Toggle bit 4 |
| 218 | |
| 219 | ; Count leading zeros |
| 220 | bsr eax, ecx ; Bit scan reverse |
| 221 | xor eax, 31 ; Convert to leading zeros |
| 222 | |
| 223 | ; Population count (popcnt) |
| 224 | popcnt eax, ecx ; Count set bits |
| 225 | |
| 226 | |
| 227 | ## Decompilation Patterns |
| 228 | |
| 229 | ### Variable Recovery |
| 230 | |
| 231 | |
| 232 | ; Local variable at rbp-8 |
| 233 | mov qword [rbp-8], rax ; Store to local |
| 234 | mov rax, [rbp-8] ; Load from local |
| 235 | |
| 236 | ; Stack-allocated array |
| 237 | lea rax, [rbp-0x40] ; Array starts at rbp-0x40 |
| 238 | mov [rax], edx ; array[0] = value |
| 239 | mov [rax+4], ecx ; array[1] = value |
| 240 | |
| 241 | |
| 242 | ### Function Signature Recovery |
| 243 | |
| 244 | |
| 245 | ; Identify parameters by register usage |
| 246 | func: |
| 247 | ; rdi used as first param (System V) |
| 248 | mov [rbp-8], rdi ; Save param to local |
| 249 | ; rsi used as second param |
| 250 | mov [rbp-16], rsi |
| 251 | ; Identify return by RAX at end |
| 252 | mov rax, [result] |
| 253 | ret |
| 254 | |
| 255 | |
| 256 | ### Type Recovery |
| 257 | |
| 258 | |
| 259 | ; 1-byte operations suggest char/bool |
| 260 | movzx eax, byte [rdi] ; Zero-extend byte |
| 261 | movsx eax, byte [rdi] ; Sign-extend byte |
| 262 | |
| 263 | ; 2-byte operations suggest short |
| 264 | movzx eax, word [rdi] |
| 265 | movsx eax, word [rdi] |
| 266 | |
| 267 | ; 4-byte operations suggest int/float |
| 268 | mov eax, [rdi] |
| 269 | movss xmm0, [rdi] ; Float |
| 270 | |
| 271 | ; 8-byte operations suggest long/double/pointer |
| 272 | mov rax, [rdi] |
| 273 | movsd xmm0, [rdi] ; Double |
| 274 | |
| 275 | |
| 276 | ## Ghidra Analysis Tips |
| 277 | |
| 278 | ### Improving Decompilation |
| 279 | |
| 280 | |
| 281 | // In Ghidra scripting |
| 282 | // Fix function signature |
| 283 | Function func = getFunctionAt(toAddr(0x401000)); |
| 284 | func.setReturnType(IntegerDataType.dataType, SourceType.USER_DEFINED); |
| 285 | |
| 286 | // Create structure type |
| 287 | StructureDataType struct = new StructureDataType("MyStruct", 0); |
| 288 | struct.add(IntegerDataType.dataType, "field_a", null); |
| 289 | struct.add(PointerDataType.dataType, "next", null); |
| 290 | |
| 291 | // Apply to memory |
| 292 | createData(toAddr(0x601000), struct); |
| 293 | |
| 294 | |
| 295 | ### Pattern Matching Scripts |
| 296 | |
| 297 | |
| 298 | # Find all calls to dangerous functions |
| 299 | for func in currentProgram.getFunctionManager().getFunctions(True): |
| 300 | for ref in getReferencesTo(func.getEntryPoint()): |
| 301 | if func.getName() in ["strcpy", "sprintf", "gets"]: |
| 302 | print(f"Dangerous call at {ref.getFromAddress()}") |
| 303 | |
| 304 | |
| 305 | ## IDA Pro Patterns |
| 306 | |
| 307 | ### IDAPython Analysis |
| 308 | |
| 309 | |
| 310 | import idaapi |
| 311 | import idautils |
| 312 | import idc |
| 313 | |
| 314 | # Find all function calls |
| 315 | def find_calls(func_name): |
| 316 | for func_ea in idautils.Functions(): |
| 317 | for head in idautils.Heads(func_ea, idc.find_func_end(func_ea)): |
| 318 | if idc.print_insn_mnem(head) == "call": |
| 319 | target = idc.get_operand_value(head, 0) |
| 320 | if idc.get_func_name(target) == func_name: |
| 321 | print(f"Call to {func_name} at {hex(head)}") |
| 322 | |
| 323 | # Rename functions based on strings |
| 324 | def auto_rename(): |
| 325 | for s in idautils.Strings(): |
| 326 | for xref in idautils.XrefsTo(s.ea): |
| 327 | func = idaapi.get_func(xref.frm) |
| 328 | if func and "sub_" in idc.get_func_name(func.start_ea): |
| 329 | # Use string as hint for naming |
| 330 | pass |
| 331 | |
| 332 | |
| 333 | ## Best Practices |
| 334 | |
| 335 | ### Analysis Workflow |
| 336 | |
| 337 | **Initial triage**: File type, architecture, imports/exports |
| 338 | **String analysis**: Identify interesting strings, error messages |
| 339 | **Function identification**: Entry points, exports, cross-references |
| 340 | **Control flow mapping**: Understand program structure |
| 341 | **Data structure recovery**: Identify structs, arrays, globals |
| 342 | **Algorithm identification**: Crypto, hashing, compression |
| 343 | **Documentation**: Comments, renamed symbols, type definitions |
| 344 | |
| 345 | ### Common Pitfalls |
| 346 | |
| 347 | **Optimizer artifacts**: Code may not match source structure |
| 348 | **Inline functions**: Functions may be expanded inline |
| 349 | **Tail call optimization**: `jmp` instead of `call` + `ret` |
| 350 | **Dead code**: Unreachable code from optimization |
| 351 | **Position-independent code**: RIP-relative addressing |
| 352 |
Details
- Updated
- Sep 21, 2026
- License
- MIT
- Stars on the repo
- ★ 39,857
- Checked
- Source
- wshobson/agents ↗
- Creator
- wshobson · 179 listings
Similar skills
See all →
SkillSecurity guidance and vulnerability review for codebasesSecurity audit
MCPYou need to audit Active Directory security postureAd security reviewer
SkillApply modern web development best practices for security
SkillHelps Claude write secure web applicationsSecure Coding Guide for Web Applications
MCPReviews completed implementation against governing securitySecurity reviewer
SkillAccount-based marketing for B2B SaaSAccount-Based Marketing OperationsMore from wshobson
SkillMaster C/.NET backend development patterns for building
SkillImplement WCAG 2.2 compliant interfaces with mobileAccessibility compliance
SkillMaster Material Design 3 and Jetpack Compose patternsAndroid Mobile Design
SkillMigrate from AngularJS to Angular using hybrid modeAngular migration
SkillUnderstand anti-reversing, obfuscationAnti reversing techniques
SkillBuild production Apache Airflow DAGs with best practicesApache Airflow DAG Patterns