t0x1n http://www.security.e-gloryon.com [email protected] Сокеты бывают трех типов: 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 Контрольная сумма Сообщения об ошибках: Чтобы в случае ошибки программа нам выдала сообщение о ней необходимо написать такую конструкцию: Code: 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~]$ Ну вот думаю и все! Желаю удач в сетевом кодинге
И чем она отличается от статей типа:"Кодим по сетевому для чайников"? Это больше похоже на инструкцию про программингу примитивнейшей сетевой проги.
Ну мне честно говоря премер с ROW Socket совсем не понятен где ты заголовок IP формируеш ? Вот я нашёл в инете крутой пример лови Code: #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])); }