raw-socket-programming No. 1
This paper is only to get to know and to understand "high security" networking. This paper is for people, who are able to write simple sockets. Raw-sockets are socket, where you get the raw packet. That means you must fill or read each byte of a packet. In this paper I will explain some basic raw-socket-programming.
Other papers about raw-socket-programming are following. In this we lern how to write the IP-heder, ICMP-header and how to get the checksum.
Main :
First we create a raw-socket, with the socket() function.
If you don't know what the socket function is, that's wasting your time.
We use the socket() function with this args :
socket( AF_INET, SOCK_RAW, IPPROTO_RAW);
To the AF_INET i don't say anything.
The SOCK_RAW is simple for RAW-sockets.
THE IPPROTO_RAW is that we will get a
RAW-socket.
Because it give thinks like IPPROTO_TCP, IPPROTO_UDP,
IPPROT_ICMP ......
Of course you must be root to create a RAW-socket.
So now we need a structure for the information for
the IP-protocol :
struct iphadr theripheader;
Here is the full structure :
struct iphdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ihl:4;
unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int version:4;
unsigned int ihl:4;
#else
# error "Please fix "
#endif
u_int8_t tos;
u_int16_t tot_len;
u_int16_t id;
u_int16_t frag_off;
u_int8_t ttl;
u_int8_t protocol;
u_int16_t check;
u_int32_t saddr;
u_int32_t daddr;
/*The options start here. */
};
Here I describe the variables of the iphdr structure :
ihl = header length
version = IP-version
tos = Type of Service
tot_len = total length
frag_of = fragmentation
ttl = TimeToLive
protocol= protocol
check = checksum
saddr = source-addr
daddr = destination-addr
Now the ICMP-header :
struct icmphdr theicmpheader;
Here is the full structure of the ICMP-header
struct icmphdr
{
u_int8_t type; /* message type */
u_int8_t code; /* type sub-code */
u_int16_t checksum;
union
{
struct
{
u_int16_t id;
u_int16_t sequence;
} echo; /* echo datagram */
u_int32_t gateway; /* gateway address */
struct
{
u_int16_t __unused;
u_int16_t mtu;
} frag; /* path mtu discovery */
} un;
};
Now I describe the variables of the ICMP-header,
only the variables we need :
type = the message-type
code = the sub-code
id = the identification
sequence = the sequence-number
Now I give you a function, which calculates the checksum.
You find this function very often in RAW-sockets, but the
function isn't in a *.h of your system. I don't who wrote
this function.
unsigned short in_checksum(unsigned short *addr,int len )
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned 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);
}
So I hope you know the XtoX() functions like ntohs(),ntohl(),
htons()..... ,because I won't explain them..
Now I had written a little pinger for you, there you can see
how to use the functions and structures now.
Source :
/* ring (little pinger) */
/* by rooty */
/* rooty@netflood.net */
/* www.netflood.net */
/* We won't waste your time */
/* g++ -oring ring.c */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
unsigned short in_checksum(unsigned short*,int );
void main(int argc,char **argv)
{
int sockfd;
int datalen, packlen, targetlen;
datalen = 0;
char *srcip;
char *destip;
char readbuffer[1500];
char sendbuffer[1500];
struct sockaddr_in strusrcip,strudestip;
struct iphdr *ipheader;
struct icmp *icmpheader;
if(argc != 3)
{
coutihl = 5;
ipheader->version = 4;
ipheader->tos = 0;
ipheader->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmp) +
datalen);
ipheader->id = 0;
ipheader->frag_off = 0;
ipheader->ttl = 200;
ipheader->protocol = IPPROTO_ICMP;
ipheader->check = in_checksum( (u_short *)ipheader, sizeof(struct iphdr));
ipheader->saddr = strusrcip.sin_addr.s_addr;
ipheader->daddr = strudestip.sin_addr.s_addr;
icmpheader->icmp_type = ICMP_ECHO;
icmpheader->icmp_code = 0;
icmpheader->icmp_seq = random();
icmpheader->icmp_cksum = in_checksum( (u_short *)icmpheader,
sizeof(struct icmp) + datalen);
sendto(sockfd,sendbuffer,sizeof(struct iphdr) + sizeof(struct icmphdr)
+ datalen,0,(struct sockaddr *)&strudestip,sizeof(struct sockaddr));
return 0;
}
unsigned short in_checksum(unsigned short *addr,int len )
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned 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);
}