Skip to content

Repository files navigation

Work in progress

Fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations

Fuzzamoto provides a framework for coverage-guided fuzzing of Bitcoin full node implementations in a holistic fashion. Instead of the common in-process LLVMFuzzerTestOneInput style tests, testing is performed through external facing interfaces, such as P2P, RPC, etc (Bitcoin Core contributors can think of it as "Functional Fuzz Tests").

Design

Snapshot fuzzing lies at the core of Fuzzamoto, to allow for deterministic and performant fuzzing of one or more full node instances at once. Currently, only support for snapshot fuzzing with afl++'s Nyx mode is implemented but future integration with other snapshot fuzzing tools is possible (e.g. full-system libafl_qemu).

The rough architecture when fuzzing with fuzzamoto looks as follows:

 Report bug
^
|
Yes
|
-------------------> Bug? -------------------
| |
---------|------------ Nyx VM ---------------------- |
| | | |
| ------------- ------------- | |
| | Fuzzamoto | <---p2p/rpc/...---> | Full Node | | No
| ------------- ------------- | |
| ^ | |
---------|------------------------------------------ |
| |
| |
Generate testcase < ----------------------------------

At the moment, only support for Bitcoin Core as target application is implemented but the existing abstractions allow for integration with other projects as well (e.g. btcd, libbitcoin).

The full node software under test is extended with a crash handler that reports application aborts to Nyx (See nyx-crash-handler.c) and the harness includes a nyx agent that deals with setup and snapshot creation (See nyx-agent.c).

Usage

Actual fuzzing (i.e. input generation) can currently only be done on bare metal x86-64 systems (limitiation of Nyx). See the Dockerfile for an example setup.

Example: fuzzing the http server of Bitcoin Core:

$ docker build -t fuzzamoto .
$ docker run --privileged -it fuzzamoto bash
root@...# mkdir /tmp/in && echo "AAA" > /tmp/in/A
root@...# afl-fuzz -X -i /tmp/in -o /tmp/out -- /tmp/fuzzamoto_scenario-http-server

Multi-core campaigns

Running a multi-core campaign can be done with AFL_Runner (installed in the Dockerfile).

Example: fuzzing the http server of Bitcoin Core with 16 cores:

root@...# aflr run --nyx-mode --target /tmp/fuzzamoto_scenario-http-server/ \
--input-dir /tmp/http_in/ --output-dir /tmp/http_out/ \
--runners 16

Reproducing testcases

Crashing inputs or other solutions can be reproduced on any architecture with something similar to the following:

$ # Rebuild fuzzamoto without nyx feature
$ cargo build --release --features inherit_stdout --workspace
$ cat ./testcase.dat | ./target/release/fuzzamoto_scenario-http-server ./bitcoind

--features inherit_stdout is used to inherit stdout from the target application, such that any logs, stack traces, etc. are printed to the terminal.

Custom target patches

Certain targets require custom patches for effective fuzzing and testcase reproduction. These can be found in the target-patches directory.

Maintaining external patches should be avoided if possible, as it has several downsides:

  • They might become outdated and require rebase
  • They might not apply to a PR we would like to fuzz, in which case the patch needs to be adjusted just for the PR
  • Testcases might not reproduce without the patches and it is on the user to make sure all patches were applied correctly

If a patch is necessary, then landing it in the target application is preferred but in the case of a fuzz blocker (e.g. checksum check in the target) the best solution is to make the harness/test produce valid inputs (if possible).

Current patches:

  • bitcoin-core-rng.patch: Attempts to make Bitcoin Core's RNG deterministic

Bugs found by Fuzzamoto

ProjectBugScenarioSecurity
Bitcoin Corebitcoin/bitcoin#32111wallet-migration
Bitcoin Corebitcoin/bitcoin#32112wallet-migration
Bitcoin Corebitcoin/bitcoin#32173rpc-generic

About

Holistic Fuzzing for Bitcoin Protocol Implementations

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - Crypt-iQ/fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations · GitHub
Skip to content

