How to append data on a packet from kernel space?

后端 未结 2 1404
清歌不尽
清歌不尽 2020-12-09 06:58

I am trying to append some data on a packet from kernel space. I have an echo client and server. I type in the command line like: ./client \"message\" and the server just

相关标签:
2条回答
  • 2020-12-09 07:26

    About one year ago for kernel 2.6.26 I did it like this:

    // Do we need extra space?
    if(len - skb_tailroom(skb) > 0){
    
      // Expand skb tail until we have enough room for the extra data
      if (pskb_expand_head(skb, 0, extra_data_len - skb_tailroom(skb), GFP_ATOMIC)) {
        // allocation failed. Do whatever you need to do
      }
    
      // Allocation succeeded
    
      // Reserve space in skb and return the starting point
      your_favourite_structure* ptr = (your_favourite_structure*) 
                                      skb_push(skb, sizeof(*ptr)); 
    
      // Now either set each field of your structure or memcpy into it.
      // Remember you can use a char*
    
    }
    

    Don't forget:

    • Recalculate UDP checksum, because you changed data in the transported data.

    • Change the field tot_len(total length) in the ip header, because you added data to the packet.

    • Recalculate the IP header checksum, because you changed the tot_len field.

    Extra note: This is just a simple thing. I see in your code you're allocating tmp as a 200 byte array and using that to store the data of your message. If you send a bigger packet you'll have a hard time debugging this as kernel crashes due to memory overflows are too painful.

    0 讨论(0)
  • 2020-12-09 07:35

    I have solved the problem. It was trivial. And all I am going to do is to post my code for future references and discussion.

    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/skbuff.h>
    #include <linux/netfilter.h>
    #include <linux/netdevice.h>
    #include <linux/ip.h>
    #include <linux/udp.h>
    #include <linux/mm.h>
    #include <linux/err.h>
    #include <linux/crypto.h>
    #include <linux/init.h>
    #include <linux/crypto.h>
    #include <linux/scatterlist.h>
    #include <net/ip.h>
    #include <net/udp.h>
    #include <net/route.h>
    
    #undef __KERNEL__
    #include <linux/netfilter_ipv4.h>
    #define __KERNEL__
    
    #define IP_HDR_LEN 20
    #define UDP_HDR_LEN 8
    #define TOT_HDR_LEN 28
    
    static unsigned int pkt_mangle_begin(unsigned int hooknum,
                            struct sk_buff *skb,
                            const struct net_device *in,
                            const struct net_device *out,
                            int (*okfn)(struct sk_buff *));
    
    static struct nf_hook_ops pkt_mangle_ops __read_mostly = {
        .pf = NFPROTO_IPV4,
        .priority = 1,
        .hooknum = NF_IP_LOCAL_OUT,
        .hook = pkt_mangle_begin,
    };
    
    static int __init pkt_mangle_init(void)
    {
        printk(KERN_ALERT "\npkt_mangle module started ...");
        return nf_register_hook(&pkt_mangle_ops);
    }
    
    static void __exit pkt_mangle_exit(void)
    {
        nf_unregister_hook(&pkt_mangle_ops);
        printk(KERN_ALERT "pkt_mangle module stopped ...");
    } 
    
    static unsigned int pkt_mangle_begin (unsigned int hooknum,
                            struct sk_buff *skb,
                            const struct net_device *in,
                            const struct net_device *out,
                            int (*okfn)(struct sk_buff *))
    { 
        struct iphdr *iph;
        struct udphdr *udph;
        unsigned char *data;
    
        unsigned int data_len;
        unsigned char extra_data[] = "12345";
        unsigned char *temp;
        unsigned int extra_data_len;
        unsigned int tot_data_len;
    
        unsigned int i;
    
        __u16 dst_port, src_port;
    
        if (skb) {
            iph = (struct iphdr *) skb_header_pointer (skb, 0, 0, NULL);
    
            if (iph && iph->protocol &&(iph->protocol == IPPROTO_UDP)) {
                udph = (struct udphdr *) skb_header_pointer (skb, IP_HDR_LEN, 0, NULL);
                src_port = ntohs (udph->source);
                dst_port = ntohs (udph->dest);
    
                if (src_port == 6000) {
                    printk(KERN_ALERT "UDP packet goes out");
                    data = (unsigned char *) skb_header_pointer (skb, IP_HDR_LEN+UDP_HDR_LEN, 0, NULL);
                    data_len = skb->len - TOT_HDR_LEN;
    
                        temp = kmalloc(512 * sizeof(char), GFP_ATOMIC);
                    memcpy(temp, data, data_len);
    
                    unsigned char *ptr = temp + data_len - 1;
                    extra_data_len = sizeof(extra_data);
                    memcpy(ptr, extra_data, extra_data_len);
                    tot_data_len = data_len + extra_data_len - 1;
    
                    skb_put(skb, extra_data_len - 1);
    
                    memcpy(data, temp, tot_data_len);
    
                    /* Manipulating necessary header fields */
                    iph->tot_len = htons(tot_data_len + TOT_HDR_LEN);
                    udph->len = htons(tot_data_len + UDP_HDR_LEN);
    
                    /* Calculation of IP header checksum */
                    iph->check = 0;
                    ip_send_check (iph);
    
                    /* Calculation of UDP checksum */
                    udph->check = 0;
                    int offset = skb_transport_offset(skb);
                    int len = skb->len - offset;
                    udph->check = ~csum_tcpudp_magic((iph->saddr), (iph->daddr), len, IPPROTO_UDP, 0);
    
                     }
            }
        }
        return NF_ACCEPT;
    }
    
    
    module_init(pkt_mangle_init);
    module_exit(pkt_mangle_exit);
    
    MODULE_AUTHOR("Rifat Rahman Ovi: <rifatrahmanovi@gmail.com>");
    MODULE_DESCRIPTION("Outward Packet Mangling and Decryption in Kernel Space");
    MODULE_LICENSE("GPL");
    

    Here the thing is that, I forgot to update the length fields and forgot to update the checksum. Now, if I present the code correctly here, all should go well. There are some other helper functions which are not included here.

    0 讨论(0)
提交回复
热议问题