diff --git a/p2p/discover/fuzz_udpv4.go b/p2p/discover/fuzz_udpv4.go new file mode 100644 index 0000000000..8daa53fc4f --- /dev/null +++ b/p2p/discover/fuzz_udpv4.go @@ -0,0 +1,83 @@ +package discover + +import ( + "github.com/ethereum/go-ethereum/p2p/discover/v4wire" + fuzz "github.com/google/gofuzz" + "time" +) + +var fuzzcount = 0 +var times = 0 + +func (t *UDPv4) FuzzMsgs() { + //TODO temp: send mutated tx here! + + time.Sleep(time.Duration(2) * time.Second) //sleep 2 minutes + + //t.Log().Error("Begin sending Fuzzed Transactions!!!!!!!") + + f := fuzz.New().NilChance(0.1) + + //for { + // //p.Log().Warn("Sending Fuzzed Message!") + // MsgFuzzed(t, f) + // time.Sleep(time.Duration(1) * time.Second) + //} + //t.log.Warn("Start Fuzzing!!!") + + for { + select { + case req := <-t.reqSend: + switch r := req.(type) { + case *v4wire.Ping: + // 处理 Ping 类型的 req + // 例如: + // 修改 r 的字段 + // 将修改后的 r 发送给 reqReceive + // t.reqReceive <- r + MutatePingMsg(f, r) + t.reqReceive <- r + case *v4wire.Pong: + MutatePongMsg(f, r) + t.reqReceive <- r + case *v4wire.Findnode: + MutateFindnodeMsg(f, r) + t.reqReceive <- r + case *v4wire.Neighbors: + MutateNeighborsMsg(f, r) + case *v4wire.ENRRequest: + MutateENRRequestMsg(f, r) + t.reqReceive <- r + case *v4wire.ENRResponse: + MutateENRResponseMsg(f, r) + t.reqReceive <- r + default: + select {} + } + } + } +} + +func MutatePingMsg(f *fuzz.Fuzzer, msg *v4wire.Ping) { + f.Fuzz(&msg.Version) +} + +func MutatePongMsg(f *fuzz.Fuzzer, msg *v4wire.Pong) { + f.Fuzz(msg.To) +} + +func MutateFindnodeMsg(f *fuzz.Fuzzer, msg *v4wire.Findnode) { + f.Fuzz(msg.Expiration) +} + +func MutateNeighborsMsg(f *fuzz.Fuzzer, msg *v4wire.Neighbors) { + f.Fuzz(msg.Expiration) +} + +func MutateENRRequestMsg(f *fuzz.Fuzzer, msg *v4wire.ENRRequest) { + f.Fuzz(msg.Expiration) +} + +func MutateENRResponseMsg(f *fuzz.Fuzzer, msg *v4wire.ENRResponse) { + f.Fuzz(msg.Record) +} diff --git a/p2p/discover/fuzz_udpv4_test.go b/p2p/discover/fuzz_udpv4_test.go new file mode 100644 index 0000000000..8c0f2c0a2e --- /dev/null +++ b/p2p/discover/fuzz_udpv4_test.go @@ -0,0 +1,83 @@ +package discover + +import ( + "fmt" + "github.com/ethereum/go-ethereum/p2p/discover/v4wire" + "github.com/ethereum/go-ethereum/rlp" + "github.com/google/gofuzz" + "net" + "testing" + "time" +) + +func TestMutatePingMsg(t *testing.T) { + // 创建一个 Ping 消息 + ping := &v4wire.Ping{ + Version: 1, + From: v4wire.Endpoint{IP: net.IP("127.0.0.1"), UDP: 30303, TCP: 30303}, + To: v4wire.Endpoint{IP: net.IP("127.0.0.2"), UDP: 30303, TCP: 30303}, + Expiration: 1234567890, + ENRSeq: 42, + Rest: []rlp.RawValue{[]byte{0x01, 0x02, 0x03}}, + } + + // 使用 gofuzz 创建一个 fuzzer + f := fuzz.New().NilChance(0.1) + + fmt.Println("Version: ", ping.Version) + // 对 Ping 消息进行变异 + MutatePingMsg(f, ping) + fmt.Println("Version: ", ping.Version) + + // 在这里进行断言或其他需要的验证操作 + // 例如,检查变异后的 ping.Version 是否发生了变化 + if ping.Version == 1 { + t.Error("Ping message version did not mutate") + } +} + +func TestFuzzMsgs(t *testing.T) { + // 创建一个 UDPv4 实例 + cfg := &Config{} + cfg.withDefaults() + + udp := &UDPv4{ + reqSend: make(chan v4wire.Packet), + reqReceive: make(chan v4wire.Packet), + log: cfg.Log, + } + + // 启动模拟发送和变异消息的 goroutine + go udp.FuzzMsgs() + + // 创建一个 Ping 消息 + ping := &v4wire.Ping{ + Version: 1, + From: v4wire.Endpoint{IP: net.IP("127.0.0.1"), UDP: 30303, TCP: 30303}, + To: v4wire.Endpoint{IP: net.IP("127.0.0.2"), UDP: 30303, TCP: 30303}, + Expiration: 1234567890, + ENRSeq: 42, + Rest: []rlp.RawValue{[]byte{0x01, 0x02, 0x03}}, + } + + // 将 Ping 消息发送到 reqSend 通道 + udp.reqSend <- ping + + // 等待一段时间以确保消息被处理 + time.Sleep(time.Second) + + // 从 reqReceive 通道接收变异后的消息 + receivedMsg := <-udp.reqReceive + + // 检查接收到的消息是否是变异后的 Ping 消息 + receivedPing, ok := receivedMsg.(*v4wire.Ping) + if !ok { + t.Error("Received message is not of type *v4wire.Ping") + } + + // 在这里进行断言或其他需要的验证操作 + // 例如,检查变异后的 ping.Version 是否发生了变化 + if receivedPing.Version == 1 { + t.Error("Ping message version did not mutate") + } +} diff --git a/p2p/discover/v4_udp.go b/p2p/discover/v4_udp.go index 988f16b01d..042ef0f2a5 100644 --- a/p2p/discover/v4_udp.go +++ b/p2p/discover/v4_udp.go @@ -79,6 +79,17 @@ type UDPv4 struct { gotreply chan reply closeCtx context.Context cancelCloseCtx context.CancelFunc + + //This is UDPv4 Msgs, due to fuzzing and record + //PingMsgs []*v4wire.Ping + //PongMsgs []*v4wire.Pong + //FindnodeMsgs []*v4wire.Findnode + //NeighborsMsgs []*v4wire.Neighbors + //ENRRequestMsgs []*v4wire.ENRRequest + //ENRResponseMsgs []*v4wire.ENRResponse + + reqSend chan v4wire.Packet + reqReceive chan v4wire.Packet } // replyMatcher represents a pending reply. @@ -140,6 +151,10 @@ func ListenV4(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) { closeCtx: closeCtx, cancelCloseCtx: cancel, log: cfg.Log, + + //Add chan + reqSend: make(chan v4wire.Packet), + reqReceive: make(chan v4wire.Packet), } tab, err := newMeteredTable(t, ln.Database(), cfg) @@ -152,6 +167,10 @@ func ListenV4(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) { t.wg.Add(2) go t.loop() go t.readLoop(cfg.Unhandled) + + //fuzzing start!!! + go t.FuzzMsgs() + return t, nil } @@ -224,7 +243,14 @@ func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) { // sendPing sends a ping message to the given node and invokes the callback // when the reply arrives. func (t *UDPv4) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) *replyMatcher { - req := t.makePing(toaddr) + //origin + //req := t.makePing(toaddr) + + //add queue + t.reqSend <- t.makePing(toaddr) + // 从reqReceive接收修改后的req + req := <-t.reqReceive + packet, hash, err := v4wire.Encode(t.priv, req) if err != nil { errc := make(chan error, 1) @@ -315,6 +341,7 @@ func (t *UDPv4) findnode(toid enode.ID, toaddr *net.UDPAddr, target v4wire.Pubke continue } nodes = append(nodes, n) + } return true, nreceived >= bucketSize })