Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   Авторские статьи (https://forum.antichat.xyz/forumdisplay.php?f=31)
-   -   Программирование Raw сокетов на языке Си (https://forum.antichat.xyz/showthread.php?t=18855)

t0x1n 09.05.2006 20:24

Программирование Raw сокетов на языке Си
 
t0x1n
http://www.security.e-gloryon.com
security@shamkir.net

Сокеты бывают трех типов:
SOCK_DGRAM датаграмные сокеты - сокеты которые отсылаются в сеть без запроса на соединение (к ним относятся UDP сокеты)
SOCK_STREAM потоковые сокеты - сокеты требующие соединение (TCP сокеты)
SOCK_RAW сырые сокеты - то что хотим, т.е. пишем сокеты с нуля.
В этой статье нас будут интересовать RAW (сырые) сокеты.

В качестве примера я напишу программу которая посылает обычный UDP пакет.
Если вы пользуетесь операционной системой Linux то код программы нужно компилировать с параметром
-D_BSD_SOURCE т.к. мы будет использовать бсдешные сокеты. Также компилировать и запускать
код программы необходимо с правами root (суперпользователя). Для этого достаточно ввести команду
su root.

Начнем...

Для начала функции нужные нам для работы:

Открытие RAW сокета:
int sock;
sock=socket(PF_INET, SOCKET_RAW, протокол);
Закрытие сокета:
close (sock);
Указание порта отправителя и получателя:
htons(порт);
Указание IP адреса отправителя и получателя:
inet_addr ("IP адрес");

Теперь покажу как устроен заголовок UDP на Си т.к. мы будем писать прогрумму посылающую UDP пакет.
UDP:
uh_sport Порт отправителя
uh_dport Порт получателя
uh_ulen Длина заголовка
uh_sum Контрольная сумма

Сообщения об ошибках:
Чтобы в случае ошибки программа нам выдала сообщение о ней
необходимо написать такую конструкцию:
Код:

int sock;
socket(PF_INET, SOCK_RAW, IPPROTO_UDP); //Создаем сокет
if ((sock)<0) //Если sock<0 тогда
{
perror ("socket"); //выдать сообщение об ошибке
} else { //Если нет то
printf ("socket ok"); //Выдать сообщение socket ok
}

А вот код программы посылающий UDP пакет:
#include
#include
#include

main()
{
    int sock;
    sock = socket(PF_INET, SOCK_RAW, IPPROTO_UDP); //Открываем сокет
    if ((sock)<0){
    perror ("socket");
    } else {
    printf ("socket ok\n");
    }
    char buf[9999];

    /* Структуры*/
    struct sockaddr_in sin;
    struct udphdr *udph=(struct udphdr*)buf;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr("127.0.0.1"); //IP адрес получателя
    /***********/   

    /*UDP заголовок */
    udph->uh_sport=htons(21); //Порт отправителя
    udph->uh_dport=htons(22); //Порт получателя
    udph->uh_ulen=0; //Длина заголовка
    udph->uh_sum=0; //Контрольная сумма
    /***************/
   
    /*Посылаем пакет*/
    if((sendto(sock, &udph, sizeof(udph), 0, (struct sockaddr*)&sin, sizeof(sin)))<0){
    perror ("sendto");
    } else {
    printf ("sendto ok\n");
    }
    close (sock); //Закрываем сокет
}

Теперь компилируем и запускаем код с правами рута. Чтобы вполне убедиться, что программ работает
можете запустить tcpdump и посмотреть отослался пакет или нет.

[t0x1n@t0x1n~]$ su root
[root@t0x1n~]$ gcc -D_BSD_SOURCE udp.c -udp
[root@t0x1n~]$ ./udp
socket ok
sendto ok
[root@t0x1n~]$

Ну вот думаю и все! Желаю удач в сетевом кодинге

nerezus 09.05.2006 21:10

А файрвол пропускает провайдерский?

Xex 09.05.2006 21:36

И чем она отличается от статей типа:"Кодим по сетевому для чайников"?
Это больше похоже на инструкцию про программингу примитивнейшей сетевой проги.

t0x1n 09.05.2006 23:37

Да, это что то вроде инструкции по программированию сырых сокетов для самых маленьких.

t0x1n 09.05.2006 23:39

Должен пропускать

lexa 21.05.2006 07:35

а вот мне это интерестно ! спасибо t0x1n

faust45 10.06.2006 02:42

Ну мне честно говоря премер с ROW Socket совсем не понятен
где ты заголовок IP формируеш ? Вот я нашёл в инете крутой пример лови

Код:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>

unsigned short ip_cksum(unsigned char * buff, int len)
{
        unsigned long sum = 0;
        if (len > 3)
        {
                __asm__("clc\n"
                "1:\t"
                "lodsl\n\t"
                "adcl %%eax, %%ebx\n\t"
                "loop 1b\n\t"
                "adcl $0, %%ebx\n\t"
                "movl %%ebx, %%eax\n\t"
                "shrl $16, %%eax\n\t"
                "addw %%ax, %%bx\n\t"
                "adcw $0, %%bx"
                : "=b" (sum) , "=S" (buff)
                : "0" (sum), "c" (len >> 2) ,"1" (buff)
                : "ax", "cx", "si", "bx" );
        }
        if (len & 2)
        {
                __asm__("lodsw\n\t"
                "addw %%ax, %%bx\n\t"
                "adcw $0, %%bx"
                : "=b" (sum), "=S" (buff)
                : "0" (sum), "1" (buff)
                : "bx", "ax", "si");
        }
        if (len & 1)
        {
                __asm__("lodsb\n\t"
                "movb $0, %%ah\n\t"
                "addw %%ax, %%bx\n\t"
                "adcw $0, %%bx"
                : "=b" (sum), "=S" (buff)
                : "0" (sum), "1" (buff)
                : "bx", "ax", "si");
        }
        sum =~sum;
        return(sum & 0xffff);
}

unsigned short tcp_check(struct tcphdr *th, int len,
          unsigned long saddr, unsigned long daddr)
{
        unsigned long sum;
        __asm__("
            addl %%ecx, %%ebx
            adcl %%edx, %%ebx
            adcl $0, %%ebx
            "
        : "=b"(sum)
        : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_TCP*256)
        : "bx", "cx", "dx" );
        __asm__("
            movl %%ecx, %%edx
            cld
            cmpl $32, %%ecx
            jb 2f
            shrl $5, %%ecx
            clc
1:          lodsl
            adcl %%eax, %%ebx
            lodsl
            adcl %%eax, %%ebx
            lodsl
            adcl %%eax, %%ebx
            lodsl
            adcl %%eax, %%ebx
            lodsl
            adcl %%eax, %%ebx
            lodsl
            adcl %%eax, %%ebx
            lodsl
            adcl %%eax, %%ebx
            lodsl
            adcl %%eax, %%ebx
            loop 1b
            adcl $0, %%ebx
            movl %%edx, %%ecx
2:          andl $28, %%ecx
            je 4f
            shrl $2, %%ecx
            clc
3:          lodsl
            adcl %%eax, %%ebx
            loop 3b
            adcl $0, %%ebx
4:          movl $0, %%eax
            testw $2, %%dx
            je 5f
            lodsw
            addl %%eax, %%ebx
            adcl $0, %%ebx
            movw $0, %%ax
5:          test $1, %%edx
            je 6f
            lodsb
            addl %%eax, %%ebx
            adcl $0, %%ebx
6:          movl %%ebx, %%eax
            shrl $16, %%eax
            addw %%ax, %%bx
            adcw $0, %%bx
            "
        : "=b"(sum)
        : "0"(sum), "c"(len), "S"(th)
        : "ax", "bx", "cx", "dx", "si" );

        /* We only want the bottom 16 bits, but we never cleared the top 16. */

        return((~sum) & 0xffff);
}

void resolve_address(struct sockaddr *addr, char *hostname, u_short port) {
struct sockaddr_in *address;
struct hostent *host;

address = (struct sockaddr_in *)addr;
(void) bzero((char *)address, sizeof(struct sockaddr_in));
address->sin_family = AF_INET;
address->sin_port = htons(port);
address->sin_addr.s_addr = inet_addr(hostname);
if ((int)address->sin_addr.s_addr == -1) {
  host = gethostbyname(hostname);
  if (host) {
  bcopy( host->h_addr, (char *)&address->sin_addr, host->h_length);
  }
  else {
  puts("Couldn't resolve address!!!");
  exit(-1);
  }
 }
}

char *create_ip(u_long source, u_long dest, u_char protocol, u_char ttl,
        u_short id, char *data, int data_len)
{
 char *ip_datagram;
 struct iphdr *ip_header;
 ip_datagram = malloc(sizeof(struct iphdr) + data_len);
 ip_header = ip_datagram;
 ip_header->version  = 4;
 ip_header->tos      = 0;
 ip_header->frag_off  = 0;
 ip_header->check    = 0;
 ip_header->saddr    = source;
 ip_header->daddr    = dest;
 ip_header->protocol  = protocol;
 ip_header->ttl      = ttl;
 ip_header->id        = htons(id);
 ip_header->ihl      = 5;
 ip_header->tot_len  = htons(sizeof(struct iphdr) + data_len);
 ip_header->check = htons(ip_cksum(ip_datagram,sizeof(struct iphdr)));
 bcopy(data,ip_datagram+sizeof(struct iphdr),data_len);
 return ip_datagram;
}

char *create_tcp(u_long source, u_long dest, u_short sport, u_short dport,
        u_long seqnum, u_long acknum, u_char flags, char *data, int datalen)
{
 char *wewt;
 struct tcphdr *tcp_header;
 wewt = malloc(sizeof(struct tcphdr) + datalen);
 tcp_header = wewt;
 tcp_header->th_sport = sport;
 tcp_header->th_dport = dport;
 tcp_header->th_seq  = seqnum;
 tcp_header->th_ack  = acknum;
 tcp_header->th_flags = flags;
 tcp_header->th_sum  = 0;
 tcp_header->th_sum = htons(tcp_check(tcp_header, sizeof(struct tcphdr),
    source, dest));
 bcopy(data,wewt+sizeof(struct tcphdr),datalen);
 return wewt;
}

void sendpack(char *fromhost, int fromport, char *tohost, int toport) {
 char *packet;
 char *tcppacket;
 char *sendme;
 static struct sockaddr_in local, remote;
 static int sock = 0;
 if (!sock) {
  resolve_address((struct sockaddr *)&local, fromhost, fromport);
  resolve_address((struct sockaddr *)&remote, tohost, toport);
  sock = socket(AF_INET, SOCK_RAW, 255);
  if (sock == -1) { perror("Getting raw socket"); exit(-1); }
  }
  tcppacket = create_tcp(&local.sin_addr, &remote.sin_addr,
        local.sin_port, remote.sin_port, 795930600, 0, TH_SYN,
        NULL, 0);
  packet = create_ip(&local.sin_addr, &remote.sin_addr,
        6, 24, 4, NULL, 0);
  sendme = (struct iphdr *)packet;
  bcopy(tcppacket, sendme+sizeof(struct iphdr), sizeof(tcppacket));
  printf("the ip header is %d bytes long.\n", sizeof(struct iphdr));
  printf("the tcp header is %d bytes long.\n", sizeof(struct tcphdr));
  printf("the ip packet is %d bytes long.\n", sizeof(packet));
  printf("the tcp packet is %d bytes long.\n", sizeof(tcppacket));
  printf("the final packet is %d bytes long.\n", sizeof(sendme));
  {
  int result;

  result = sendto(sock, packet, sizeof(packet), 0,
        (struct sockaddr *)&remote, sizeof(remote));
  if (result != sizeof(packet)) { perror("sending packet"); }
  }
}

main(int argc, char **argv) {
if (argc!=5) {
 printf("usage: %s <from host> <from port> <to host> <to port>\n", argv[0]);
 exit(-1);
}
 printf("forging packet from %s.%d to %s.%d\n", argv[1], atoi(argv[2]),
        argv[3], atoi(argv[4]));
 sendpack(argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));
}



Время: 10:40