Extract ssl_log_secret() offsets from BoringSSL/RustLS binaries for Frida hooking
Project description
BoringSecretHunter
A Ghidra-based tool designed to analyze binaries and identify the ssl_log_secret() function. The tool extracts and prints the byte pattern of this function, making it ready for use with Frida for efficient function hooking and TLS key extraction.
Its primary purpose is to analyze binaries with BoringSSL statically linked into them.
The extracted pattern can be used directly with friTap to hook the ssl_log_secret() function in target applications.
Building
Step 1: Build the Docker Image
Run the following command in the root of the BoringSecretHunter directory to build the Docker image:
docker build -t boringsecrethunter .
Usage
Once the image is built, you can run the Docker container and provide the binary you want to analyze.
For example, if your binary is named libcrypto.so and is located in the binary/ folder, run:
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
Installation (CLI)
BoringSecretHunter is also available as a pip-installable CLI tool called bsh. This requires a local Ghidra installation.
pip install boringsecrethunter
bsh analyze binary/libcronet.132.0.6779.0.so
For debug output:
bsh analyze -d binary/libcronet.132.0.6779.0.so
To simplify Ghidra installation, you can use ghidractl, our tool designed to simplify and streamline the setup process.
Supported Input Types
BoringSecretHunter accepts the following file types in the binary/ folder:
- ELF, Mach-O, PE32 binaries — analyzed directly (e.g.,
.so,.dylib,.dll) - Raw binary data files — memory dumps without proper headers (e.g.,
.binfiles reported asdatabyfile) are imported and analyzed as raw binaries - IPA files — iOS app bundles; Mach-O binaries are extracted automatically before analysis
- APK files — Android app bundles; ELF
.sofiles are extracted automatically before analysis
Debug Output
If you're experiencing issues, try running BoringSecretHunter with debug output enabled. There are two ways:
Option 1: Environment variable (recommended for Docker)
$ docker run --rm -v "$(pwd)/binary":/usr/local/src/binaries -v "$(pwd)/results":/host_output -e DEBUG_RUN=true boringsecrethunter
Option 2: Command-line flag
$ docker run --rm -v "$(pwd)/binary":/usr/local/src/binaries -v "$(pwd)/results":/host_output boringsecrethunter -d
Note: Do not combine both methods (e.g.,
-e DEBUG_RUN=true ... boringsecrethunter -d). Use one or the other.
Raw Data Files (DATA_PROCESSOR)
When analyzing raw binary data files (e.g., memory dumps reported as data by file), BoringSecretHunter auto-detects the CPU architecture from sibling binaries in the same folder. To override the auto-detection, set the DATA_PROCESSOR environment variable:
$ docker run --rm -v "$(pwd)/binary":/usr/local/src/binaries -v "$(pwd)/results":/host_output \
-e DATA_PROCESSOR="AARCH64:LE:64:v8A" boringsecrethunter
Supported processor values:
| Value | Architecture |
|---|---|
AARCH64:LE:64:v8A |
ARM 64-bit (default) |
ARM:LE:32:v8 |
ARM 32-bit |
x86:LE:64:default |
x86-64 |
x86:LE:32:default |
x86 32-bit |
Strategy Selection
Status: Under active development. SSL_read/SSL_write detection is opt-in and experimental. The strategies below may produce false positives, especially on stripped binaries or non-BoringSSL TLS stacks. Feedback welcome.
BoringSecretHunter uses 8 detection strategies to identify SSL_read and SSL_write functions. You can control which strategies are used:
--no-symbols— Skip symbol table lookup (useful for verifying pattern-based detection)--strategy <name>— Use only a specific strategy
bsh analyze --no-symbols path/to/libssl.so
bsh analyze --strategy ErrorStringFingerprinting path/to/libssl.so
See STRATEGY_GUIDE.md for details on each strategy and usage examples.
SSL_read / SSL_write Scanning
Status: Under active development. This feature is opt-in and experimental. Detection uses 8 fallback strategies and may produce false positives, especially on stripped binaries or non-BoringSSL TLS stacks. Feedback welcome.
By default, BoringSecretHunter only identifies the ssl_log_secret() function. To also scan for SSL_read and SSL_write functions, use the --find-ssl-rw flag:
bsh analyze --find-ssl-rw path/to/libssl.so
Docker (environment variable):
docker run --rm -v "$(pwd)/binary":/usr/local/src/binaries -e FIND_SSL_RW=true boringsecrethunter
Docker (command-line flag):
docker run --rm -v "$(pwd)/binary":/usr/local/src/binaries boringsecrethunter --find-ssl-rw
Note: The
--no-symbolsand--strategyflags imply--find-ssl-rwautomatically, since they only affect SSL_read/SSL_write identification.
Interactive Debugging
For deeper inspection or troubleshooting, you can start BoringSecretHunter in interactive mode and work directly with the Headless Analyzer of Ghidra invoking our script:
$ docker run -it --entrypoint /bin/bash -v "$(pwd)/binary":/usr/local/src/binaries -v "$(pwd)/results":/host_output boringsecrethunter
# /opt/ghidra_12.0.3_PUBLIC/support/analyzeHeadless /tmp ghidra_project_$(date +%s) \
-import "$bin" -scriptPath /usr/local/src/ -prescript /usr/local/src/MinimalAnalysisOption.java -postScript /usr/local/src/BoringSecretHunter.java DEBUG_RUN=true
How to identify SSL/TLS libraries
To identify which SSL/TLS libraries a target application uses at runtime, see tlsLibHunter. It scans a process’ mapped memory ranges for TLS-related strings (e.g., CLIENT_RANDOM) and extracts the corresponding shared libraries from the device. This works well on Android where multiple TLS stacks may be present (Conscrypt/BoringSSL, Cronet, app-bundled JNI libs, etc.).
Once you have identified and extracted the target library, provide it to BoringSecretHunter for analysis.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file boringsecrethunter-1.3.0.tar.gz.
File metadata
- Download URL: boringsecrethunter-1.3.0.tar.gz
- Upload date:
- Size: 3.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20df552722d06a8186bcd8db9f56362fd73c9d786eca45f42c887ae414e37145
|
|
| MD5 |
513138ec5f0ddd591682f50289c153a8
|
|
| BLAKE2b-256 |
b0b91ea17b639ca95be39b3b41f3de9a470ee611f7599254ec7ce9deb771012d
|
Provenance
The following attestation bundles were made for boringsecrethunter-1.3.0.tar.gz:
Publisher:
publish.yml on monkeywave/BoringSecretHunter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
boringsecrethunter-1.3.0.tar.gz -
Subject digest:
20df552722d06a8186bcd8db9f56362fd73c9d786eca45f42c887ae414e37145 - Sigstore transparency entry: 1566783560
- Sigstore integration time:
-
Permalink:
monkeywave/BoringSecretHunter@a80bbf17b79b80684319f379f570f8a292d7cdce -
Branch / Tag:
refs/heads/main - Owner: https://github.com/monkeywave
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a80bbf17b79b80684319f379f570f8a292d7cdce -
Trigger Event:
push
-
Statement type:
File details
Details for the file boringsecrethunter-1.3.0-py3-none-any.whl.
File metadata
- Download URL: boringsecrethunter-1.3.0-py3-none-any.whl
- Upload date:
- Size: 56.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7e171c3bb803b41904735dcd692e72ac4e41e5a9af1cfd805ad9b02a4525cbe
|
|
| MD5 |
abc0082b8a97e0f0b99742ef36912f24
|
|
| BLAKE2b-256 |
bdf9164063c7161c6337ca00f54e576ce12d203f799de81aaa2ca1e480045687
|
Provenance
The following attestation bundles were made for boringsecrethunter-1.3.0-py3-none-any.whl:
Publisher:
publish.yml on monkeywave/BoringSecretHunter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
boringsecrethunter-1.3.0-py3-none-any.whl -
Subject digest:
a7e171c3bb803b41904735dcd692e72ac4e41e5a9af1cfd805ad9b02a4525cbe - Sigstore transparency entry: 1566783578
- Sigstore integration time:
-
Permalink:
monkeywave/BoringSecretHunter@a80bbf17b79b80684319f379f570f8a292d7cdce -
Branch / Tag:
refs/heads/main - Owner: https://github.com/monkeywave
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a80bbf17b79b80684319f379f570f8a292d7cdce -
Trigger Event:
push
-
Statement type: