Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation fault when getting payload_size of a RawPDU with length of 0 #429

Closed
kevsjh opened this issue Feb 7, 2021 · 2 comments
Closed

Comments

@kevsjh
Copy link

kevsjh commented Feb 7, 2021

Hi there,

I am trying to parse TCP DNS packet with libtins. From initial testing, it doesn't seemed to be supported. I have came up with the following to parse TCP DNS and was able to do so successfully.



TCP *tcp = pkt.find_pdu<TCP>();

    if (tcp)
    {
        //check if its dns ports
        if (tcp->sport() == 53 || tcp->dport() == 53)
        {
            // retrieve TCP layer PDU

            //retrieve TCP layer PDU payload
            RawPDU &raw = *tcp->find_pdu<RawPDU>();

            // check if payload size is 0, parse TCP dns if payload size is not 0
            if (raw.payload_size() == 0)
            {
                std::cout << "no dns field" << std::endl;
            }
            else
            {
                std::cout << raw.payload_size() << std::endl;
                RawPDU::payload_type &payload = raw.payload();
                // Omit the first 2 byte of DNS length field, only included
                // in TCP based on RFC7766, in order to reuse the DNS UDP parser
                payload.erase(payload.begin(), payload.begin() + 2);
                //parse the modified payload to DNS parser
                DNS dns = raw.rfind_pdu<RawPDU>().to<DNS>();
                std::cout << dns.id() << std::endl;

                for (const auto &query : dns.queries())
                {
                    std::cout << query.dname() << std::endl;
                }
            }
        }


However, one of my check before parsing TCP DNS was to check if the TCP length !=0 as that would represent the presence of DNS layer.
When calling for raw.payload_size() for PDU with length 0, I'm getting Segmentation fault error.
I tried to modified rawpdu.h so that the RawPDU object instantiated with 0 but doesn't work too

RawPDU(const uint8_t* pload, uint32_t size=0);

Any idea on this? Otherwise it works great.

image of the said tcp packet without dns field, len=0
image

@mfontanini
Copy link
Owner

Hello! The problem in your code is that you're getting a pointer to the RawPDU in that packet, dereferencing it and using it, even though there may not be such a layer in the packet at all. If the TCP packet contains no payload, there simply won't be a RawPDU layer in it at all.

To make your code work, you'd need to fetch a pointer to the RawPDU layer, make sure it's there, and then use it. e.g.:

// Fetch a *pointer* to it
const RawPDU* raw = tcp->find_pdu<RawPDU>();

if (raw == nullptr) {
    std::cout << "No payload in this packet!\n";
}
else {
    // It is safe to use `raw` here
}

@kevsjh
Copy link
Author

kevsjh commented Feb 8, 2021

Tried and tested and its working. Thank you so much for your help! I shall close this

@kevsjh kevsjh closed this as completed Feb 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants