diff --git a/doc/fuzzing.md b/doc/fuzzing.md index c97b8d4d50..4391fb78a2 100644 --- a/doc/fuzzing.md +++ b/doc/fuzzing.md @@ -157,3 +157,77 @@ $ honggfuzz/honggfuzz -i inputs/ -- src/test/fuzz/process_message ``` Read the [Honggfuzz documentation](https://github.com/google/honggfuzz/blob/master/docs/USAGE.md) for more information. + +## Fuzzing the Bitcoin Core P2P layer using Honggfuzz NetDriver + +Honggfuzz NetDriver allows for very easy fuzzing of TCP servers such as Bitcoin +Core without having to write any custom fuzzing harness. The `bitcoind` server +process is largely fuzzed without modification. + +This makes the fuzzing highly realistic: a bug reachable by the fuzzer is likely +also remotely triggerable by an untrusted peer. + +To quickly get started fuzzing the P2P layer using Honggfuzz NetDriver: + +```sh +$ mkdir bitcoin-honggfuzz-p2p/ +$ cd bitcoin-honggfuzz-p2p/ +$ git clone https://github.com/bitcoin/bitcoin +$ cd bitcoin/ +$ ./autogen.sh +$ git clone https://github.com/google/honggfuzz +$ cd honggfuzz/ +$ make +$ cd .. +$ CC=$(pwd)/honggfuzz/hfuzz_cc/hfuzz-clang \ + CXX=$(pwd)/honggfuzz/hfuzz_cc/hfuzz-clang++ \ + ./configure --disable-wallet --with-gui=no \ + --with-sanitizers=address,undefined +$ git apply << "EOF" +diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp +index 455a82e39..2faa3f80f 100644 +--- a/src/bitcoind.cpp ++++ b/src/bitcoind.cpp +@@ -158,7 +158,11 @@ static bool AppInit(int argc, char* argv[]) + return fRet; + } + ++#ifdef HFND_FUZZING_ENTRY_FUNCTION_CXX ++HFND_FUZZING_ENTRY_FUNCTION_CXX(int argc, char* argv[]) ++#else + int main(int argc, char* argv[]) ++#endif + { + #ifdef WIN32 + util::WinCmdLineArgs winArgs; +diff --git a/src/net.cpp b/src/net.cpp +index cf987b699..636a4176a 100644 +--- a/src/net.cpp ++++ b/src/net.cpp +@@ -709,7 +709,7 @@ int V1TransportDeserializer::readHeader(const char *pch, unsigned int nBytes) + } + + // Check start string, network magic +- if (memcmp(hdr.pchMessageStart, m_chain_params.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { ++ if (false && memcmp(hdr.pchMessageStart, m_chain_params.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { // skip network magic checking + LogPrint(BCLog::NET, "HEADER ERROR - MESSAGESTART (%s, %u bytes), received %s, peer=%d\n", hdr.GetCommand(), hdr.nMessageSize, HexStr(hdr.pchMessageStart), m_node_id); + return -1; + } +@@ -768,7 +768,7 @@ Optional V1TransportDeserializer::GetMessage(const std::chrono::mic + RandAddEvent(ReadLE32(hash.begin())); + + // Check checksum and header command string +- if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) { ++ if (false && memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) { // skip checksum checking + LogPrint(BCLog::NET, "CHECKSUM ERROR (%s, %u bytes), expected %s was %s, peer=%d\n", + SanitizeString(msg->m_command), msg->m_message_size, + HexStr(Span(hash.begin(), hash.begin() + CMessageHeader::CHECKSUM_SIZE)), +EOF +$ make -C src/ bitcoind +$ mkdir -p inputs/ +$ honggfuzz/honggfuzz --exit_upon_crash --quiet --timeout 4 -n 1 -Q \ + -E HFND_TCP_PORT=18444 -f inputs/ -- \ + src/bitcoind -regtest -discover=0 -dns=0 -dnsseed=0 -listenonion=0 \ + -nodebuglogfile -bind=127.0.0.1:18444 -logthreadnames \ + -debug +```