-
#include <stdio.h>
-
#include <string.h>
-
#include <errno.h>
-
#include <sys/types.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <linux/if_ether.h>
-
#include <linux/sockios.h>
-
#include <sys/socket.h>
-
#include <netpacket/packet.h>
-
#include <net/ethernet.h>
-
#include <net/if_arp.h>
-
#include <net/if.h>
-
-
-
#define DESTPORT 80
-
#define LOCALPORT 0x8888
-
-
/* Buffer Size */
-
#define SND_BUF_SIZE 1024*5
-
-
/* Buffer */
-
static int g_iSendBufSize = SND_BUF_SIZE;
-
-
static int g_iRecvBufSize = SND_BUF_SIZE;
-
-
static unsigned long seqno, ackno; //save sequence no and ackment no
-
-
extern int errno;
-
-
/* Prseuheader */
-
struct prseuheader
-
{
-
unsigned long s_addr;
-
unsigned long d_addr;
-
unsigned char zero;
-
unsigned char prototp;
-
unsigned short len;
-
};
-
-
/* IP Head */
-
struct IP_Head
-
{
-
unsigned char length:4;
-
unsigned char version:4;
-
unsigned char tos;
-
unsigned short total_length;
-
unsigned short id;
-
unsigned short flagoff;
-
unsigned char ttl;
-
unsigned char protocol;
-
unsigned short chksum;
-
unsigned int source;
-
unsigned int dest;
-
};
-
-
/* TCP Head */
-
struct TCP_Head
-
{
-
unsigned short source_port;
-
unsigned short dest_port;
-
unsigned int seqno;
-
unsigned int ackno;
-
unsigned char rev1:4;
-
unsigned char len:4;
-
unsigned char fin:1;
-
unsigned char syn:1;
-
unsigned char rst:1;
-
unsigned char psh:1;
-
unsigned char ack:1;
-
unsigned char urg:1;
-
unsigned char rev2:2;
-
unsigned short winsize;
-
unsigned short chksum;
-
unsigned short urgent;
-
};
-
-
/* Check sum */
-
unsigned short
-
checksum (unsigned short *buffer, int size)
-
{
-
unsigned long cksum = 0;
-
-
while (size > 1)
-
{
-
cksum += *buffer++;
-
size -= 2;
-
}
-
if (size)
-
{
-
cksum += *(u_char *) buffer;
-
}
-
cksum = (cksum >> 16) + (cksum & 0xffff);
-
cksum += (cksum >> 16);
-
return (unsigned short) (~cksum);
-
}
-
-
//Create SOCK_RAW
-
int
-
creat_raw ()
-
{
-
int sk;
-
-
sk = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL));
-
if (sk < 0)
-
{
-
strerror (errno);
-
return -1;
-
}
-
return sk;
-
}
-
-
//Set sock option
-
int
-
set_promisc (int sk)
-
{
-
// struct ifreq ifr;
-
//
-
// strcpy (ifr.ifr_name, "eth0");
-
// if ((ioctl (sk, SIOCGIFFLAGS, &ifr) == -1))
-
// {
-
// strerror (errno);
-
// }
-
// ifr.ifr_flags |= IFF_PROMISC;
-
// if (ioctl (sk, SIOCSIFFLAGS, &ifr) == -1)
-
// {
-
// strerror (errno);
-
// }
-
return 0;
-
}
-
-
/* fill ip head */
-
int
-
fill_iph (unsigned char buffer[])
-
{
-
struct IP_Head *pIph;
-
-
int total_len = sizeof (struct IP_Head) + sizeof (struct TCP_Head);
-
-
-
pIph = (struct IP_Head *) buffer;
-
-
pIph->length = 5;
-
pIph->version = 4;
-
pIph->tos = 0;
-
pIph->total_length = htons (total_len);
-
pIph->id = 0;
-
pIph->flagoff = htons (0x4000);
-
pIph->ttl = 255;
-
pIph->protocol = 6;
-
pIph->chksum = 0;
-
pIph->source = inet_addr ("192.168.1.2"); //Local PC 写上自己网卡的IP
-
pIph->dest = inet_addr ("119.75.217.56"); //remote PC 服务器的IP
-
pIph->chksum =
-
checksum ((unsigned short *) pIph, sizeof (struct IP_Head));
-
-
return 0;
-
}
-
-
/* fill tcp head */
-
int
-
fill_tcp (unsigned char buffer[], unsigned char control)
-
{
-
struct TCP_Head *pTcph;
-
-
pTcph = (struct TCP_Head *) (buffer + sizeof (struct IP_Head));
-
-
pTcph->source_port = htons (LOCALPORT);
-
pTcph->dest_port = htons (DESTPORT);
-
pTcph->seqno = htonl (seqno);
-
pTcph->ackno = htonl (ackno);
-
pTcph->rev1 = 0;
-
pTcph->len = 5;
-
pTcph->fin = control & 0x01 ? 1 : 0;
-
pTcph->syn = control & 0x02 ? 1 : 0;
-
pTcph->rst = control & 0x04 ? 1 : 0;
-
pTcph->psh = control & 0x10 ? 1 : 0;
-
pTcph->ack = control & 0x20 ? 1 : 0;
-
pTcph->urg = control & 0x40 ? 1 : 0;
-
pTcph->rev2 = 0;
-
pTcph->winsize = htons (1000);
-
pTcph->chksum = 0;
-
pTcph->urgent = 0;
-
-
return 0;
-
}
-
-
//send tcp packet
-
int
-
sendto_packet (int sk, unsigned char buffer[])
-
{
-
int iRet;
-
-
struct IP_Head *pIph;
-
-
struct TCP_Head *pTcph;
-
-
struct prseuheader theheader;
-
-
char tcpbuff[32]; //it include prseuheader and tcp head
-
-
int total_len = sizeof (struct IP_Head) + sizeof (struct TCP_Head);
-
-
struct sockaddr_ll addr;
-
-
pIph = (struct IP_Head *) buffer;
-
pTcph = (struct TCP_Head *) (buffer + sizeof (struct IP_Head));
-
-
bzero (&addr, sizeof (struct sockaddr_ll));
-
addr.sll_family = htons (PF_PACKET);
-
addr.sll_protocol = htons (ETH_P_IP);
-
addr.sll_ifindex = if_nametoindex ("eth0");//换成你的网口的名字
-
addr.sll_addr[0] = 0x08;//
-
addr.sll_addr[1] = 0x10;//
-
addr.sll_addr[2] = 0x74;//换成你的网关的MAC地址就行了
-
addr.sll_addr[3] = 0xC9;//
-
addr.sll_addr[4] = 0x0B;//
-
addr.sll_addr[5] = 0x16;//
-
-
bzero (tcpbuff, 32);
-
theheader.s_addr = pIph->source;
-
theheader.d_addr = pIph->dest;
-
theheader.zero = 0;
-
theheader.prototp = 6;
-
theheader.len = htons (20); //the size of TCP head
-
-
memcpy (tcpbuff, &theheader, 12);
-
memcpy (tcpbuff + 12, pTcph, 20);
-
pTcph->chksum = 0;
-
pTcph->chksum = checksum ((unsigned short *) tcpbuff, 32);
-
-
iRet =
-
sendto (sk, buffer, total_len, 0, (struct sockaddr *) &addr,
-
sizeof (struct sockaddr_ll));
-
if (iRet < 0)
-
{
-
strerror (errno);
-
return -1;
-
}
-
-
return 0;
-
}
-
-
//receive tcp packet and display IP Head and TCP Head
-
int
-
recvfrom_packet (int sk, unsigned char buffer[])
-
{
-
int iRet;
-
-
int lenfrom = sizeof (struct sockaddr_in);
-
-
struct sockaddr_in addr;
-
-
struct in_addr in;
-
-
struct IP_Head *pIph;
-
-
struct TCP_Head *pTcph;
-
-
fd_set fdR;
-
-
struct timeval timeout;
-
-
//Set Non-block
-
bzero (&addr, sizeof (struct sockaddr_in));
-
while (1)
-
{
-
iRet =
-
recvfrom (sk, buffer, g_iRecvBufSize, 0,
-
(struct sockaddr *) &addr, &lenfrom);
-
if (iRet < 0)
-
{
-
printf ("error recvfrom\n");
-
return -1;
-
}
-
else
-
{
-
pIph = (struct IP_Head *) buffer;
-
pTcph = (struct TCP_Head *) (buffer + pIph->length * 4);
-
if ((pIph->protocol!=6) || ntohs (pTcph->dest_port) != 0x8888)
-
{
-
continue;
-
}
-
//Display IP Head
-
printf ("Parse IP......\n");
-
printf ("length:%x\n", pIph->length);
-
printf ("version:%x\n", pIph->version);
-
printf ("tos:%x\n", pIph->tos);
-
printf ("total_length:%d\n", ntohs (pIph->total_length));
-
printf ("id:%d\n", ntohs (pIph->id));
-
printf ("flagoff:%x\n", ntohs (pIph->flagoff));
-
printf ("ttl:%d\n", pIph->ttl);
-
printf ("protocol:%d\n", pIph->protocol);
-
printf ("cksum:%x\n", ntohs (pIph->chksum));
-
in.s_addr = pIph->source;
-
printf ("SIP:%s\n", inet_ntoa (in));
-
in.s_addr = pIph->dest;
-
printf ("DIP:%s\n", inet_ntoa (in));
-
-
//Display TCP Head
-
printf ("Parse TCP......\n");
-
printf ("source_port:%d\n", ntohs (pTcph->source_port));
-
printf ("dest_port:%d\n", ntohs (pTcph->dest_port));
-
printf ("seqno:%d\n", ntohl (pTcph->seqno));
-
printf ("ackno:%d\n", ntohl (pTcph->ackno));
-
printf ("len:%d\n", pTcph->len);
-
printf ("fin:%d\n", pTcph->fin);
-
printf ("syn:%d\n", pTcph->syn);
-
printf ("rst:%d\n", pTcph->rst);
-
printf ("psh:%d\n", pTcph->psh);
-
printf ("ack:%d\n", pTcph->ack);
-
printf ("urg:%d\n", pTcph->urg);
-
printf ("winsize:%d\n", ntohs (pTcph->winsize));
-
printf ("urgent:%d\n", ntohs (pTcph->urgent));
-
printf ("\n");
-
-
seqno = ntohl (pTcph->seqno);
-
ackno = ntohl (pTcph->ackno);
-
-
return;
-
}
-
}
-
}
-
-
//Main
-
int
-
main ()
-
{
-
int sk;
-
-
unsigned char buffers[g_iSendBufSize]; //send buffer
-
-
unsigned char bufferr[g_iRecvBufSize]; //receive buffer
-
-
int iRet;
-
-
unsigned long temp;
-
-
-
sk = creat_raw ();
-
if (sk < 0)
-
{
-
printf ("Creat socket error.\n");
-
return -1;
-
}
-
-
-
iRet = set_promisc (sk);
-
if (iRet < 0)
-
{
-
printf ("Set socket promisc error.\n");
-
close (sk);
-
return -1;
-
}
-
-
//the first
-
bzero (buffers, g_iSendBufSize);
-
bzero (bufferr, g_iRecvBufSize);
-
-
fill_iph (buffers);
-
seqno = 0;
-
ackno = 0;
-
fill_tcp (buffers, 0x02);
-
iRet = sendto_packet (sk, buffers);
-
if (iRet < 0)
-
{
-
printf ("Sendto_packet error.\n");
-
close (sk);
-
return -1;
-
}
-
-
iRet = recvfrom_packet (sk, bufferr);
-
if (iRet < 0)
-
{
-
printf ("Recvfrom_packet error.\n");
-
printf ("time is over or error opertion \n");
-
close (sk);
-
return -1;
-
}
-
-
-
//the third
-
bzero (buffers, g_iSendBufSize);
-
bzero (bufferr, g_iRecvBufSize);
-
-
fill_iph (buffers);
-
temp = seqno;
-
seqno = ackno;
-
ackno = temp + 1;
-
fill_tcp (buffers, 0x20);
-
iRet = sendto_packet (sk, buffers);
-
if (iRet < 0)
-
{
-
printf ("Sendto_packet error.\n");
-
close (sk);
-
return -1;
-
}
-
-
close (sk);
-
return 0;
-
}
模拟了一下TCP的三次握手,写得比较粗糙。
主要是创建一个PF_PACKET的套接字,绕过(bypass)系统的协议栈,然后自己构造IP层和TCP层就可以了。
运行之前先执行一下iptables -I INPUT -j DROP把来的数据都扔掉,要不然等服务器发回SYN ACK的时候会被系统的协议栈返回个RST。
可以打开wireshark看效果。
阅读(6611) | 评论(0) | 转发(0) |