gpt4 book ai didi

c - 如何从内核空间向数据包附加数据?

转载 作者:IT王子 更新时间:2023-10-29 00:33:02 24 4
gpt4 key购买 nike

我正在尝试将一些数据附加到来自内核空间的数据包上。我有一个回声客户端和服务器。我在命令行中键入:./client "message",服务器只是回显它。服务器使用 ./server 运行。

现在,客户端和服务器在两台不同的机器上(可能是虚拟机)。我正在编写一个在客户端机器上运行的内核模块。它的工作是在数据包离开机器时在“消息”之后附加“12345”。我在下面展示代码。

/*
* This is ibss_obsf_cat.c
*/

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/udp.h>
#include <linux/ip.h>

#undef __KERNEL__
#include <linux/netfilter_ipv4.h>
#define __KERNEL__


/*
* Function prototypes ...
*/

static unsigned int cat_obsf_begin (unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *));

static void hex_dump (char str[], int len)
{

}

/*
* struct nf_hook_ops instance initialization
*/

static struct nf_hook_ops cat_obsf_ops __read_mostly = {
.pf = NFPROTO_IPV4,
.priority = 1,
.hooknum = NF_IP_POST_ROUTING,
.hook = cat_obsf_begin,
};

/*
* Module init and exit functions.
* No need to worry about that.
*/

static int __init cat_obsf_init (void)
{
printk(KERN_ALERT "cat_obsf module started...\n");
return nf_register_hook(&cat_obsf_ops);
}

static void __exit cat_obsf_exit (void)
{
nf_unregister_hook(&cat_obsf_ops);
printk(KERN_ALERT "cat_obsf module stopped...\n");
}

/*
* Modification of the code begins here.
* Here are all the functions and other things.
*/

static unsigned int cat_obsf_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 char dt[] = "12345";
unsigned char *tmp;
unsigned char *ptr;

int i, j, len;

if (skb){
iph = ip_hdr(skb);

if (iph && iph->protocol && (iph->protocol == IPPROTO_UDP)){
udph = (struct udphdr *) ((__u32 *)iph + iph->ihl);
data = (char *)udph + 8;

if(ntohs(udph->dest) == 6000){
for (i=0; data[i]; i++);
len = i;

//printk(KERN_ALERT "\nData length without skb: %d", len);
//printk(KERN_ALERT "Data is: %s", data);
//printk(KERN_ALERT "dt size: %lu", sizeof(dt));
//printk(KERN_ALERT "skb->len: %d", skb->len);
tmp = kmalloc(200*sizeof(char), GFP_KERNEL);

memcpy(tmp, data, len);
ptr = tmp + len;
memcpy(ptr, dt, sizeof(dt));

printk(KERN_ALERT "tmp: %s", tmp);


printk(KERN_ALERT "skb->tail: %d", skb->tail);
//skb_put(skb, sizeof(dt));
printk(KERN_ALERT "skb->end: %d", skb->end);
printk(KERN_ALERT "skb->tail: %d", skb->tail);
printk(KERN_ALERT "skb->tail(int): %d", (unsigned int)skb->tail);

//memset(data, 0, len + sizeof(dt));

//memcpy(data, tmp, len + sizeof(dt));

//skb_add_data(skb, tmp, len+sizeof(dt));

printk(KERN_ALERT "Now data is: %s", data);
for(i=0; data[i]; i++);
printk(KERN_ALERT "data length: %d", i);

kfree(tmp);

}
}
}
return NF_ACCEPT;
}

/*
* Nothing to be touched hereafter
*/

module_init(cat_obsf_init);
module_exit(cat_obsf_exit);

MODULE_AUTHOR("Rifat");
MODULE_DESCRIPTION("Module for packet mangling");
MODULE_LICENSE("GPL");

我想让“消息”成为“message12345”,同时从内核空间发送出客户端机器。这样服务器将获得“message12345”并将其回显,客户端将只读取“message12345”但是我在使用 skb_put() 和 skb_add_data() 函数时遇到了问题。我不明白我犯了什么错误。如果有人可以帮助我编写代码,我将不胜感激。提前致谢。为了方便起见,我还提供了 Makefile。这是针对分发内核,而不是针对内置内核。

#If KERNELRELEASE is defined, we've been invoked from the
#kernel build system and use its language
ifneq ($(KERNELRELEASE),)
obj-m := ibss_obsf_cat.o

#Otherwise we were called directly from the command
#line; invoke the kernel build system.
else

KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

endif

现在我很确定 skb->end - skb->tail太小了,我将不得不在内核空间中创建新的数据包。我用过 alloc_skb() skb_reserve() skb_header_pointer()和其他用于创建新 skb 的有用 skb 函数,但我想不通的是如何在数据包流路径中路由新创建的数据包。使用方法
ip_route_me_harder()我在 xtables-addons 包中寻找建议,但他们使用的功能与 linux 内核中的功能不同。欢迎任何建议。

最佳答案

大约一年前,对于内核 2.6.26,我是这样做的:

// 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*

}

不要忘记:

  • 重新计算 UDP 校验和,因为您更改了传输数据中的数据。

  • 更改 ip header 中的字段 tot_len(总长度),因为您向数据包添加了数据。

  • 重新计算 IP header 校验和,因为您更改了 tot_len 字段。

额外说明:这只是一件简单的事情。我在您的代码中看到您将 tmp 分配为一个 200 字节的数组,并使用它来存储您的消息数据。如果你发送一个更大的数据包,你将很难调试它,因为内存溢出导致内核崩溃太痛苦了。

关于c - 如何从内核空间向数据包附加数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12529497/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com