Repository files navigation

Work in progress

Fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations

Fuzzamoto provides a framework for coverage-guided fuzzing of Bitcoin full node implementations in a holistic fashion. Instead of the common in-process LLVMFuzzerTestOneInput style tests, testing is performed through external facing interfaces, such as P2P, RPC, etc (Bitcoin Core contributors can think of it as "Functional Fuzz Tests").

Design

Snapshot fuzzing lies at the core of Fuzzamoto, to allow for deterministic and performant fuzzing of one or more full node instances at once. Currently, only support for snapshot fuzzing with afl++'s Nyx mode is implemented but future integration with other snapshot fuzzing tools is possible (e.g. full-system libafl_qemu).

The rough architecture when fuzzing with fuzzamoto looks as follows:

 Report bug
^
|
Yes
|
-------------------> Bug? -------------------
| |
---------|------------ Nyx VM ---------------------- |
| | | |
| ------------- ------------- | |
| | Fuzzamoto | <---p2p/rpc/...---> | Full Node | | No
| ------------- ------------- | |
| ^ | |
---------|------------------------------------------ |
| |
| |
Generate testcase < ----------------------------------

At the moment, only support for Bitcoin Core as target application is implemented but the existing abstractions allow for integration with other projects as well (e.g. btcd, libbitcoin).

The full node software under test is extended with a crash handler that reports application aborts to Nyx (See nyx-crash-handler.c) and the harness includes a nyx agent that deals with setup and snapshot creation (See nyx-agent.c).

Usage

Actual fuzzing (i.e. input generation) can currently only be done on bare metal x86-64 systems (limitiation of Nyx). See the Dockerfile for an example setup.

Example: fuzzing the http server of Bitcoin Core:

$ docker build -t fuzzamoto .
$ docker run --privileged -it fuzzamoto bash
root@...# mkdir /tmp/in && echo "AAA" > /tmp/in/A
root@...# afl-fuzz -X -i /tmp/in -o /tmp/out -- /tmp/fuzzamoto_scenario-http-server

Multi-core campaigns

Running a multi-core campaign can be done with AFL_Runner (installed in the Dockerfile).

Example: fuzzing the http server of Bitcoin Core with 16 cores:

root@...# aflr run --nyx-mode --target /tmp/fuzzamoto_scenario-http-server/ \
--input-dir /tmp/http_in/ --output-dir /tmp/http_out/ \
--runners 16

Reproducing testcases

Crashing inputs or other solutions can be reproduced on any architecture with something similar to the following:

$ # Rebuild fuzzamoto without nyx feature
$ cargo build --release --features inherit_stdout --workspace
$ cat ./testcase.dat | ./target/release/fuzzamoto_scenario-http-server ./bitcoind

--features inherit_stdout is used to inherit stdout from the target application, such that any logs, stack traces, etc. are printed to the terminal.

Custom target patches

Certain targets require custom patches for effective fuzzing and testcase reproduction. These can be found in the target-patches directory.

Maintaining external patches should be avoided if possible, as it has several downsides:

  • They might become outdated and require rebase
  • They might not apply to a PR we would like to fuzz, in which case the patch needs to be adjusted just for the PR
  • Testcases might not reproduce without the patches and it is on the user to make sure all patches were applied correctly

If a patch is necessary, then landing it in the target application is preferred but in the case of a fuzz blocker (e.g. checksum check in the target) the best solution is to make the harness/test produce valid inputs (if possible).

Current patches:

  • bitcoin-core-rng.patch: Attempts to make Bitcoin Core's RNG deterministic

Bugs found by Fuzzamoto

ProjectBugScenarioSecurity
Bitcoin Corebitcoin/bitcoin#32111wallet-migration
Bitcoin Corebitcoin/bitcoin#32112wallet-migration
Bitcoin Corebitcoin/bitcoin#32173rpc-generic

About

Holistic Fuzzing for Bitcoin Protocol Implementations

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Crypt-iQ/fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations · GitHub
Skip to content

