Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify header of a captured packet

I am trying to modify the IP header to include more IP options with the use of the libnetfiletr_queue. So far I have managed to come to the point where I obtain the packet as shown below.

if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
    fprintf(stderr, "Unable to set nfq_set_mode\n");
    exit(1);
}

Then I managed to go far as shown below,

static int my_callBack(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,struct nfq_data *tb)
{   
    int id = 0;
    int packet_len;
    unsigned char *data;
    struct nfqnl_msg_packet_hdr *packet_hdr;
    unsigned char *data;

    packet_hdr = nfq_get_msg_packet_hdr(tb);

    if (packet_hdr) {
        id = ntohl(packet_hdr->packet_id);          
    }

    packet_len = nfq_get_payload(tb, &data);

    if (packet_len >= 0) {
        //print payload length
        printf("payload_length = %d ", packet_len);
        //modify packet ip header  
    }

    return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
}

But from here onwards I am a bit confused on how to proceed on modifying the IP header of the captured packet at //modify packet ip header comment.Example on a modification to the IP header (such as traffic class(IPV6)/ IP options/ version/ flags/ destination address) is ok since I only need to understand how the modification works :).

I have tried many resources and could not succeed in proceeding any further. You expert advice and help on this query will be very much appreciated. :)

Thank you very much :)

like image 912
Hasitha Shan Avatar asked Oct 01 '22 09:10

Hasitha Shan


1 Answers

To modify the values of an IP header, start by defining a structure to represent your header. You find what the structure should be by reading the RFC spec for the protocol you're trying to access.

Here's a link to the RFC for IPv6: https://www.rfc-editor.org/rfc/rfc2460#section-3

The first row of the IPv6 header is a bit tricky, because they aren't using byte-aligned fields. The Version field is 4-bits wide, the Traffic Class is 8-bits wide, and the Flow Label is 20-bits wide. The whole header is 320 bits (40 bytes) and 256 of those are src and dest address. Only 64-bits are used for the other fields, so it's probably easiest to define your struct like this:

struct ipv6_hdr {
    uint32_t row1;
    uint16_t payload_length;
    uint8_t next_header;
    uint8_t hop_limit;
    uint16_t src[8];
    uint16_t dest[8];
};

To extract the row one values, you can use some masking:

#define VERSION_MASK 0xF0000000
#define TRAFFIC_CLASS_MASK 0x0FF00000
#define FLOW_LABEL_MASK 0x000FFFFF

struct ipv6_hdr foo;

...

nfq_get_payload(tb, &foo); // Just an example; don't overflow your buffer!

// bit-wise AND gets masked field from row1
uint8_t version = (uint8_t) ((foo->row1 & VERSION_MASK) >> 28);  // shift (32-4) bits

Once you point your struct to the data payload, assuming your byte array matches this format, modifying the header values becomes simple assignment:

version = 6;

// bit-wise OR puts our value in the right place in row1
foo->row1 &= ~(VERSION_MASK) // clear out the old value first
foo->row1 = ((uint32_t) version << 28) | foo->row1;  

I chose to make the src and dest addresses in the struct an array of 16-bit values because IPv6 addresses are a series of 8, 16-bit values. This should make it easy to isolate any given pair of bytes.

You will have to determine what format your data payload is in before applying the proper struct to it.

For info on how to create an IPv4 header, check its RFC: https://www.rfc-editor.org/rfc/rfc791#section-3.1

Hope this helps (you may have to fiddle with my code samples to get the syntax right, it's been a few months).


editing with info about checksums as requested in comments

Follow this RFC for generating checksums after modifying your header: https://www.rfc-editor.org/rfc/rfc1071

The key take-away there is to zero the checksum field in the header before generating the new checksum.

like image 125
awiseman Avatar answered Oct 18 '22 11:10

awiseman