Uninformed: Informative Information for the Uninformed

Vol 1» 2005.May


Sniffer Code

To monitor the connection, compile and run this code with a log filename as an argument. This code is written for openbsd and uses it's i386_iopl() function to get access to writing to the ports. You may need to modify it to work on other OSs. Due to file i/o speed limitations, it will log to the file whenever you hit ctrl+c.

/*
 * Synchronous Smart Card Logger v1.0 [synclog.c]
 * by h1kari <h1kari@dachb0den.com>
 */
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <machine/sysarch.h>
#include <i386/pio.h>

#define BASE    0x378
#define DATA    (BASE)
#define STATUS  (BASE + 1)
#define CONTROL (BASE + 2)
#define ECR (BASE + 0x402)
#define BUF_MAX (1024 * 1024 * 8) /* max log size 8mb */

int bufi = 0;
u_char buf[BUF_MAX];
char *logfile;

void
die(int signo)
{
    int i, b;
    FILE *fh;

    /* open logfile and write output */
    if((fh = fopen(logfile, "w")) == NULL) {
        perror("unable to open lpt log file");
        exit(1);
    }
    for(i = 0; i < bufi; i++)
        printbits(fh, buf[i]);

    /* flush and exit out */
    fflush(fh);
    fclose(fh);
    _exit(0);
}

int
printbits(FILE *fh, int b)
{
    fprintf(fh, "%d%d%d%d\n",
        (b >> 7) & 1, (b >> 6) & 1,
        (b >> 5) & 1, (b >> 4) & 1);
}

int
main(int argc, char *argv[])
{
    unsigned char a, b, c;
    unsigned int *ptraddr;
    unsigned int address;

    if(argc < 2) {
        fprintf(stderr, "usage: %s <file>\n", argv[0]);
        exit(1);
    }

    logfile = argv[1];

    /* enable port writing privileges */
    if(i386_iopl(3)) {
        printf("You need to be superuser to use this\n");
        exit(1);
    }

    /* clear status flags */
    outb(STATUS, inb(STATUS) & 0x0f);

    /* set epp mode, just in case */
    outb(ECR, (inb(ECR) & 0x1f) | 0x80);

    /* log to file when we get ctrl+c */
    signal(SIGINT, die);

    /* fetch dataz0r */
    c = 0;
    while(bufi < BUF_MAX) {
        /* select low nibble */
        outb(CONTROL, (inb(CONTROL) & 0xf0) | 0x04);

        /* read low nibble */
        if((b = inb(STATUS)) == c)
            continue;

        buf[bufi++] = c = b; /* save last state bits */
    }

    printf("buffer overflow!\n");
    die(0);
}

It might also help to drop the priority level when running it, if it looks like you're having timing issues:

# nice -n -20 ./synclog file.log