Repository files navigation

Work in progress

Fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations

Fuzzamoto provides a framework for coverage-guided fuzzing of Bitcoin full node implementations in a holistic fashion. Instead of the common in-process LLVMFuzzerTestOneInput style tests, testing is performed through external facing interfaces, such as P2P, RPC, etc (Bitcoin Core contributors can think of it as "Functional Fuzz Tests").

Design

Snapshot fuzzing lies at the core of Fuzzamoto, to allow for deterministic and performant fuzzing of one or more full node instances at once. Currently, only support for snapshot fuzzing with afl++'s Nyx mode is implemented but future integration with other snapshot fuzzing tools is possible (e.g. full-system libafl_qemu).

The rough architecture when fuzzing with fuzzamoto looks as follows:

 Report bug
^
|
Yes
|
-------------------> Bug? -------------------
| |
---------|------------ Nyx VM ---------------------- |
| | | |
| ------------- ------------- | |
| | Fuzzamoto | <---p2p/rpc/...---> | Full Node | | No
| ------------- ------------- | |
| ^ | |
---------|------------------------------------------ |
| |
| |
Generate testcase < ----------------------------------

At the moment, only support for Bitcoin Core as target application is implemented but the existing abstractions allow for integration with other projects as well (e.g. btcd, libbitcoin).

The full node software under test is extended with a crash handler that reports application aborts to Nyx (See nyx-crash-handler.c) and the harness includes a nyx agent that deals with setup and snapshot creation (See nyx-agent.c).

Usage

Actual fuzzing (i.e. input generation) can currently only be done on bare metal x86-64 systems (limitiation of Nyx). See the Dockerfile for an example setup.

Example: fuzzing the http server of Bitcoin Core:

$ docker build -t fuzzamoto .
$ docker run --privileged -it fuzzamoto bash
root@...# mkdir /tmp/in && echo "AAA" > /tmp/in/A
root@...# afl-fuzz -X -i /tmp/in -o /tmp/out -- /tmp/fuzzamoto_scenario-http-server

Multi-core campaigns

Running a multi-core campaign can be done with AFL_Runner (installed in the Dockerfile).

Example: fuzzing the http server of Bitcoin Core with 16 cores:

root@...# aflr run --nyx-mode --target /tmp/fuzzamoto_scenario-http-server/ \
--input-dir /tmp/http_in/ --output-dir /tmp/http_out/ \
--runners 16

Reproducing testcases

Crashing inputs or other solutions can be reproduced on any architecture with something similar to the following:

$ # Rebuild fuzzamoto without nyx feature
$ cargo build --release --features inherit_stdout --workspace
$ cat ./testcase.dat | ./target/release/fuzzamoto_scenario-http-server ./bitcoind

--features inherit_stdout is used to inherit stdout from the target application, such that any logs, stack traces, etc. are printed to the terminal.

Custom target patches

Certain targets require custom patches for effective fuzzing and testcase reproduction. These can be found in the target-patches directory.

Maintaining external patches should be avoided if possible, as it has several downsides:

  • They might become outdated and require rebase
  • They might not apply to a PR we would like to fuzz, in which case the patch needs to be adjusted just for the PR
  • Testcases might not reproduce without the patches and it is on the user to make sure all patches were applied correctly

If a patch is necessary, then landing it in the target application is preferred but in the case of a fuzz blocker (e.g. checksum check in the target) the best solution is to make the harness/test produce valid inputs (if possible).

Current patches:

  • bitcoin-core-rng.patch: Attempts to make Bitcoin Core's RNG deterministic

Bugs found by Fuzzamoto

ProjectBugScenarioSecurity
Bitcoin Corebitcoin/bitcoin#32111wallet-migration
Bitcoin Corebitcoin/bitcoin#32112wallet-migration
Bitcoin Corebitcoin/bitcoin#32173rpc-generic

About

Holistic Fuzzing for Bitcoin Protocol Implementations

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Crypt-iQ/fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations · GitHub
Skip to content

