tcp/ip填充部分代码参考<网络扫描技术揭密>,同样代码可以参考 anti_sniff代码的anti_sniff/flood_net.c,使用的是一样的方法。
预条件:
安装ethotool, 目的,为了关闭checksum的pre-calculated, 原因Google关键字"tcpdump cksum incorrect"
参考link http://seclists.org/tcpdump/2012/q4/91
http://linux.about.com/od/commands/l/blcmdl8_ethtool.htm
安装ethtool过程:
>>./configure
>>make
>>./ethtool -K eth0 rx off
简易prot scanner使用方法
>>./a.out ipaddress startport endport
代码:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <pthread.h>
#define PACKET_LENGTH 128
#define IP_LENGTH 16
struct sockInfo{
int dport;
char dIpAddr[IP_LENGTH];
};
struct ip_hdr{
unsigned char h_verlen;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
};
struct psd_hdr{
unsigned long saddr;
unsigned long daddr;
unsigned char mbz;
unsigned char ptcl;
unsigned long tcpl;
};
//reference /use/include/netinet/tcp.h
struct tcp_hdr{
u_int16_t th_sport;
u_int16_t th_dport;
u_int32_t th_seq;
u_int32_t th_ack;
u_int8_t th_lenres;
u_int8_t th_flag;
u_int16_t th_win;
u_int16_t th_sum;
u_int16_t th_urp;
};
void* tcpScan(void* param);
void fillSockInfo(struct sockInfo *pSockInfo, char* destIp, int destPort);
void usage(void);
unsigned short csum(unsigned short *buf, int len);
int main(int argc, char* argv[])
{
int startPort = 0;
int endPort = 0;
int numPort = 0;
int i = 0;
char buf[PACKET_LENGTH] = {0};
struct iphdr *ip = (struct iphdr *) buf;
struct tcphdr *tcp = (struct tcphdr*)(buf + sizeof(struct iphdr));
struct sockInfo sInfo = {0};
int one = 1;
const int* val = &one;
if( 4 != argc){
usage();
return 0;
}
startPort = atoi(argv[2]);
endPort = atoi(argv[3]);
if((startPort < 1) ||(startPort > 65535)){
printf("Error: port number should between 1~56635\n");
return 0;
}
if((endPort < 1)||(endPort > 65535)){
printf("Error: port number should between 1~56635\n");
return 0;
}
if(startPort > endPort){
printf("Error: start port should not be greater than end port\n");
return 0;
}
numPort = endPort - startPort + 1;
for(i = 0; i < numPort; i++){
fillSockInfo(&sInfo, argv[1], startPort+ i);
tcpScan((void*)&sInfo);
}
return 0;
}
void usage(void)
{
printf("Usage:\n");
printf("\t\t ./sscan ipaddress startport endport\n");
return;
}
void fillSockInfo(struct sockInfo *pSockInfo, char* destIp, int destPort)
{
memset(pSockInfo, 0, sizeof(struct sockInfo));
pSockInfo->dport = destPort;
strcpy(pSockInfo->dIpAddr, destIp);
return ;
}
void* tcpScan(void* param)
{
char* src = "192.168.0.133";
char* dst = ((struct sockInfo*)param)->dIpAddr;
int dPort =((struct sockInfo*)param)->dport;
int sPort = 55555;
int sd = 0;
char buf[PACKET_LENGTH] = {0};
char recv[PACKET_LENGTH] = {0};
struct iphdr *ip = (struct iphdr*) buf;
struct tcphdr *tcp = (struct tcphdr*)(buf + sizeof(struct iphdr));
struct ip_hdr ipHeader = {0};
struct tcp_hdr tcpHeader = {0};
struct psd_hdr psdHeader = {0};
struct sockaddr_in sin, din;
int one = 1;
int cnt = 0;
socklen_t socklen = 0;
const int *val = &one;
struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;
memset(buf, 0, PACKET_LENGTH);
sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if( sd < 0){
perror("socket() error");
exit(-1);
}else{
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");
}
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
sin.sin_port = htons(sPort);
din.sin_port = htons(dPort);
sin.sin_addr.s_addr = inet_addr(src);
din.sin_addr.s_addr = inet_addr(dst);
ipHeader.h_verlen = (4<<4|sizeof(ipHeader)/sizeof(unsigned long));
ipHeader.tos = 0;
ipHeader.total_len = htonl(sizeof(ipHeader) + sizeof(tcpHeader));
ipHeader.ident = 1;
ipHeader.frag_and_flags = 0;
ipHeader.ttl = 128;
ipHeader.proto = IPPROTO_TCP;
ipHeader.checksum = 0;
ipHeader.sourceIP = inet_addr(src);
ipHeader.destIP = inet_addr(dst);
tcpHeader.th_sport = htons(sPort);
tcpHeader.th_dport = htons(dPort);
tcpHeader.th_seq = (random()%65535);
tcpHeader.th_ack = (random()%65535);
tcpHeader.th_lenres = (sizeof(tcpHeader)/4 << 4 | 0);
tcpHeader.th_flag = 2;
tcpHeader.th_win = htons(512);
tcpHeader.th_urp = 0;
tcpHeader.th_sum = 0;
psdHeader.saddr = inet_addr(src);
psdHeader.daddr = inet_addr(dst);
psdHeader.mbz = 0;
psdHeader.ptcl = IPPROTO_TCP;
psdHeader.tcpl = htonl(sizeof(tcpHeader));
memcpy(buf, &psdHeader, sizeof(psdHeader));
memcpy(buf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader));
tcpHeader.th_sum = csum((unsigned short*) buf, sizeof(*ip) + sizeof(tcpHeader));
memcpy(buf, &ipHeader, sizeof(ipHeader));
memcpy(buf+ sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));
ipHeader.checksum = csum((unsigned short*) buf, sizeof(ipHeader)+ sizeof(tcpHeader));
memcpy(buf, &ipHeader, sizeof(ipHeader));
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0){
perror("setsockopt() error");
exit(-1);
}else{
printf("setsockopt() is OK\n");
}
if (setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0){
error("setsockopt failed\n");
}else{
printf("setsockopt() is OK\n");
}
if (setsockopt (sd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0){
error("setsockopt failed\n");
}else{
printf("setsockopt() is OK\n");
}
if(sendto(sd, buf, sizeof(ipHeader) + sizeof(tcpHeader), 0, (struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("sendto() error");
exit(-1);
}else{
printf("sendto() is OK\n");
}
cnt = 5;
while(cnt){
memset(recv, 0, PACKET_LENGTH);
if( recvfrom(sd, recv, PACKET_LENGTH, 0, (struct sockaddr*)&sin, (socklen_t *)&socklen) > 0 ){
printf("receive data from %d\n", dPort);
break;
}
cnt--;
}
return NULL;
}
unsigned short csum(unsigned short *buf, int len)
{
unsigned long sum;
for(sum=0; len>0; len--){
sum += *buf++;
}
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}
===============================================================================================================================
发送端:
接收端