【问题标题】:Netfilter Kernel module doesn't get the ftp packets' dataNetfilter 内核模块没有得到 ftp 数据包数据
【发布时间】:2022-08-03 13:34:05
【问题描述】:

Netfilter 内核模块未获取 FTP 数据包数据

问题

我一直在尝试编写一个内核模块来通过 netfilter 读取传出的 FTP 数据包的用户名、密码和 cmd。当我测试我的代码时,我发现 ftp 数据包的长度是正确的,但是我得到的所有数据都是0x00 检查内核模块的输出时。

代码

这是我的代码。我写了一个pkt_hex_dump 函数来将我所有的数据包的字节转储到 Internet 层(包括 Internet 层)之上,这符合 Printing sk_buff data

/* Sample code to install a Netfilter hook function */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/icmp.h>
#include <linux/netdevice.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>

MODULE_LICENSE(\"MIT\");
MODULE_AUTHOR(\"1933\");
MODULE_DESCRIPTION(\"An net sniff module for demonstration\");
MODULE_VERSION(\"1.0\");

/* Used to describe our Netfilter hooks */
static struct nf_hook_ops post_hook;

/* THESE values are used to keep the USERname and PASSword until
 * they are queried. Only one USER/PASS pair will be held at one
 * time
 */

static char *username = NULL;
static char *password = NULL;
static unsigned short src_port = 0; 
static int  have_pair = 0;   /* Marks if we already have a pair */

/* dump packet\'s data */
void pkt_hex_dump(struct sk_buff *skb){
    size_t len;
    int rowsize = 16;
    int i, l, linelen, remaining;
    int li = 0;
    uint8_t *data, ch; 
    struct iphdr *ip = (struct iphdr *)skb_network_header(skb);

    printk(\"Packet hex dump:\\n\");
    data = (uint8_t *) skb_network_header(skb);

    len=ntohs(ip->tot_len);

    remaining = len;
    for (i = 0; i < len; i += rowsize) {
        printk(\"%06d\\t\", li);
        linelen = min(remaining, rowsize);
        remaining -= rowsize;
        for (l = 0; l < linelen; l++) {
            ch = data[l];
            printk(KERN_CONT \"%02X \", (uint32_t) ch);
        }
        data += linelen;
        li += 10; 

        printk(KERN_CONT \"\\n\");
    }
}

/* This is the hook function itself */
unsigned int watch_out(void *priv,
        struct sk_buff *skb,
        const struct nf_hook_state *state)
{
    struct iphdr *ip = NULL;
    struct tcphdr *tcp = NULL;
    unsigned char *data=NULL;

    ip = (struct iphdr *)skb_network_header(skb);
    if (ip->protocol != IPPROTO_TCP){
        return NF_ACCEPT;
    }

    tcp = (struct tcphdr *)skb_transport_header(skb);

    /* Now check to see if it\'s an FTP packet */
    if (tcp->dest!= htons(21)){
        return NF_ACCEPT;    
    }
    
    pkt_hex_dump(skb);
  /* Parse the FTP packet for relevant information if we don\'t already
   * have a username and password pair. */
     data = (unsigned char *)((unsigned char *)tcp + (tcp->doff * 4));

    printk(\"hex : data[0-3] = 0x%02x%02x%02x%02x\\n\", data[0], data[1], data[2], data[3]);
    printk(\"char: data[0-3] = %c%c%c%c\\n\", data[0], data[1], data[2], data[3]);
    printk(\"--------------- findpkt_iwant ------------------\\n\");
    return NF_ACCEPT;
}

/* Initialisation routine */
int init_module(){
    /* Fill in our hook structure */
    post_hook.hook = watch_out;         /* Handler function */
    post_hook.hooknum  = NF_INET_POST_ROUTING; 
    post_hook.pf       = AF_INET;
    post_hook.priority = NF_IP_PRI_FIRST;   /* Make our function first */

    nf_register_net_hook(&init_net,&post_hook);

    // Debug
    printk(\"HELLO:  this is hello module speaking\\n\");
    return 0;
}

/* Cleanup routine */
void cleanup_module(){
    printk(\"HELLO : Goodbye!\\n\");
    nf_unregister_net_hook(&init_net,&post_hook);
}

环境

  • Linux 5.13.0-37-通用 x86_64 GNU/Linux
  • Ubuntu 20.04.4 LTS
  • 生成文件:
    obj-m+=NetKernal.o
    
    all:
        make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
    

内核模块的输出和 Wireshark 的捕获:

  • 这是the whole demsg output,当我连接到 ftp 服务器并在局域网上输入我的用户名和密码时。

  • 这是添加过滤规则后的整个wireshark packettcp.dstport == 21。Internet 层字节以 pcapng 中的偏移量0xe 开头。

这些ftp数据包有什么奇怪的。以第四个数据包为例。

  • 这是内核模块的日志。(原始数据中不存在的/**/是我添加的注释以便更好地理解)
[ 4964.195893] Packet hex dump:
[ 4964.195904] 000000   45 10 00 42 D9 86 40 00 40 06 DD BC C0 A8 01 07     /* dump start from Internet layer */
[ 4964.195953] 000010   C0 A8 01 0B 93 E4 00 15 A5 63 17 A8 92 28 25 E3 
[ 4964.195982] 000020   80 18 01 F6 83 97 00 00 01 01 08 0A C0 EC BD AB 
[ 4964.196011] 000030   00 08 A7 2F 00 00 00 00 00 00 00 00 00 00 00 00     /* ftp content:0x00 */
[ 4964.196038] 000040   00 00 
[ 4964.196045] hex : data[0-3] = 0x00000000
[ 4964.196049] char: data[0-3] = 
[ 4964.196052] --------------- findpkt_iwant ------------------
  • 这是根据以下内容的wireshark捕获数据包:
No.     Time           Source                Source Port Destination           Destination Port Protocol Length Info
    132 14.635575358   192.168.1.7           37860       192.168.1.11          21               FTP      80     Request: USER ftpuser

Frame 132: 80 bytes on wire (640 bits), 80 bytes captured (640 bits) on interface wlp3s0, id 0
Ethernet II, Src: 58:a0:23:05:3b:2e, Dst: 1c:c1:de:65:e5:d4
Internet Protocol Version 4, Src: 192.168.1.7, Dst: 192.168.1.11
Transmission Control Protocol, Src Port: 37860, Dst Port: 21, Seq: 1, Ack: 28, Len: 14
File Transfer Protocol (FTP)
[Current working directory: ]

0000  1c c1 de 65 e5 d4 58 a0 23 05 3b 2e 08 00 45 10   ...e..X.#.;...E.    /* # Internet layer starts from the offset 0x0e */
0010  00 42 d9 86 40 00 40 06 dd bc c0 a8 01 07 c0 a8   .B..@.@.........
0020  01 0b 93 e4 00 15 a5 63 17 a8 92 28 25 e3 80 18   .......c...(%...
0030  01 f6 ab 01 00 00 01 01 08 0a c0 ec bd ab 00 08   ................
0040  a7 2f 55 53 45 52 20 66 74 70 75 73 65 72 0d 0a   ./USER ftpuser..

可以看出,ftp数据包的内容是0x00,但是整个数据包的长度是正确的(在Internet层之上)。所有其他的ftp数据包都有同样的问题。似乎 sk_buff 没有得到 ftp 数据。

由于wireshark可以得到正确的数据包,我不认为它是防火墙的问题。

我的问题是:

  • 为什么所有 ftp 数据包的内容都是0x00 而数据包的长度是正确的?
  • 我的 ftp 数据在 struct sk_buff 中的什么位置或存储在其他位置?
  • 是否有人遇到过同样的问题?

任何帮助将不胜感激。

    标签: c linux-kernel network-programming kernel-module netfilter


    【解决方案1】:

    我也有同样的问题!只有 Ubuntu 22 不能正确运行代码,在 Ubuntu 16 LTS 下可以,我猜代码是正确的,问题是 Ubuntu 系统,可能系统增加了新的安全特性?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-13
      • 2018-08-18
      • 2020-03-14
      • 2014-07-17
      • 2018-03-12
      • 2011-12-29
      • 1970-01-01
      相关资源
      最近更新 更多