Repository files navigation

Work in progress

Fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations

Fuzzamoto provides a framework for coverage-guided fuzzing of Bitcoin full node implementations in a holistic fashion. Instead of the common in-process LLVMFuzzerTestOneInput style tests, testing is performed through external facing interfaces, such as P2P, RPC, etc (Bitcoin Core contributors can think of it as "Functional Fuzz Tests").

Design

Snapshot fuzzing lies at the core of Fuzzamoto, to allow for deterministic and performant fuzzing of one or more full node instances at once. Currently, only support for snapshot fuzzing with afl++'s Nyx mode is implemented but future integration with other snapshot fuzzing tools is possible (e.g. full-system libafl_qemu).

The rough architecture when fuzzing with fuzzamoto looks as follows:

 Report bug
^
|
Yes
|
-------------------> Bug? -------------------
| |
---------|------------ Nyx VM ---------------------- |
| | | |
| ------------- ------------- | |
| | Fuzzamoto | <---p2p/rpc/...---> | Full Node | | No
| ------------- ------------- | |
| ^ | |
---------|------------------------------------------ |
| |
| |
Generate testcase < ----------------------------------

At the moment, only support for Bitcoin Core as target application is implemented but the existing abstractions allow for integration with other projects as well (e.g. btcd, libbitcoin).

The full node software under test is extended with a crash handler that reports application aborts to Nyx (See nyx-crash-handler.c) and the harness includes a nyx agent that deals with setup and snapshot creation (See nyx-agent.c).

Usage

Actual fuzzing (i.e. input generation) can currently only be done on bare metal x86-64 systems (limitiation of Nyx). See the Dockerfile for an example setup.

Example: fuzzing the http server of Bitcoin Core:

$ docker build -t fuzzamoto .
$ docker run --privileged -it fuzzamoto bash
root@...# mkdir /tmp/in && echo "AAA" > /tmp/in/A
root@...# afl-fuzz -X -i /tmp/in -o /tmp/out -- /tmp/fuzzamoto_scenario-http-server

Multi-core campaigns

Running a multi-core campaign can be done with AFL_Runner (installed in the Dockerfile).

Example: fuzzing the http server of Bitcoin Core with 16 cores:

root@...# aflr run --nyx-mode --target /tmp/fuzzamoto_scenario-http-server/ \
--input-dir /tmp/http_in/ --output-dir /tmp/http_out/ \
--runners 16

Reproducing testcases

Crashing inputs or other solutions can be reproduced on any architecture with something similar to the following:

$ # Rebuild fuzzamoto without nyx feature
$ cargo build --release --features inherit_stdout --workspace
$ cat ./testcase.dat | ./target/release/fuzzamoto_scenario-http-server ./bitcoind

--features inherit_stdout is used to inherit stdout from the target application, such that any logs, stack traces, etc. are printed to the terminal.

Custom target patches

Certain targets require custom patches for effective fuzzing and testcase reproduction. These can be found in the target-patches directory.

Maintaining external patches should be avoided if possible, as it has several downsides:

  • They might become outdated and require rebase
  • They might not apply to a PR we would like to fuzz, in which case the patch needs to be adjusted just for the PR
  • Testcases might not reproduce without the patches and it is on the user to make sure all patches were applied correctly

If a patch is necessary, then landing it in the target application is preferred but in the case of a fuzz blocker (e.g. checksum check in the target) the best solution is to make the harness/test produce valid inputs (if possible).

Current patches:

  • bitcoin-core-rng.patch: Attempts to make Bitcoin Core's RNG deterministic

Bugs found by Fuzzamoto

ProjectBugScenarioSecurity
Bitcoin Corebitcoin/bitcoin#32111wallet-migration
Bitcoin Corebitcoin/bitcoin#32112wallet-migration
Bitcoin Corebitcoin/bitcoin#32173rpc-generic

About

Holistic Fuzzing for Bitcoin Protocol Implementations

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - Crypt-iQ/fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations · GitHub
Skip to content

