Arwa
Arwa

Reputation: 23

Packet sniffer in C for all VM

I have 3 Ubuntu VM that represent client/server/attacker. I created an application that connect client and server in TCP and I have a packet sniffer in the attacker machine. However, the code only manage to sniff packet going from the attacker machine only, it can't detect the client/server connection. I tried the Wireshark, and it captured the connection between them. What do you think the problem is?

I'm using Virtual Box and the network is bridged. this is the code

#include <pcap.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>


pcap_t* handle; 
int linkhdrsize; 
char filter[256];

/* - Packet Capture function - */
pcap_t* packet_capture(char* device, const char* bpfstr)
{
char errorbuffer[PCAP_ERRBUF_SIZE];
pcap_t* handle;
uint32_t source_ip, netmask;
struct bpf_program bpf;

if((handle=pcap_open_live(device,BUFSIZ,1,0,errorbuffer)) == NULL){
printf("pcap_open_live(): %s\n", errorbuffer);
return NULL;
}

if(pcap_lookupnet(device, &source_ip, &netmask, errorbuffer) <0)
{
printf("pcap_lookupnet: %s\n", errorbuffer);
return NULL;
}

if (pcap_compile(handle, &bpf, (char*)filter, 0, netmask))
{
printf("pcap_compile(): %s\n", pcap_geterr(handle));
return NULL;
}
if (pcap_setfilter(handle, &bpf) < 0)
{
printf("pcap_setfilter(): %s\n", pcap_geterr(handle));
return NULL;
}

return handle;
}

/* - Capture Loop function - */

void capture_loop(pcap_t* handle, pcap_handler func)
{
int linktype;
if((linktype = pcap_datalink(handle))<0)
{
printf("pcap_datalink(): %s\n", pcap_geterr(handle));
}
if(linktype==DLT_EN10MB)
linkhdrsize=14;
else
printf("Unsupported datalink (%d)\n", linktype);
if (pcap_loop(handle, 0, func, 0) < 0)
printf("pcap_loop failed: %s\n", pcap_geterr(handle));
}

/* - Parsing function - */

void parse_packet(u_char *user, struct pcap_pkthdr *packethdr, u_char *packetptr)
{
struct ip* ip_header;
struct tcphdr* tcp_header;
char ip_header_info[256], source_ip[256], destination_ip[256];
unsigned short id, seq;
packetptr += linkhdrsize;
ip_header = (struct ip*)packetptr;
strcpy(source_ip, inet_ntoa(ip_header->ip_src));
strcpy(destination_ip, inet_ntoa(ip_header->ip_dst));
packetptr += 4*ip_header->ip_hl;
if((ip_header->ip_p)==IPPROTO_TCP)
    {
        tcp_header = (struct tcphdr*)packetptr;
        printf("TCP  %s:%d -> %s:%d\n", source_ip, ntohs(tcp_header->source),
               destination_ip, ntohs(tcp_header->dest));
        printf("%c%c%c%c%c%c Seq: 0x%x Ack: 0x%x Win: 0x%x TcpLen: %d\n",
               (tcp_header->urg ? 'U' : '*'),
               (tcp_header->ack ? 'A' : '*'),
               (tcp_header->psh ? 'P' : '*'),
               (tcp_header->rst ? 'R' : '*'),
               (tcp_header->syn ? 'S' : '*'),
               (tcp_header->fin ? 'F' : '*'),
               ntohl(tcp_header->seq), ntohl(tcp_header->ack_seq),
               ntohs(tcp_header->window), 4*tcp_header->doff);
}
printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n");
}
void bailout(int signo)
{
    struct pcap_stat stats;

    if (pcap_stats(handle, &stats) >= 0)
    {
        printf("%d packets received\n", stats.ps_recv);
        printf("%d packets dropped\n\n", stats.ps_drop);
    }
    pcap_close(handle);
    exit(0);
}
/* - Main function - */
int main()
{
char interface[256]="eth0"; 
char filter[256]="tcp"; 
int packets=0;

if(( handle=packet_capture(interface,filter)) != NULL)
{
signal(SIGINT, bailout);
signal(SIGTERM, bailout);
signal(SIGQUIT, bailout);
capture_loop(handle,(pcap_handler)parse_packet);
bailout(0);
}
exit(0);
}

Upvotes: 2

Views: 1315

Answers (1)

Iansus
Iansus

Reputation: 198

You are on an emulated LAN. The behavior will change depending on whether the VM bridge architecture emulates a switch or a hub:

  • The hub will send the recived packets to all output ports
  • The switch will target the MAC address associated with the target's IP address referred in its ARP table

Regarding the "promiscuous mode" mentioned in the comments: AFAIK, it only enables the network card to look at the packets it receives (on the physical link) even if they are not addressed to it (in the cas of a hub for example, where it receives packets sent to a different MAC address).

In your case, the network card will only see :

  • packets address to its MAC address
  • packets sent from the network card to any recipient
  • packets that have been sent to broadcast (MAC/IP)

To enable your attacker VM to see ALL the packets, you must either :

  • Use it as the default gateway in routing mode (will see all the packets)
  • Spoof each other host's MAC address (like Cain does)

Basically, you are trying to write a light-Wireshark/TCPdump in C, and if you take a look at their capabilities, you'll see they won't do more than what I described above.

Upvotes: 1

Related Questions