Pattern-Based Hooking¶
Pattern-based hooking is one of friTap's most powerful features, allowing you to analyze applications with stripped SSL libraries or statically linked implementations where traditional symbol-based hooking fails.
Overview¶
When SSL/TLS libraries are stripped of symbols or statically linked into applications, friTap cannot use traditional function name resolution. Pattern-based hooking solves this by matching byte patterns in memory to identify and hook the required functions. By default friTap has already some patterns included for well-known libaries but due to compilation and library updates it might be the case that these patterns needs to be updated.
When to Use Pattern-Based Hooking¶
Pattern-based hooking works by searching for unique byte sequences (patterns) that identify specific functions in memory. This technique is essential for:
- Stripped libraries: No symbol information available
- Statically linked SSL: BoringSSL embedded in Chrome, libflutter.so
- Obfuscated binaries: Anti-analysis protections
- Custom SSL implementations: Modified or proprietary libraries
- Mobile applications: Flutter, React Native, Unity apps
Pattern File Format¶
Pattern files use JSON format to define byte patterns for different hooking categories:
{
"version": "1.0",
"architecture": "arm64",
"platform": "android",
"library": "libflutter.so",
"patterns": {
"Dump-Keys": {
"primary": "1F 20 03 D5 ?? ?? ?? ?? F4 4F 01 A9",
"fallback": "1F 20 03 D5 ?? ?? ?? ?? ?? ?? ?? ?? F4 4F 01 A9",
"offset": 0,
"description": "SSL_read function pattern"
},
"Install-Key-Log-Callback": {
"primary": "FF 83 00 D1 ?? ?? ?? ?? F4 4F 02 A9",
"fallback": "FF 83 00 D1 ?? ?? ?? ?? ?? ?? ?? ?? F4 4F 02 A9",
"offset": 0,
"description": "SSL_write function pattern"
}
}
}
Pattern Categories¶
friTap supports five main hooking categories:
- Dump-Keys: Extract encryption keys right now we support only this feature
- Install-Key-Log-Callback: Install key logging callbacks
- KeyLogCallback-Function: Key callback function hooks
- SSL_Read: Hook SSL read operations
- SSL_Write: Hook SSL write operations
Creating Pattern Files¶
Manual Pattern Creation¶
Step 1: Identify Target Functions
Use tools like Ghidra, IDA Pro, or Radare2 to analyze the binary code of target functions:
# Use radare2 to analyze library
r2 -A libflutter.so
[0x00000000]> afl | grep -i ssl
[0x00000000]> pdf @ sym.ssl_log_secret
Step 2: Extract Byte Patterns
# Extract bytes around function prologue
# example pattern 1
[0x00000000]> px 32 @ sym.ssl_log_secret
0x12345678 1f2003d5 12345678 f44f01a9 87654321 .....O......
In other tools, retrieving the function’s bytes often requires an even more manual process:
; Example ssl_log_secret function prologue
; example pattern 2
push rbp ; 55
mov rbp, rsp ; 48 89 E5
sub rsp, 0x20 ; 48 83 EC 20
mov [rbp-8], rdi ; 48 89 7D F8
This translates to the pattern: 55 48 89 E5 48 83 EC 20 48 89 7D F8
Step 3: Create Pattern with Wildcards
Replace variable bytes with ?
or ??
:
; example pattern 1
1F 20 03 D5 ?? ?? ?? ?? F4 4F 01 A9
; example pattern 2
55 48 89 E? ?? 83 EC 20 ?8 89 ?? F8
;
?
or ??
) are used for: - Register variations - Immediate value variations - Padding bytes - Compiler-specific differences Automated Pattern Generation¶
Using BoringSecretHunter to Generate Patterns:
For applications with stripped libraries where we only interested in a pattern to dump the keys (category Dump-Keys
), we recommend using our tool BoringSecretHunter to automatically generate these patterns. These generated byte patterns can then be supplied to friTap.
Use BoringSecretHunter with its Docker container:
# Create directories for BoringSecretHunter
mkdir -p binary results
# Copy target libraries to analyze
cp libcronet.113.0.5672.61.so binary/
cp libssl.so binary/
# Run BoringSecretHunter with Docker (recommended)
docker run --rm \
-v "$(pwd)/binary":/usr/local/src/binaries \
-v "$(pwd)/results":/host_output \
boringsecrethunter
Analyzing libcronet.113.0.5672.61.so...
BoringSecretHunter
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⠾⠛⢉⣉⣉⣉⡉⠛⠷⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⠋⣠⣴⣿⣿⣿⣿⣿⡿⣿⣶⣌⠹⣷⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣼⠁⣴⣿⣿⣿⣿⣿⣿⣿⣿⣆⠉⠻⣧⠘⣷⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢰⡇⢰⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⢸⣿⠛⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠈⣷⠀⢿⡆⠈⠛⠻⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣧⡀⠻⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢼⠿⣦⣄⠀⠀⠀⠀⠀⠀⠀⣀⣴⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣠⣾⣿⣦⠀⠀⠈⠉⠛⠓⠲⠶⠖⠚⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⣠⣾⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⣠⣾⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⣾⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⣄⠈⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Identifying the ssl_log_secret() function for extracting key material using Frida.
Version: 1.0.2 by Daniel Baier
[*] Start analyzing binary libcronet.113.0.5672.61.so (CPU Architecture: AARCH64). This might take a while ...
[*] Target function identified (ssl_log_secret):
Function label: FUN_00493BB0
Function offset: 00493BB0 (0X493BB0)
Byte pattern for frida (friTap): 3F 23 03 D5 FF C3 01 D1 FD 7B 04 A9 F6 57 05 A9 F4 4F 06 A9 FD 03 01 91 08 34 40 F9 08 11 41 F9 C8 07 00 B4
# Use generated patterns with friTap
fritap --patterns results/libcronet.so_patterns.json -k keys.log com.example.flutter_app
Why Docker?
The Docker approach provides a pre-configured environment with Ghidra, eliminating setup complexity and ensuring consistent results across platforms.
Using Pattern Files¶
Basic Pattern Usage¶
# Use pattern file for analysis
fritap --patterns patterns.json -k keys.log target_app
# Combine with other options
fritap --patterns patterns.json --pcap traffic.pcap -k keys.log target_app
# Mobile application with patterns
fritap -m --patterns android_patterns.json -k keys.log com.example.app
Debug Pattern Matching¶
# Enable debug output to see pattern matching
fritap -do --patterns patterns.json -v target_app
# Expected output:
# [*] Pattern matching enabled
# [*] Loading patterns from patterns.json
# [*] Searching for SSL_Read pattern in libssl.so
# [*] Pattern match found at offset 0x12345678
# [*] Hooking SSL_read at 0x12345678
Platform-Specific Patterns¶
Android Patterns:
# ARM64 Android patterns
fritap -m --patterns android_arm64_patterns.json -k keys.log com.example.app
# x86_64 Android patterns (emulator)
fritap -m --patterns android_x64_patterns.json -k keys.log com.example.app
iOS Patterns:
Advanced Pattern Techniques¶
Multi-Architecture Support¶
Create patterns for multiple architectures:
{
"version": "1.0",
"patterns": {
"arm64": {
"SSL_Read": {
"primary": "1F 20 03 D5 ?? ?? ?? ?? F4 4F 01 A9"
}
},
"x86_64": {
"SSL_Read": {
"primary": "55 48 89 E5 ?? ?? ?? ?? 48 83 EC ??"
}
},
"armv7": {
"SSL_Read": {
"primary": "?? ?? 2D E9 ?? ?? ?? ?? ?? ?? ?? ??"
}
}
}
}
Real-World Examples¶
Flutter Applications¶
Flutter apps often have statically linked BoringSSL:
Flutter Pattern File (flutter_patterns.json):
{
"version": "1.0",
"architecture": "arm64",
"platform": "android",
"library": "libflutter.so",
"patterns": {
"Dump-Keys": {
"primary": "FF 83 00 D1 FD 7B 01 A9 ?? ?? ?? ?? F4 4F 03 A9",
"fallback": "FF 83 00 D1 ?? ?? ?? ?? ?? ?? ?? ?? F4 4F 03 A9"
}
}
}
Usage:
Cronet Applications¶
Chrome's Cronet library with embedded BoringSSL:
Cronet Pattern File (cronet_patterns.json):
{
"version": "1.0",
"architecture": "arm64",
"platform": "android",
"library": "libcronet.so",
"patterns": {
"SSL_Read": {
"primary": "FF 83 00 D1 FD 7B 01 A9 F4 4F 02 A9 F6 57 03 A9",
"fallback": "FF 83 00 D1 ?? ?? ?? ?? F4 4F 02 A9",
"offset": 0,
"description": "Cronet BoringSSL SSL_read"
},
"SSL_Write": {
"primary": "FF 83 00 D1 FD 7B 01 A9 F4 4F 02 A9 F6 57 03 A9",
"fallback": "FF 83 00 D1 ?? ?? ?? ?? F4 4F 02 A9",
"offset": 0,
"description": "Cronet BoringSSL SSL_write"
}
}
}
Usage:
Pattern Development Workflow¶
Step-by-Step Pattern Creation¶
1. Analyze Target Application:
# Extract APK and analyze libraries
apktool d target_app.apk
cd target_app/lib/arm64-v8a/
file *.so | grep -v stripped
2. Use Static Analysis:
# Analyze with radare2
r2 -A libssl.so
[0x00000000]> afl | grep -i ssl_read
[0x00000000]> pdf @ sym.SSL_read
3. Extract and Test Patterns:
# Test pattern matching
fritap --patterns test_patterns.json -do -v target_app
# Check debug output for pattern matches
grep -i "pattern" debug_output.log
4. Refine Patterns:
Pattern Validation¶
Test Pattern Reliability:
#!/bin/bash
# Test pattern across multiple app versions
PATTERN_FILE="$1"
APP_PACKAGE="$2"
for version in v1.0 v1.1 v1.2; do
echo "Testing $APP_PACKAGE $version"
fritap -m --patterns "$PATTERN_FILE" -k "test_${version}.log" "$APP_PACKAGE"
if [ -s "test_${version}.log" ]; then
echo "✓ $version: Pattern worked"
else
echo "✗ $version: Pattern failed"
fi
done
Troubleshooting Patterns¶
Common Issues¶
Pattern Not Found:
# Enable debug output
fritap -do --patterns patterns.json -v target_app
# Check library loading
fritap --list-libraries target_app
# Verify pattern syntax
python -m json.tool patterns.json
False Positives:
Performance Issues:
Debug Techniques¶
Pattern Matching Debug:
# Enable maximum verbosity
fritap -do -v --patterns patterns.json target_app 2>&1 | tee pattern_debug.log
# Analyze pattern matching process
grep -E "(Pattern|Match|Hook)" pattern_debug.log
Memory Analysis:
# Dump memory regions for analysis
fritap -c memory_dump.js --patterns patterns.json target_app
# Where memory_dump.js contains:
# Memory.scan(ptr("0x7000000000"), 0x10000000, "1F 20 03 D5", {
# onMatch: function(address, size) {
# console.log("Match at: " + address);
# }
# });
Best Practices¶
1. Pattern Design¶
- Use sufficient context: Include enough bytes to avoid false positives
- Implement fallbacks: Provide alternative patterns for robustness
- Document patterns: Include descriptions and version information
- Test thoroughly: Validate across different versions and devices
2. Maintenance¶
- Version control: Track pattern changes over time
- Automated testing: Validate patterns against known samples
- Community sharing: Contribute patterns to friTap community
- Regular updates: Update patterns for new library versions
3. Performance¶
- Optimize pattern length: Balance specificity with performance
- Target specific libraries: Avoid scanning unnecessary memory regions
- Use caching: Cache successful pattern matches
- Parallel scanning: Use multiple patterns simultaneously
How Pattern-Based Hooking Works¶
1. Pattern Generation¶
Patterns are generated by analyzing the binary code of target functions:
; Example SSL_read function prologue
push rbp ; 55
mov rbp, rsp ; 48 89 E5
sub rsp, 0x20 ; 48 83 EC 20
mov [rbp-8], rdi ; 48 89 7D F8
This translates to the pattern: 55 48 89 E5 48 83 EC 20 48 89 7D F8
2. Pattern Matching¶
friTap searches for these patterns in the target process memory:
function find_pattern_in_module(module_name: string, pattern: string): NativePointer[] {
const module = Process.getModuleByName(module_name);
const pattern_bytes = pattern_to_bytes(pattern);
return Memory.scan(module.base, module.size, pattern_bytes, {
onMatch: function(address, size) {
return address;
},
onError: function(reason) {
devlog_error(`Pattern scan failed: ${reason}`);
}
});
}
3. Hook Installation¶
Once patterns are found, hooks are installed at the matching addresses:
function hook_by_pattern(
module_name: string,
pattern: string,
function_name: string,
hook_callback: Function
): boolean {
const addresses = find_pattern_in_module(module_name, pattern);
if (addresses.length === 0) {
devlog_error(`Pattern not found: ${pattern}`);
return false;
}
if (addresses.length > 1) {
devlog_error(`Multiple matches for pattern: ${pattern}`);
return false;
}
Interceptor.attach(addresses[0], hook_callback);
return true;
}
Summary¶
Pattern-based hooking is a powerful technique that extends friTap's capabilities to handle stripped binaries and complex scenarios. By understanding the principles, implementing proper validation, and following best practices, you can create robust pattern-based hooks that work reliably across different environments and library versions.
The key to successful pattern-based hooking is careful pattern selection, thorough testing, and robust error handling. Combined with friTap's other hooking methods, it provides comprehensive coverage for SSL/TLS traffic analysis in any scenario.
Next Steps¶
- Learn about custom Frida scripts using
-c
parameter for advanced hooking - Explore anti-detection techniques in specialized security analysis scenarios
- Check platform-specific guides for pattern examples