Repository files navigation

Work in progress

Fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations

Fuzzamoto provides a framework for coverage-guided fuzzing of Bitcoin full node implementations in a holistic fashion. Instead of the common in-process LLVMFuzzerTestOneInput style tests, testing is performed through external facing interfaces, such as P2P, RPC, etc (Bitcoin Core contributors can think of it as "Functional Fuzz Tests").

Design

Snapshot fuzzing lies at the core of Fuzzamoto, to allow for deterministic and performant fuzzing of one or more full node instances at once. Currently, only support for snapshot fuzzing with afl++'s Nyx mode is implemented but future integration with other snapshot fuzzing tools is possible (e.g. full-system libafl_qemu).

The rough architecture when fuzzing with fuzzamoto looks as follows:

 Report bug
^
|
Yes
|
-------------------> Bug? -------------------
| |
---------|------------ Nyx VM ---------------------- |
| | | |
| ------------- ------------- | |
| | Fuzzamoto | <---p2p/rpc/...---> | Full Node | | No
| ------------- ------------- | |
| ^ | |
---------|------------------------------------------ |
| |
| |
Generate testcase < ----------------------------------

At the moment, only support for Bitcoin Core as target application is implemented but the existing abstractions allow for integration with other projects as well (e.g. btcd, libbitcoin).

The full node software under test is extended with a crash handler that reports application aborts to Nyx (See nyx-crash-handler.c) and the harness includes a nyx agent that deals with setup and snapshot creation (See nyx-agent.c).

Usage

Actual fuzzing (i.e. input generation) can currently only be done on bare metal x86-64 systems (limitiation of Nyx). See the Dockerfile for an example setup.

Example: fuzzing the http server of Bitcoin Core:

$ docker build -t fuzzamoto .
$ docker run --privileged -it fuzzamoto bash
root@...# mkdir /tmp/in && echo "AAA" > /tmp/in/A
root@...# afl-fuzz -X -i /tmp/in -o /tmp/out -- /tmp/fuzzamoto_scenario-http-server

Multi-core campaigns

Running a multi-core campaign can be done with AFL_Runner (installed in the Dockerfile).

Example: fuzzing the http server of Bitcoin Core with 16 cores:

root@...# aflr run --nyx-mode --target /tmp/fuzzamoto_scenario-http-server/ \
--input-dir /tmp/http_in/ --output-dir /tmp/http_out/ \
--runners 16

Reproducing testcases

Crashing inputs or other solutions can be reproduced on any architecture with something similar to the following:

$ # Rebuild fuzzamoto without nyx feature
$ cargo build --release --features inherit_stdout --workspace
$ cat ./testcase.dat | ./target/release/fuzzamoto_scenario-http-server ./bitcoind

--features inherit_stdout is used to inherit stdout from the target application, such that any logs, stack traces, etc. are printed to the terminal.

Custom target patches

Certain targets require custom patches for effective fuzzing and testcase reproduction. These can be found in the target-patches directory.

Maintaining external patches should be avoided if possible, as it has several downsides:

  • They might become outdated and require rebase
  • They might not apply to a PR we would like to fuzz, in which case the patch needs to be adjusted just for the PR
  • Testcases might not reproduce without the patches and it is on the user to make sure all patches were applied correctly

If a patch is necessary, then landing it in the target application is preferred but in the case of a fuzz blocker (e.g. checksum check in the target) the best solution is to make the harness/test produce valid inputs (if possible).

Current patches:

  • bitcoin-core-rng.patch: Attempts to make Bitcoin Core's RNG deterministic

Bugs found by Fuzzamoto

ProjectBugScenarioSecurity
Bitcoin Corebitcoin/bitcoin#32111wallet-migration
Bitcoin Corebitcoin/bitcoin#32112wallet-migration
Bitcoin Corebitcoin/bitcoin#32173rpc-generic

About

Holistic Fuzzing for Bitcoin Protocol Implementations

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Crypt-iQ/fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations · GitHub
Skip to content

