1
1
mirror of https://github.com/wader/fq.git synced 2024-11-26 10:33:53 +03:00

pcap: fuzz: Skip ssl2 packet if too short

Should report error somehow?
This commit is contained in:
Mattias Wadman 2021-12-06 17:56:48 +01:00
parent 38509683a7
commit b525d0b3c8
4 changed files with 63 additions and 45 deletions

View File

@ -18,23 +18,24 @@ type IPEndpoint struct {
type TCPConnection struct {
ClientEndpoint IPEndpoint
ServerEnpoint IPEndpoint
ClientStream *bytes.Buffer
ServerStream *bytes.Buffer
ServerEndpoint IPEndpoint
ClientToServer *bytes.Buffer
ServerToClient *bytes.Buffer
tcpstate *reassembly.TCPSimpleFSM
optchecker reassembly.TCPOptionCheck
net, transport gopacket.Flow
tcpState *reassembly.TCPSimpleFSM
optChecker reassembly.TCPOptionCheck
net gopacket.Flow
transport gopacket.Flow
}
func (t *TCPConnection) Accept(tcp *layers.TCP, ci gopacket.CaptureInfo, dir reassembly.TCPFlowDirection, nextSeq reassembly.Sequence, start *bool, ac reassembly.AssemblerContext) bool {
// has ok state?
if !t.tcpstate.CheckState(tcp, dir) {
if !t.tcpState.CheckState(tcp, dir) {
// TODO: handle err?
return false
}
// has ok options?
if err := t.optchecker.Accept(tcp, ci, dir, nextSeq, start); err != nil {
if err := t.optChecker.Accept(tcp, ci, dir, nextSeq, start); err != nil {
// TODO: handle err?
return false
}
@ -52,9 +53,9 @@ func (t *TCPConnection) ReassembledSG(sg reassembly.ScatterGather, ac reassembly
switch dir {
case reassembly.TCPDirClientToServer:
t.ClientStream.Write(data)
t.ClientToServer.Write(data)
case reassembly.TCPDirServerToClient:
t.ServerStream.Write(data)
t.ServerToClient.Write(data)
}
}
@ -79,17 +80,17 @@ func (fd *Decoder) New(net, transport gopacket.Flow, tcp *layers.TCP, ac reassem
IP: append([]byte(nil), net.Src().Raw()...),
Port: int(binary.BigEndian.Uint16(transport.Src().Raw())),
},
ServerEnpoint: IPEndpoint{
ServerEndpoint: IPEndpoint{
IP: append([]byte(nil), net.Dst().Raw()...),
Port: int(binary.BigEndian.Uint16(transport.Dst().Raw())),
},
ClientStream: &bytes.Buffer{},
ServerStream: &bytes.Buffer{},
ClientToServer: &bytes.Buffer{},
ServerToClient: &bytes.Buffer{},
net: net,
transport: transport,
tcpstate: reassembly.NewTCPSimpleFSM(fsmOptions),
optchecker: reassembly.NewTCPOptionCheck(),
tcpState: reassembly.NewTCPSimpleFSM(fsmOptions),
optChecker: reassembly.NewTCPOptionCheck(),
}
fd.TCPConnections = append(fd.TCPConnections, stream)
@ -98,8 +99,8 @@ func (fd *Decoder) New(net, transport gopacket.Flow, tcp *layers.TCP, ac reassem
}
type Decoder struct {
TCPConnections []*TCPConnection
IPV4Reassbled []IPV4Reassembled
TCPConnections []*TCPConnection
IPV4Reassembled []IPV4Reassembled
ipv4Defrag *ip4defrag.IPv4Defragmenter
tcpAssembler *reassembly.Assembler
@ -115,36 +116,38 @@ func New() *Decoder {
return flowDecoder
}
func (fd *Decoder) SLLPacket(bs []byte) {
fd.packet(gopacket.NewPacket(bs, layers.LayerTypeLinuxSLL, gopacket.Lazy))
func (fd *Decoder) SLLPacket(bs []byte) error {
return fd.packet(gopacket.NewPacket(bs, layers.LayerTypeLinuxSLL, gopacket.Lazy))
}
func (fd *Decoder) EthernetFrame(bs []byte) {
fd.packet(gopacket.NewPacket(bs, layers.LayerTypeEthernet, gopacket.Lazy))
func (fd *Decoder) EthernetFrame(bs []byte) error {
return fd.packet(gopacket.NewPacket(bs, layers.LayerTypeEthernet, gopacket.Lazy))
}
func (fd *Decoder) packet(p gopacket.Packet) {
func (fd *Decoder) packet(p gopacket.Packet) error {
// TODO: linkType
ip4Layer := p.Layer(layers.LayerTypeIPv4)
if ip4Layer != nil {
ip4, _ := ip4Layer.(*layers.IPv4)
l := ip4.Length
newip4, err := fd.ipv4Defrag.DefragIPv4(ip4)
newIPv4, err := fd.ipv4Defrag.DefragIPv4(ip4)
if err != nil {
panic(err)
} else if newip4 != nil {
return err
} else if newIPv4 != nil {
// TODO: correct way to detect finished reassemble?
if newip4.Length != l {
if newIPv4.Length != l {
// TODO: better way to reconstruct package?
sb := gopacket.NewSerializeBuffer()
b, _ := sb.PrependBytes(len(newip4.Payload))
copy(b, newip4.Payload)
_ = newip4.SerializeTo(sb, gopacket.SerializeOptions{
b, _ := sb.PrependBytes(len(newIPv4.Payload))
copy(b, newIPv4.Payload)
if err := newIPv4.SerializeTo(sb, gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
})
}); err != nil {
return err
}
fd.IPV4Reassbled = append(fd.IPV4Reassbled, IPV4Reassembled{
fd.IPV4Reassembled = append(fd.IPV4Reassembled, IPV4Reassembled{
SourceIP: ip4.SrcIP,
DestinationIP: ip4.DstIP,
Datagram: sb.Bytes(),
@ -154,8 +157,10 @@ func (fd *Decoder) packet(p gopacket.Packet) {
if !ok {
panic("not a PacketBuilder")
}
nextDecoder := newip4.NextLayerType()
_ = nextDecoder.Decode(newip4.Payload, pb)
nextDecoder := newIPv4.NextLayerType()
if err := nextDecoder.Decode(newIPv4.Payload, pb); err != nil {
return err
}
}
}
}
@ -165,6 +170,8 @@ func (fd *Decoder) packet(p gopacket.Packet) {
tcp, _ := tcp.(*layers.TCP)
fd.tcpAssembler.Assemble(p.NetworkLayer().NetworkFlow(), tcp)
}
return nil
}
func (fd *Decoder) Flush() {

View File

@ -77,7 +77,8 @@ func decodePcap(d *decode.D, in interface{}) interface{} {
}
if fn, ok := linkToDecodeFn[linkType]; ok {
fn(fd, bs)
// TODO: report decode errors
_ = fn(fd, bs)
}
if g, ok := linkToFormat[linkType]; ok {

View File

@ -240,7 +240,9 @@ var blockFns = map[uint64]func(d *decode.D, dc *decodeContext){
linkType := dc.interfaceTypes[int(interfaceID)]
if fn, ok := linkToDecodeFn[linkType]; ok {
fn(dc.flowDecoder, bs)
// TODO: report decode errors
_ = fn(dc.flowDecoder, bs)
_ = fn(dc.flowDecoder, bs)
}
if g, ok := linkToFormat[linkType]; ok {

View File

@ -1,6 +1,8 @@
package pcap
import (
"fmt"
"github.com/wader/fq/format"
"github.com/wader/fq/format/inet/flowsdecoder"
"github.com/wader/fq/pkg/bitio"
@ -14,10 +16,15 @@ var linkToFormat = map[int]*decode.Group{
format.LinkTypeLINUX_SLL2: &pcapngSLL2PacketFormat,
}
var linkToDecodeFn = map[int]func(fd *flowsdecoder.Decoder, bs []byte){
var linkToDecodeFn = map[int]func(fd *flowsdecoder.Decoder, bs []byte) error{
format.LinkTypeETHERNET: (*flowsdecoder.Decoder).EthernetFrame,
format.LinkTypeLINUX_SLL: (*flowsdecoder.Decoder).SLLPacket,
format.LinkTypeLINUX_SLL2: func(fd *flowsdecoder.Decoder, bs []byte) {
format.LinkTypeLINUX_SLL2: func(fd *flowsdecoder.Decoder, bs []byte) error {
if len(bs) < 20 {
// TODO: too short sll packet, error somehow?
return fmt.Errorf("packet too short %d", len(bs))
}
// TODO: gopacket does not support SLL2 atm so convert SLL to SSL2
nbs := []byte{
0, bs[10], // packet type
@ -27,13 +34,14 @@ var linkToDecodeFn = map[int]func(fd *flowsdecoder.Decoder, bs []byte){
bs[0], bs[1], // protocol type
}
nbs = append(nbs, bs[20:]...)
fd.SLLPacket(nbs)
return fd.SLLPacket(nbs)
},
}
func fieldFlows(d *decode.D, fd *flowsdecoder.Decoder, tcpStreamFormat decode.Group, ipv4PacketFormat decode.Group) {
d.FieldArray("ipv4_reassembled", func(d *decode.D) {
for _, p := range fd.IPV4Reassbled {
for _, p := range fd.IPV4Reassembled {
bb := bitio.NewBufferFromBytes(p.Datagram, -1)
if dv, _, _ := d.TryFieldFormatBitBuf(
"ipv4_packet",
@ -51,29 +59,29 @@ func fieldFlows(d *decode.D, fd *flowsdecoder.Decoder, tcpStreamFormat decode.Gr
d.FieldStruct("flow", func(d *decode.D) {
d.FieldValueStr("source_ip", s.ClientEndpoint.IP.String())
d.FieldValueU("source_port", uint64(s.ClientEndpoint.Port), format.TCPPortMap)
d.FieldValueStr("destination_ip", s.ServerEnpoint.IP.String())
d.FieldValueU("destination_port", uint64(s.ServerEnpoint.Port), format.TCPPortMap)
csBB := bitio.NewBufferFromBytes(s.ClientStream.Bytes(), -1)
d.FieldValueStr("destination_ip", s.ServerEndpoint.IP.String())
d.FieldValueU("destination_port", uint64(s.ServerEndpoint.Port), format.TCPPortMap)
csBB := bitio.NewBufferFromBytes(s.ClientToServer.Bytes(), -1)
if dv, _, _ := d.TryFieldFormatBitBuf(
"client_stream",
csBB,
tcpStreamFormat,
format.TCPStreamIn{
SourcePort: s.ClientEndpoint.Port,
DestinationPort: s.ServerEnpoint.Port,
DestinationPort: s.ServerEndpoint.Port,
},
); dv == nil {
d.FieldRootBitBuf("client_stream", csBB)
}
scBB := bitio.NewBufferFromBytes(s.ServerStream.Bytes(), -1)
scBB := bitio.NewBufferFromBytes(s.ServerToClient.Bytes(), -1)
if dv, _, _ := d.TryFieldFormatBitBuf(
"server_stream",
scBB,
tcpStreamFormat,
format.TCPStreamIn{
SourcePort: s.ClientEndpoint.Port,
DestinationPort: s.ServerEnpoint.Port,
DestinationPort: s.ServerEndpoint.Port,
},
); dv == nil {
d.FieldRootBitBuf("server_stream", scBB)