Автор Гілка: сніффер  (Прочитано 2870 раз)

Відсутній AliceStein

  • Новачок
  • *
  • дописів: 8
  • Карма: +0/-0
сніффер
« : 2009-03-03 17:12:13 »
Пишу сніффер приймаеє тільки пакети адресовані самому хосту на якому запускаю, знаю що для цього в Windows є флаг SIO_RCVALL через ioctl дозволяе приймати всі пакети ioctl(ss,SIO_RCVALL,&flg); в Linux такого немає. Як це зробити в Linux?
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>

typedef struct IPHeader {
char iph_verlen;
char iph_tos;
short iph_length;
short iph_id;
short iph_offset;
char iph_ttl;
char iph_protocol;
short iph_xsum;
long iph_src;
long iph_dest;
}IPHeader;

int read_sock(char *buf,int sock)
{
int n=0;
if(buf!=NULL){
   n=recv(sock,buf,100,0);
};
return n;
};
int ac;
char **av;
void *pthr1(void *);
static char lhost[16];
static char buff[65536];
struct hostent *ht;
struct sockaddr_in sa;
int ss=0;
int main(int argc,char *argv[])
{
ac=argc;
av=argv;
if(argc<3)
{
printf("May be 3 arguments in command line\n");
exit(0);
};
gethostname(lhost,sizeof(lhost));
ht=gethostbyname(lhost);
sa.sin_family=AF_INET;
sa.sin_addr.s_addr= ((struct in_addr*)ht->h_addr_list[0])->s_addr;
ss=socket(AF_INET,SOCK_RAW,IPPROTO_TCP);
if(ss==-1){
perror("socket");
exit(0);
};
bind(ss,(struct sockaddr*)&sa,sizeof(sa));
bool flg=true;
int ff=open("snif.txt",O_RDWR | O_CREAT);
close(ff);
//ioctl(ss,SIO_RCVALL,&flg);
pthread_attr_t pa1;
pthread_t pt1;
pthread_attr_init(&pa1);
int pr=pthread_create(&pt1,&pa1,pthr1,NULL);
if(pr==0)
{
printf("Snifer thread 1\n");
} else
{
perror("thread 1");
exit(1);
};
for(;;)
{};

return 0;
};

void *pthr1(void *)
{
for(;;)
{
int i=0;
 if (recv(ss, buff, sizeof(buff), 0) >= sizeof(IPHeader)) {
IPHeader* hdr = (IPHeader*)buff;
long size=(hdr->iph_length << 8) + (hdr->iph_length >> 8);
if(size>=60)
{
int fd=open("snif.txt",O_RDWR);
if(fd==-1){
perror("open");
exit(0);
} else {
lseek(fd,0,SEEK_END);
write(fd, "--Packet begin--\r\n", 18);
struct in_addr ia;
ia.s_addr=hdr->iph_dest;
char *ptarip=inet_ntoa(ia);
write(fd, "To: ", 4);
write(fd, ptarip,strlen(ptarip));
write(fd, "\r\n", 2);
static char ssize[16];
sprintf(ssize,"%d",size);
write(fd,"Packet length: ",15);
write(fd,ssize,strlen(ssize));
write(fd,&buff[sizeof(IPHeader)],size);
};

};

};
};
};

Знаю що сніфер можна написати з використанням libpcap, але хочу зробити через сокети.

Відсутній borman

  • Графоман
  • ****
  • дописів: 416
  • Карма: +0/-0
  • Debianizer
Re: сніффер
« Відповідей #1 : 2009-03-03 23:04:30 »
Потрібно перевести мережевий інтерфейс в спеціальний режим - promisc mode. Тоді мережева карта будет приймати всі пакети, а не лише призначені хосту.
dd if=/dev/zero of=/dev/null

Відсутній borman

  • Графоман
  • ****
  • дописів: 416
  • Карма: +0/-0
  • Debianizer
Re: сніффер
« Відповідей #2 : 2009-03-03 23:13:48 »
Додаткова література. Більше теорії, практичних порад небагато. Але зможе дати уявлення про питання в цілому та вказати напрямок розвитку. А далі досконалості допоможе досягти великий та жахливий google.

(рос.):
http://ru.wikipedia.org/wiki/Promiscuous_mode
http://www.xakep.ru/magazine/xs/047/028/1.asp
dd if=/dev/zero of=/dev/null

Відсутній AliceStein

  • Новачок
  • *
  • дописів: 8
  • Карма: +0/-0
