Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей.
Здесь обсуждаются безопасность, программирование, технологии и многое другое.
Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
 |
Программирование Raw сокетов на языке Си |

09.05.2006, 20:24
|
|
Новичок
Регистрация: 08.05.2006
Сообщений: 6
Провел на форуме: 13259
Репутация:
1
|
|
Программирование 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~]$
Ну вот думаю и все! Желаю удач в сетевом кодинге
Последний раз редактировалось Green_Bear; 10.06.2006 в 10:14..
Причина: тег код для придурков создали
|
|
|

09.05.2006, 21:10
|
|
Pagan Heart
Регистрация: 12.08.2004
Сообщений: 3,791
Провел на форуме: 6490435
Репутация:
2290
|
|
А файрвол пропускает провайдерский?
|
|
|

09.05.2006, 21:36
|
|
Banned
Регистрация: 10.07.2005
Сообщений: 224
Провел на форуме: 1062041
Репутация:
50
|
|
И чем она отличается от статей типа:"Кодим по сетевому для чайников"?
Это больше похоже на инструкцию про программингу примитивнейшей сетевой проги.
|
|
|

09.05.2006, 23:37
|
|
Новичок
Регистрация: 08.05.2006
Сообщений: 6
Провел на форуме: 13259
Репутация:
1
|
|
Да, это что то вроде инструкции по программированию сырых сокетов для самых маленьких.
|
|
|

09.05.2006, 23:39
|
|
Новичок
Регистрация: 08.05.2006
Сообщений: 6
Провел на форуме: 13259
Репутация:
1
|
|
Должен пропускать
|
|
|

21.05.2006, 07:35
|
|
Участник форума
Регистрация: 14.01.2005
Сообщений: 169
Провел на форуме: 427901
Репутация:
23
|
|
а вот мне это интерестно ! спасибо t0x1n
|
|
|

10.06.2006, 02:42
|
|
Познающий
Регистрация: 02.03.2006
Сообщений: 43
Провел на форуме: 132146
Репутация:
0
|
|
Ну мне честно говоря премер с 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]));
}
Последний раз редактировалось Green_Bear; 10.06.2006 в 10:13..
Причина: тег код для придурков создали
|
|
|
|
 |
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|