Repository files navigation

Work in progress

Fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations

Fuzzamoto provides a framework for coverage-guided fuzzing of Bitcoin full node implementations in a holistic fashion. Instead of the common in-process LLVMFuzzerTestOneInput style tests, testing is performed through external facing interfaces, such as P2P, RPC, etc (Bitcoin Core contributors can think of it as "Functional Fuzz Tests").

Design

Snapshot fuzzing lies at the core of Fuzzamoto, to allow for deterministic and performant fuzzing of one or more full node instances at once. Currently, only support for snapshot fuzzing with afl++'s Nyx mode is implemented but future integration with other snapshot fuzzing tools is possible (e.g. full-system libafl_qemu).

The rough architecture when fuzzing with fuzzamoto looks as follows:

 Report bug
^
|
Yes
|
-------------------> Bug? -------------------
| |
---------|------------ Nyx VM ---------------------- |
| | | |
| ------------- ------------- | |
| | Fuzzamoto | <---p2p/rpc/...---> | Full Node | | No
| ------------- ------------- | |
| ^ | |
---------|------------------------------------------ |
| |
| |
Generate testcase < ----------------------------------

At the moment, only support for Bitcoin Core as target application is implemented but the existing abstractions allow for integration with other projects as well (e.g. btcd, libbitcoin).

The full node software under test is extended with a crash handler that reports application aborts to Nyx (See nyx-crash-handler.c) and the harness includes a nyx agent that deals with setup and snapshot creation (See nyx-agent.c).

Usage

Actual fuzzing (i.e. input generation) can currently only be done on bare metal x86-64 systems (limitiation of Nyx). See the Dockerfile for an example setup.

Example: fuzzing the http server of Bitcoin Core:

$ docker build -t fuzzamoto .
$ docker run --privileged -it fuzzamoto bash
root@...# mkdir /tmp/in && echo "AAA" > /tmp/in/A
root@...# afl-fuzz -X -i /tmp/in -o /tmp/out -- /tmp/fuzzamoto_scenario-http-server

Multi-core campaigns

Running a multi-core campaign can be done with AFL_Runner (installed in the Dockerfile).

Example: fuzzing the http server of Bitcoin Core with 16 cores:

root@...# aflr run --nyx-mode --target /tmp/fuzzamoto_scenario-http-server/ \
--input-dir /tmp/http_in/ --output-dir /tmp/http_out/ \
--runners 16

Reproducing testcases

Crashing inputs or other solutions can be reproduced on any architecture with something similar to the following:

$ # Rebuild fuzzamoto without nyx feature
$ cargo build --release --features inherit_stdout --workspace
$ cat ./testcase.dat | ./target/release/fuzzamoto_scenario-http-server ./bitcoind

--features inherit_stdout is used to inherit stdout from the target application, such that any logs, stack traces, etc. are printed to the terminal.

Custom target patches

Certain targets require custom patches for effective fuzzing and testcase reproduction. These can be found in the target-patches directory.

Maintaining external patches should be avoided if possible, as it has several downsides:

  • They might become outdated and require rebase
  • They might not apply to a PR we would like to fuzz, in which case the patch needs to be adjusted just for the PR
  • Testcases might not reproduce without the patches and it is on the user to make sure all patches were applied correctly

If a patch is necessary, then landing it in the target application is preferred but in the case of a fuzz blocker (e.g. checksum check in the target) the best solution is to make the harness/test produce valid inputs (if possible).

Current patches:

  • bitcoin-core-rng.patch: Attempts to make Bitcoin Core's RNG deterministic

Bugs found by Fuzzamoto

ProjectBugScenarioSecurity
Bitcoin Corebitcoin/bitcoin#32111wallet-migration
Bitcoin Corebitcoin/bitcoin#32112wallet-migration
Bitcoin Corebitcoin/bitcoin#32173rpc-generic

About

Holistic Fuzzing for Bitcoin Protocol Implementations

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Crypt-iQ/fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations · GitHub
Skip to content