Re: сніффер
« Відповідей #3 : 2009-03-04 00:36:36 »
Зрозумів у мене все неправильно. Знайшов цікаву статью яка допоможе мені написати сніффер там використовуются пакетні сокети PF_PACKET які дозволяють приймати та передавати пакети на рівні драйвера man 7 packet. http://x-news.ru/index.php?option=com_content&task=view&id=876&Itemid=70
« Змінено: 2009-03-04 00:37:28 від AliceStein »

Відсутній AliceStein

  • Новачок
  • *
  • дописів: 8
  • Карма: +0/-0
Re: сніффер
« Відповідей #4 : 2009-03-08 20:31:09 »
Маю нічибто нормальний сніффер створював по шаблону з http://x-news.ru/index.php?option=com_content&task=view&id=876&Itemid=2
При намаганні прийняти адрессу хоста на якому запущений видає ioctl: Cannot assign requested address ось функція в якій є помилка
int getifconfig (struct ifreq *ifr, char *intf, struct ifparam *ifp)
{
int fd; //- дескриптор сокета

//Создадим сокет:
if (( fd= socket (AF_INET, SOCK_DGRAM, 0)) <0 ) {
perror ( "socket" );
return ( - 1 );
}

//Скопируем имя интерфейса в поле ifr_name структуры ifr:
sprintf (ifr->ifr_name, "%s", intf);
struct sockaddr_in s;
char iphost[25];
memset(iphost,0x20,sizeof(iphost));
//Получим IP адрес интерфейса:
if (ioctl (fd, SIOCGIFADDR, ifr) <0 ) {
printf("Can't get ip address\n");
perror ("ioctl");
gethostname(iphost,sizeof(iphost));
//ifp.ip=inet_addr(iphost);
}
memset(&s, 0, sizeof (struct sockaddr_in));
memcpy(&s, &ifr->ifr_addr, sizeof(struct sockaddr));
memcpy(&ifp->ip, &s.sin_addr.s_addr, sizeof (u_long));

//Получим маску подсети:
if (ioctl (fd, SIOCGIFNETMASK, ifr) <0 ) {
perror ("ioctl");
return (-1);
}
memset(&s, 0, sizeof (struct sockaddr_in));
memcpy(&s, &ifr->ifr_netmask, sizeof (struct sockaddr));
memcpy(&ifp->mask, &s.sin_addr.s_addr, sizeof (u_long));

//Получим номер подсети:
ifp->subnet = check_subnet(ifp->mask, ifp->ip);

//Получим размер MTU:
if (ioctl (fd, SIOCGIFMTU, ifr) <0 ) {
perror ("ioctl");
return (-1);
}
ifp -> mtu = ifr -> ifr_mtu;

//Получим индекс (номер) интерфейса:
if ( ioctl (fd, SIOCGIFINDEX, ifr) <0 ) {
perror ("ioctl");
return (-1);
}
ifp -> index = ifr -> ifr_ifindex;

//Переведем интерфейс в неразборчивый режим. Для этого получим значение флагов интерфейса:
if ( ioctl (fd, SIOCGIFFLAGS, ifr) <0 ) {
perror ("ioctl");
close (fd);
return (-1);
}

//Установим флаг неразборчивого режима:
ifr -> ifr_flags |= IFF_PROMISC;

//Установим новое значение флагов интерфейса:
if ( ioctl (fd, SIOCSIFFLAGS, ifr) <0 ) {
perror ("ioctl");
close (fd);
return (-1);
}

return 1;
}
Отримую всі параметри через ioctl. В чому може бути помилка?
Але ж компілится без помилок.
« Змінено: 2009-03-08 20:35:29 від AliceStein »

Відсутній borman

  • Графоман
  • ****
  • дописів: 416
  • Карма: +0/-0
  • Debianizer
Re: сніффер
« Відповідей #5 : 2009-03-09 00:49:49 »
Зазвичай така помилка видається, коли вказаної ip-адреси на інтерфейсі немає. Тому серед загальних порад можу лише рекомендувати уважно перевірити, чи не поплутали ви інтерфейси, та звернути увагу - можливо, маніпуляції з ip-адресою потрібно проводити в специфічній формі, тобто спочатку здійснити якесь перетворення. Завтра зможу поколупати детальніше.

Ну й побажаю вставити побільше printf на різних етапах - для пошуку бліх дуже допомагає.
dd if=/dev/zero of=/dev/null