A RoBERTa-based masked language model trained on binary executable files for security research and binary analysis. Part of the Glaurung project: a modern reverse engineering framework with first-class AI integration.
Overview
Glaurung Large 001 is a transformer model specifically designed for understanding binary executable files. It uses a custom BPE (Byte Pair Encoding) tokenizer trained on multi-byte patterns from various binary formats across multiple architectures (x86-64, ARM64, etc.) and operating systems (Linux, Alpine, Ubuntu, Debian, Rocky).
This is the large variant (371M parameters, 24 layers) offering enhanced understanding of binary patterns. For faster inference, see glaurung-small-001 (160M parameters).
Key Features
Custom Binary Tokenizer: BPE tokenizer that creates efficient multi-byte tokens from binary data
Binary-Aware: Trained on actual executable files, not hex strings
Multi-Architecture: Understands patterns from various CPU architectures and file formats
Latin-1 Encoding: Preserves all byte values (0-255) without loss
Large Model: 371M parameters with deeper architecture for enhanced binary understanding
Model Details
Architecture: RoBERTa for Masked Language Modeling
This model is part of the Glaurung project ecosystem:
🔧 Main Project
Glaurung - A modern reverse engineering framework designed to replace Ghidra with first-class AI integration throughout the analysis pipeline. Built with Rust's performance and Python's accessibility, featuring AI agents integrated at every level from format detection to decompilation.
binary-tokenizer-005 - 65K vocabulary BPE tokenizer trained on multi-byte patterns
Performance Comparison vs Glaurung Small 001
Metric
Glaurung Small 001
Glaurung Large 001
Improvement
Architecture
Parameters
~160M
~371M
+132%
Hidden Size
768
1024
+33%
Layers
12
24
+100%
Attention Heads
12
16
+33%
ELF Magic Prediction (\x7fEL)
Top-1 Confidence
~45-50% (est.)
59.2%
Stronger recognition
x86 Prologue in Context
Top-1 Confidence
~70-80% (est.)
100.0%
Perfect prediction
PE Magic Recognition
Top-1 Confidence
~5-8% (est.)
7.3% (rank #2)
Weak (training bias)
Binary Similarity Detection
ELF-to-ELF Similarity
0.85-0.95
0.67-0.92
More nuanced
ELF-to-Text Separation
~0.25-0.30
~0.21-0.32
Similar
Key Improvements:
Dramatically improved confidence on binary pattern prediction (+21pp on ELF magic)
Deeper architecture enables better long-range dependencies in binary code
More stable predictions with near-perfect accuracy on structured headers
Larger capacity for learning complex multi-architecture binary patterns
Installation & Loading
pip install transformers torch
python
1from transformers import AutoTokenizer, AutoModelForMaskedLM, AutoModel, pipeline
23# Method 1: Load with pipeline for fill-mask tasks4fill_mask = pipeline('fill-mask', model='mjbommar/glaurung-large-001', device=-1)56# Method 2: Load model and tokenizer directly for fill-mask7model = AutoModelForMaskedLM.from_pretrained('mjbommar/glaurung-large-001')8tokenizer = AutoTokenizer.from_pretrained('mjbommar/glaurung-large-001')910# Method 3: Load base model for feature extraction/embeddings11model_base = AutoModel.from_pretrained('mjbommar/glaurung-large-001')
Usage Guide
1. Loading Binary Data (Critical!)
Binary files MUST be read as bytes and converted to latin-1 encoding:
python
1# CORRECT: Read as bytes, decode with latin-12withopen('/usr/bin/ls','rb')as f:3 binary_data = f.read()# Read first 512 bytes or as needed4 text = binary_data.decode('latin-1', errors='ignore')56# WRONG: Never use hex strings or other encodings7# hex_string = "7f454c46..." # ❌ Will not work8# utf8_text = binary_data.decode('utf-8') # ❌ Will lose bytes
2. Understanding the BPE Tokenizer
The tokenizer creates multi-byte tokens from common binary patterns:
python
1from transformers import AutoTokenizer
23tokenizer = AutoTokenizer.from_pretrained('mjbommar/glaurung-large-001')45# Example: ELF header tokenization6elf_header =b'\x7fELF\x02\x01\x01\x00'7text = elf_header.decode('latin-1')89tokens = tokenizer(text, return_tensors='pt')10token_ids = tokens['input_ids'][0].tolist()1112# Decode tokens individually to see multi-byte patterns13for token_id in token_ids[1:5]:# Skip special tokens14 decoded = tokenizer.decode([token_id], skip_special_tokens=True)15print(f"Token {token_id}: {repr(decoded)}")1617# Output:18# Token 45689: '\x7fEL' # ELF magic compressed to one token!19# Token 3665: 'F\x02' # Format byte + 64-bit flag20# Token 458: '\x01\x01' # Little-endian + version21# Token 600: '\x00\x00\x00\x00\x00\x00\x00\x00\x00' # Padding
3. Fill-Mask Task (Token-Level Prediction)
Important: Masking works at the TOKEN level, not byte level!
The pipeline handles tokenization automatically but requires understanding multi-byte tokens:
python
1from transformers import pipeline
23# Load pipeline4fill_mask = pipeline('fill-mask', model='mjbommar/glaurung-large-001', device=-1)56# Read binary7withopen('/usr/bin/ls','rb')as f:8 binary_data = f.read(100)9 text = binary_data.decode('latin-1', errors='ignore')1011# Create masked input at token boundaries12# First, tokenize to understand token boundaries13tokenizer = fill_mask.tokenizer
14tokens = tokenizer(text)15decoded_tokens =[tokenizer.decode([tid], skip_special_tokens=True)for tid in tokens['input_ids']]1617# Reconstruct with mask at token boundary18masked_text =''.join([19 decoded_tokens[0],# <|start|>20 fill_mask.tokenizer.mask_token,# Mask the ELF magic21''.join(decoded_tokens[2:])# Rest of tokens22])2324# Predict25predictions = fill_mask(masked_text, top_k=3)26for pred in predictions:27print(f"{repr(pred['token_str'])}: {pred['score']:.2%}")
5. Feature Extraction & Embedding Similarity
Compare binary files by their learned embeddings:
python
1from transformers import AutoTokenizer, AutoModel
2import torch
3import torch.nn.functional as F
4from pathlib import Path
56# Load for embeddings (not MaskedLM)7tokenizer = AutoTokenizer.from_pretrained('mjbommar/glaurung-large-001')8model = AutoModel.from_pretrained('mjbommar/glaurung-large-001')9model.eval()1011defget_binary_embedding(file_path, max_bytes=512):12"""Extract embedding for a binary file using mean pooling"""13withopen(file_path,'rb')as f:14 binary_data = f.read(max_bytes)15 text = binary_data.decode('latin-1', errors='ignore')1617# Tokenize18 tokens = tokenizer(text, return_tensors='pt',19 padding=True, truncation=True, max_length=512)2021# Get embeddings with mean pooling22with torch.no_grad():23 outputs = model(**tokens)24# Mean pooling (better than CLS token for this model)25 attention_mask = tokens['attention_mask']26 hidden_states = outputs.last_hidden_state
2728# Mask padding tokens29 mask_expanded = attention_mask.unsqueeze(-1).expand(hidden_states.size()).float()30 sum_embeddings = torch.sum(hidden_states * mask_expanded, dim=1)31 sum_mask = torch.clamp(mask_expanded.sum(dim=1),min=1e-9)32 embedding = sum_embeddings / sum_mask
3334return embedding
3536# Compare multiple binaries37files =['/usr/bin/ls','/usr/bin/cat','/usr/bin/echo','/etc/passwd']38embeddings ={}3940for file_path in files:41if Path(file_path).exists():42 name = Path(file_path).name
43 embeddings[name]= get_binary_embedding(file_path)4445# Calculate similarities46print("Cosine Similarity Matrix:")47names =list(embeddings.keys())48for name1 in names:49 similarities =[]50for name2 in names:51 sim = F.cosine_similarity(embeddings[name1], embeddings[name2], dim=-1).item()52 similarities.append(f"{sim:.3f}")53print(f"{name1:10s}: {' '.join(similarities)}")5455# Expected output:56# ELF executables (ls, cat, echo) will have high similarity (0.85-0.95)57# Text file (passwd) will have low similarity (0.25-0.30) to ELF files
Real-World Example: ELF Header Analysis
python
1from transformers import AutoTokenizer, AutoModelForMaskedLM
2import torch
34# Load model and tokenizer5model = AutoModelForMaskedLM.from_pretrained('mjbommar/glaurung-large-001')6tokenizer = AutoTokenizer.from_pretrained('mjbommar/glaurung-large-001')78# Analyze ELF executable structure9withopen('/usr/bin/ls','rb')as f:10 binary_data = f.read(512)# Read enough for context1112print(f"Raw bytes (hex): {binary_data[:16].hex()}")13# Output: 7f454c460201010000000000000000001415# Convert to latin-1 for model16text = binary_data.decode('latin-1', errors='ignore')1718# Tokenize to see learned patterns19tokens = tokenizer(text, return_tensors='pt')20token_ids = tokens['input_ids'][0].tolist()2122# Show what tokens the model learned23print("\nTokenized ELF header:")24for i inrange(1,min(5,len(token_ids)-1)):# First few content tokens25 token_text = tokenizer.decode([token_ids[i]], skip_special_tokens=True)26print(f"Token {i}: {token_ids[i]:5d} = {repr(token_text)}")2728# Output:29# Token 1: 45689 = '\x7fEL' - ELF magic compressed to one token!30# Token 2: 3665 = 'F\x02' - 'F' + 64-bit flag31# Token 3: 458 = '\x01\x01' - Little-endian + version32# Token 4: 600 = '\x00\x00\x00\x00\x00\x00\x00\x00\x00' - Padding3334# Test model's understanding by masking each token35print("\nTesting model predictions:")36for position in[1,2,3]:# Test first 3 content tokens37 masked_ids = token_ids.copy()38 original_token = masked_ids[position]39 masked_ids[position]= tokenizer.mask_token_id
4041# Create input tensors42 tokens_masked ={43'input_ids': torch.tensor([masked_ids]),44'attention_mask': torch.tensor([[1]*len(masked_ids)])45}4647# Get prediction48with torch.no_grad():49 outputs = model(**tokens_masked)50 predictions = outputs.logits[0, position].softmax(dim=-1)51 predicted_token = predictions.argmax().item()52 confidence = predictions.max().item()5354# Show results55 original_text = tokenizer.decode([original_token], skip_special_tokens=True)56 predicted_text = tokenizer.decode([predicted_token], skip_special_tokens=True)57 correct ="✓"if predicted_token == original_token else"✗"5859print(f"Position {position}: {correct}")60print(f" Original: {repr(original_text)}")61print(f" Predicted: {repr(predicted_text)} (confidence: {confidence:.1%})")6263# Expected Output:64# Position 1: ✓65# Original: '\x7fEL'66# Predicted: '\x7fEL' (confidence: 59.2%)67# Position 2: ✗ (prefers single 'F')68# Original: 'F\x02'69# Predicted: 'F' (confidence: 96.0%)70# Position 3: ✗ (not in top 5)71# Original: '\x01\x01'72# Predicted: '\x00\x00\x00\x00\x00\x00\x00\x00' (confidence: 59.1%)
Multi-Format Analysis: ELF vs PE Headers & x86 Instructions
Systematic testing reveals performance varies by format and training data exposure:
Performance Summary Table
Pattern Type
Confidence
Rank
Notes
ELF magic (\x7fEL)
59.2%
#1
Strong (94.6% of training data)
PE magic (MZ)
7.3%
#2
Proportional to training (5.4% of data)
x86 prologue (PUSH RBP; MOV RBP, RSP)
100.0%
#1
Perfect in full context
ELF Header Recognition (Strong)
python
1# Test: /usr/bin/ls with 152 bytes of context2# Token 1: '\x7fEL' (3-byte ELF magic)3# Result: 59.23% confidence, rank #1 ✓
The model strongly recognizes ELF headers (94.6% of training data).
PE Header Recognition (Limited)
python
1# Test: Realistic DOS/PE header with 152 bytes of context2# Token 1: 'MZ' (2-byte PE signature)3# Result: 7.34% confidence, rank #2 (null bytes ranked #1 at 29.95%)
PE recognition reflects limited training exposure (5.4% of training data, 647 files).
x86 Instructions (Context-Dependent)
python
1# Test: Function prologue in /usr/bin/ls at offset 0x4e052# Token: 'UH\x89å' = 0x554889e5 (4 bytes: PUSH RBP; MOV RBP, RSP)3# Result: 100.00% confidence, rank #1 ✓
Key Finding: The BPE tokenizer learned to respect x86 instruction boundaries!
1-byte tokens: PUSH reg (0x55), RET (0xc3)
2-byte tokens: MOV reg,reg with ModR/M (0x89e5)
4-byte tokens: Common prologues (0x554889e5)
Performance is excellent with full binary context but degrades on isolated instruction bytes.
Training Data Distribution & Performance Correlation
The model was trained on the following binary distribution:
Source
Format
File Count
Size (MB)
% by Count
% by Size
Debian/Ubuntu/Alpine packages
ELF
11,330
4,572
94.6%
68.9%
Windows Update drivers + SOREL-20M malware
PE
647
2,062
5.4%
31.1%
Total
11,977
6,634
Key Metrics:
By file count: 17.5:1 (ELF:PE)
By data size: 2.2:1 (ELF:PE)
PE files are 8x larger on average (3.19 MB vs 0.40 MB per file)
This distribution explains the observed performance:
Format
Training Data
Recognition Confidence
Notes
ELF
11,330 files (95%) / 4,572 MB (69%)
59.2%
Dominant by count
PE
647 files (5%) / 2,062 MB (31%)
7.3%
Better represented by size
Key Takeaway: The model's PE performance reflects training data composition. While PE is only 5% by file count, it represents 31% by size due to larger average file sizes. The 8.1x performance gap (59.2% vs 7.3%) roughly correlates with the 17.5x file count imbalance, though size-based exposure is more balanced.