Repository files navigation

Work in progress

Fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations

Fuzzamoto provides a framework for coverage-guided fuzzing of Bitcoin full node implementations in a holistic fashion. Instead of the common in-process LLVMFuzzerTestOneInput style tests, testing is performed through external facing interfaces, such as P2P, RPC, etc (Bitcoin Core contributors can think of it as "Functional Fuzz Tests").

Design

Snapshot fuzzing lies at the core of Fuzzamoto, to allow for deterministic and performant fuzzing of one or more full node instances at once. Currently, only support for snapshot fuzzing with afl++'s Nyx mode is implemented but future integration with other snapshot fuzzing tools is possible (e.g. full-system libafl_qemu).

The rough architecture when fuzzing with fuzzamoto looks as follows:

 Report bug
^
|
Yes
|
-------------------> Bug? -------------------
| |
---------|------------ Nyx VM ---------------------- |
| | | |
| ------------- ------------- | |
| | Fuzzamoto | <---p2p/rpc/...---> | Full Node | | No
| ------------- ------------- | |
| ^ | |
---------|------------------------------------------ |
| |
| |
Generate testcase < ----------------------------------

At the moment, only support for Bitcoin Core as target application is implemented but the existing abstractions allow for integration with other projects as well (e.g. btcd, libbitcoin).

The full node software under test is extended with a crash handler that reports application aborts to Nyx (See nyx-crash-handler.c) and the harness includes a nyx agent that deals with setup and snapshot creation (See nyx-agent.c).

Usage

Actual fuzzing (i.e. input generation) can currently only be done on bare metal x86-64 systems (limitiation of Nyx). See the Dockerfile for an example setup.

Example: fuzzing the http server of Bitcoin Core:

$ docker build -t fuzzamoto .
$ docker run --privileged -it fuzzamoto bash
root@...# mkdir /tmp/in && echo "AAA" > /tmp/in/A
root@...# afl-fuzz -X -i /tmp/in -o /tmp/out -- /tmp/fuzzamoto_scenario-http-server

Multi-core campaigns

Running a multi-core campaign can be done with AFL_Runner (installed in the Dockerfile).

Example: fuzzing the http server of Bitcoin Core with 16 cores:

root@...# aflr run --nyx-mode --target /tmp/fuzzamoto_scenario-http-server/ \
--input-dir /tmp/http_in/ --output-dir /tmp/http_out/ \
--runners 16

Reproducing testcases

Crashing inputs or other solutions can be reproduced on any architecture with something similar to the following:

$ # Rebuild fuzzamoto without nyx feature
$ cargo build --release --features inherit_stdout --workspace
$ cat ./testcase.dat | ./target/release/fuzzamoto_scenario-http-server ./bitcoind

--features inherit_stdout is used to inherit stdout from the target application, such that any logs, stack traces, etc. are printed to the terminal.

Custom target patches

Certain targets require custom patches for effective fuzzing and testcase reproduction. These can be found in the target-patches directory.

Maintaining external patches should be avoided if possible, as it has several downsides:

  • They might become outdated and require rebase
  • They might not apply to a PR we would like to fuzz, in which case the patch needs to be adjusted just for the PR
  • Testcases might not reproduce without the patches and it is on the user to make sure all patches were applied correctly

If a patch is necessary, then landing it in the target application is preferred but in the case of a fuzz blocker (e.g. checksum check in the target) the best solution is to make the harness/test produce valid inputs (if possible).

Current patches:

  • bitcoin-core-rng.patch: Attempts to make Bitcoin Core's RNG deterministic

Bugs found by Fuzzamoto

ProjectBugScenarioSecurity
Bitcoin Corebitcoin/bitcoin#32111wallet-migration
Bitcoin Corebitcoin/bitcoin#32112wallet-migration
Bitcoin Corebitcoin/bitcoin#32173rpc-generic

About

Holistic Fuzzing for Bitcoin Protocol Implementations

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - Crypt-iQ/fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations · GitHub
Skip to content

Repository files navigation

