Hello, I am an Engineering Manager at Facebook with 13+ years in Ad Technology, Natural Language Processing and Data mining. (Learn More)
by Pravin Paratey

Yahoo Messenger Packet Analyser

/img/posts/ypkt.png

Today, we’ll take a look at writing a Yahoo Packet Analyser. Yahoo changes its YMSG protocol (used on Yahoo Messenger) very often. Developers of alternative Yahoo Messengers have to scrabble around everytime this happens. This tool will show you the raw YMSG packets going in and coming out of your machine. Developers and non-developers can use this to understand the YMSG protocol better.

This code has been tested on ubuntu linux with gcc. It should work on all flavors of *nix. You’ll need libpcap and libpcap-dev. You will have to run Yahoo Messenger or its alternatives available to view YMSG packets.

The idea is to capture all packets on an interface (ex. ethernet card) and pick the YMSG packets and dump them on the screen in hex.

The source code is given below. It is under GPL. It’s fairly commented and you shouldn’t have trouble understanding what’s going on. Copy-paste the code to ypkt.c. To compile and run (as root):

$ gcc ypkt.c -lpcap -o ypkt && ./ypkt
/* Yahoo Packet Analyser
 * by Pravin Paratey (January 12, 2005)
 * pravinp [at] gmail [dot] com
**/

#include <stdio.h>
#include <pcap.h>
#include <sys/socket.h>

char *InitCapture();
void DoCapture(char *dev);
void ParsePkts(pcap_t *fp);

int main(int argc, char **argv)
{
    char *dev;
    fprintf(stdout,"\t\t===============================\n");
    fprintf(stdout,"\t\t  Yahoo Packet Analyser v0.1\n");
    fprintf(stdout,"\t\t       by Pravin Paratey\n");
    fprintf(stdout,"\t\t  (pravinp[at]gmail[dot]com)\n");
    fprintf(stdout,"\t\t  http://insanitybegins.com/\n");
    fprintf(stdout,"\t\t===============================\n");

    dev = InitCapture();
    if(dev)
        DoCapture(dev);

    return 0;
}

char *InitCapture()
{
    pcap_if_t *alldevs, *d;
    pcap_t *fp;
    char errbuf[PCAP_ERRBUF_SIZE];
    u_int inum, i=0;

    // Find all interfaces
    if(pcap_findalldevs(&alldevs, errbuf) == -1) {
        fprintf(stderr,"*** Error in pcap_findalldevs: %s\n", errbuf);
        return 0;
    }

    // Print the list of interfaces found
    for (d=alldevs; d; d=d->next) {
        printf("%d. %s",++i,d->name);
        if (d->description)
            printf(" (%s)\n", d->description);
        else
            printf(" (No description available)\n");
    }

    if(i==0) {
        fprintf(stderr,"*** No interfaces found! Exiting ...\n");
        return 0;
    }

    if (i > 1) {
        printf("Enter the interface number (1-%d):",i);
        scanf("%d", &inum);
        if(inum < 1 || inum > i) {
            printf("\nInterface number out of range.\n");
            // Free the device list
            pcap_freealldevs(alldevs);
            return 0;
        }
    }
    else {
        inum = 1;
    }

    // Jump to the selected adapter
    for(d=alldevs, i=0; i<inum-1; d=d->next, i++)
        ;
    return d->name;
}

void DoCapture(char *dev)
{
    pcap_t *fp;
    struct bpf_program fcode;
    char errbuf[PCAP_ERRBUF_SIZE];

    // Open the device
    if ((fp = pcap_open_live(dev, // device to open
            65536, // grants the whole packet will be captured
            0, // view packets of this machine
            1000, // read timeout
            errbuf)) == NULL) {
        fprintf(stderr,"*** pcap_open_live(): %s\n", errbuf);
        return;
    }

    // Set filter to capture TCP packets only
    if (pcap_compile(fp, &fcode, "tcp", 1, 0xffffff) < 0) {
        fprintf(stderr,"*** Unable to compile packet filter\n");
        return;
    }

    if (pcap_setfilter(fp,&fcode) < 0) {
        fprintf(stderr,"*** Unable to set packet filter\n");
        return;
    }

    // Successful, now we sit back and listen
    fprintf(stdout, "\n### Listening on adaptor\n### To quit, press Ctrl+C\n\n");

    ParsePkts(fp);
}


void ParsePkts(pcap_t *fp)
{
    int res;
    const u_char *pkt_data;
    struct pcap_pkthdr *header;
    u_int i, j; u_char c;

    // While packets are present in the interface, capture them
    while((res = pcap_next_ex(fp, &header, &pkt_data)) >= 0) {
        // If this is a Yahoo YMSG packet
        if(pkt_data[66] == 'Y' && pkt_data[67] == 'M' &&
            pkt_data[68] == 'S' && pkt_data[69] == 'G') {
            // Dump contents to screen
            for(i=66; i < header->caplen; i=i+16) {
                for (j=0;j<16 && (i+j < header->caplen);j++) {
                    fprintf(stdout, "%2.2x ",pkt_data[i+j]);
                    if(j == 7) printf("    ");
                }

                fprintf(stdout, "\t");

                for (j=0;j<15 && (i+j < header->caplen);j++) {
                    c = pkt_data[i+j];
                    fprintf(stdout, "%c", (c > 32 && c < 127) ? c : '.');
                }

                fprintf(stdout, "\n");
            }
            fprintf(stdout,"\n");
        }
    }
}

The next version will have color coding to denote diffents parts of the packet. A Microsoft Windows implementation with a GUI can be viewed on Github