|
|
Creating a sniffer app (Using libpcap)
|
|
|
|
Junior Member
Join Date: Jul 2002
Location: Australia
Status:
Offline
|
|
Hey all,
I'm having trouble with the following program. I want to be able to spy on my net-device (ppp0) and see all incoming and outgoing connection... just the IPs for now. Technically its working though its printing the same destination and source IPs.
Here is the code:
Code:
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
int main() {
pcap_t *handle; /* Session handle */
char *dev; /* The device to sniff on */
char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
struct pcap_pkthdr header; /* The header that pcap gives us */
const u_char *packet; /* The actual packet */
const struct ip *ip; /* The IP header */
int x; /* Loop Counter */
/* Define the device */
dev = "ppp0";
/* Open the session in promiscuous mode */
handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
for (x=0; x<10; x++) {
/* Grab a packet */
packet = pcap_next(handle, &header);
/* Set variables from packet data */
ip = (struct ip*)(packet);
/* Print the packet's info */
printf("------------------------------------------------\n");
printf("Recieved a packet with length of [%d]\n", header.len);
printf("Source IP:\t%s\nDestination IP:\t%s\n", inet_ntoa(ip->ip_src), inet_ntoa(ip->ip_dst) );
}
/* And close the session */
pcap_close(handle);
return(0);
}
I'm running Mac OS 10.3.6 ( Darwin Kernel Version 7.6.0: root:xnu/xnu-517.9.4.obj~1/RELEASE_PPC )
You need to be the root user to run this program.
I'm compiling this the following way:
Code:
cc <filename> -o <program name> -l pcap
|
|
|
|
|
|
|
|
|
Junior Member
Join Date: Jul 2002
Location: Australia
Status:
Offline
|
|
just under a year later and I still haven't figured out the prob... any help would be appreciated
|
|
|
|
|
|
|
|
|
Junior Member
Join Date: Jul 2002
Location: Australia
Status:
Offline
|
|
Now nearly 2 years and no luck :P
Here's my re-write:
Code:
- (void) awakeFromNib
{
/* Authenticate */
[self authenticate];
/* Start a new thread */
[NSThread detachNewThreadSelector:@selector(theSniffer) toTarget:self withObject:nil];
}
- (void) theSniffer
{
/* For the thread's auto release pool */
NSAutoreleasePool *apool=[[NSAutoreleasePool alloc] init];
pcap_t *handle; /* Session handle */
char *dev; /* The device to sniff on */
struct pcap_pkthdr header; /* The header that pcap gives us */
const u_char *packet; /* The actual packet */
char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
struct ip *_ip; /* The IP header */
int x; /* Loop Counter */
NS_DURING
/* Define the device */
dev = "en0";
/* Open the session in promiscuous mode */
handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
for (x=0; x<5; x++) {
/* Grab a packet */
packet = pcap_next(handle, &header);
/* Set variables from packet data */
_ip = (struct ip*)(packet + 14); // The +14 is the size of the ethernet frame
/* Print the packet's info */
[sniffOutput insertText:[NSString stringWithString:@"------------------------------------------------\n"]];
[sniffOutput insertText:[NSString stringWithFormat:@"Recieved a packet with length of [%d]\n", header.len]];
[sniffOutput insertText:[NSString stringWithFormat:@"Source IP:\t%s\nDestination IP:\t%s\n", inet_ntoa(ip->ip_src), inet_ntoa(ip->ip_dst)]];
}
/* And close the session */
pcap_close(handle);
NS_HANDLER
NS_ENDHANDLER
/* Release the autorelease pool */
[apool release];
}
- (void) authenticate
{
// To Do
}
P.S. You'll need to run this program as root or using an Administrator account
|
|
|
|
|
|
|
|
|
Fresh-Faced Recruit
Join Date: Jun 2003
Status:
Offline
|
|
So, I have no access to a ppp device and I don't know objective-c, so I started with the code you posted initially. First, I don't know what is returned from a pcap_next with ppp, but with normal devices you receive back the packet starting at the ethernet header, not the IP header. I don't know if ppp would start you at a ppp header or not, but you need to take this into account. The second thing, and perhaps the more important thing, is your problem with the same source and destination addresses. I played around a bit, got the same results, and thought about it for second. I had no experience with libpcap before, but the calls to inet_ntoa both return a char*. The most common way for something like this to be implemented would be a static char array within inet_ntoa. Thus, each successive call to the function will overwrite the value from the prior call. THus, in your print statement you call it for ip_src which returns a char*, then you call it on ip_dst. This will also return a char*, and in fact it will be the same char* as the first call (because of the use of a static array for storge). Anyway, the solution to this is to make use of each call distinct. I modified your code to work with an ethernet card, but minor modifications should fix the ppp case as well. My changes include included:
1. including the <net/ethernet.h> header
2. adding a variable for the ethernet header struct ether_header
3. appropriately setting the ip header to packet + sizeof(struct ether_header)
4. making two separate calls to printf when calling inet_ntoa
Code:
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <net/ethernet.h>
int main() {
pcap_t *handle; /* Session handle */
char *dev; /* The device to sniff on */
char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
struct pcap_pkthdr header; /* The header that pcap gives us */
const u_char *packet; /* The actual packet */
const struct ip *ip; /* The IP header */
int x; /* Loop Counter */
const struct ether_header *eth; /* The Ethernet Header */
/* Define the device */
dev = "en1";
/* Open the session in promiscuous mode */
handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
for (x=0; x<10; x++) {
/* Grab a packet */
packet = pcap_next(handle, &header);
/* Set variable to ethernet header*/
eth = (struct ether_header*)(packet);
/* Set variables from packet data */
ip = (struct ip*)(packet + sizeof(struct ether_header));
/* Print the packet's info */
printf("------------------------------------------------\n");
printf("Recieved a packet with length of [%d]\n", header.len);
printf("Source IP \t%s\n", inet_ntoa(ip->ip_src));
printf("Dest IP \t%s\n", inet_ntoa(ip->ip_dst));
}
/* And close the session */
pcap_close(handle);
return(0);
}
(
Last edited by ptoomey3; Aug 6, 2006 at 11:45 AM.
)
|
Patrick
|
|
|
|
|
|
|
|
Fresh-Faced Recruit
Join Date: Jun 2003
Status:
Offline
|
|
Ok, so I should have looked at your objective-c version, as it didn't really matter if I knew objetive-c or not to fix the problem. It looks like you already account for the ethernet header with the
Code:
_ip = (struct ip*)(packet + 14); // The +14 is the size of the ethernet frame
I would get rid of the 14 though and use the real struct. Anyway, you can fix your problem with changing
Code:
[sniffOutput insertText:[NSString stringWithFormat:@"Source IP:\t%s\nDestination IP:\t%s\n", inet_ntoa(ip->ip_src), inet_ntoa(ip->ip_dst)]];
to
Code:
[sniffOutput insertText:[NSString stringWithFormat:@"Source IP:\t%s\n", inet_ntoa(ip->ip_src)]];
[sniffOutput insertText:[NSString stringWithFormat:@"Destination IP:\t%s\n, inet_ntoa(ip->ip_dst)]];
|
Patrick
|
|
|
|
|
|
|
|
Mac Elite
Join Date: Jul 2002
Status:
Offline
|
|
I don't think that should be stringWithFormat there but stringWithString.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Forum Rules
|
|
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
|
HTML code is Off
|
|
|
|
|
|
|
|
|
|
|
|