Work in progress

Fuzzamoto: Holistic Fuzzing for Bitcoin Protocol Implementations

Fuzzamoto provides a framework for coverage-guided fuzzing of Bitcoin full node implementations in a holistic fashion. Instead of the common in-process LLVMFuzzerTestOneInput style tests, testing is performed through external facing interfaces, such as P2P, RPC, etc (Bitcoin Core contributors can think of it as "Functional Fuzz Tests").

Design

Snapshot fuzzing lies at the core of Fuzzamoto, to allow for deterministic and performant fuzzing of one or more full node instances at once. Currently, only support for snapshot fuzzing with afl++'s Nyx mode is implemented but future integration with other snapshot fuzzing tools is possible (e.g. full-system libafl_qemu).

The rough architecture when fuzzing with fuzzamoto looks as follows:

 Report bug
^
|
Yes
|
-------------------> Bug? -------------------
| |
---------|------------ Nyx VM ---------------------- |
| | | |
| ------------- ------------- | |
| | Fuzzamoto | <---p2p/rpc/...---> | Full Node | | No
| ------------- ------------- | |
| ^ | |
---------|------------------------------------------ |
| |
| |
Generate testcase < ----------------------------------

At the moment, only support for Bitcoin Core as target application is implemented but the existing abstractions allow for integration with other projects as well (e.g. btcd, libbitcoin).

The full node software under test is extended with a crash handler that reports application aborts to Nyx (See nyx-crash-handler.c) and the harness includes a nyx agent that deals with setup and snapshot creation (See nyx-agent.c).

Usage

Actual fuzzing (i.e. input generation) can currently only be done on bare metal x86-64 systems (limitiation of Nyx). See the Dockerfile for an example setup.

Example: fuzzing the http server of Bitcoin Core:

$ docker build -t fuzzamoto .
$ docker run --privileged -it fuzzamoto bash
root@...# mkdir /tmp/in && echo "AAA" > /tmp/in/A
root@...# afl-fuzz -X -i /tmp/in -o /tmp/out -- /tmp/fuzzamoto_scenario-http-server

Multi-core campaigns

Running a multi-core campaign can be done with AFL_Runner (installed in the Dockerfile).

Example: fuzzing the http server of Bitcoin Core with 16 cores:

root@...# aflr run --nyx-mode --target /tmp/fuzzamoto_scenario-http-server/ \
--input-dir /tmp/http_in/ --output-dir /tmp/http_out/ \
--runners 16

Reproducing testcases

Crashing inputs or other solutions can be reproduced on any architecture with something similar to the following:

$ # Rebuild fuzzamoto without nyx feature
$ cargo build --release --features inherit_stdout --workspace
$ cat ./testcase.dat | ./target/release/fuzzamoto_scenario-http-server ./bitcoind

--features inherit_stdout is used to inherit stdout from the target application, such that any logs, stack traces, etc. are printed to the terminal.

Custom target patches

Certain targets require custom patches for effective fuzzing and testcase reproduction. These can be found in the target-patches directory.

Maintaining external patches should be avoided if possible, as it has several downsides:

  • They might become outdated and require rebase
  • They might not apply to a PR we would like to fuzz, in which case the patch needs to be adjusted just for the PR
  • Testcases might not reproduce without the patches and it is on the user to make sure all patches were applied correctly

If a patch is necessary, then landing it in the target application is preferred but in the case of a fuzz blocker (e.g. checksum check in the target) the best solution is to make the harness/test produce valid inputs (if possible).

Current patches:

  • bitcoin-core-rng.patch: Attempts to make Bitcoin Core's RNG deterministic

Bugs found by Fuzzamoto

ProjectBugScenarioSecurity
Bitcoin Corebitcoin/bitcoin#32111wallet-migration
Bitcoin Corebitcoin/bitcoin#32112wallet-migration
Bitcoin Corebitcoin/bitcoin#32173rpc-generic

About

Holistic Fuzzing for Bitcoin Protocol Implementations

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages