PoC Software for Magnetic Stripe Processing of Credit/Debit Cards for Snort SDF
Bill Parker <[email protected]>
| Newsgroups | gmane.comp.security.ids.snort.devel |
|---|---|
| Message-ID | <CAFrbyQw1NZ0E9OLac6_AuFgbkkPZg_4JbVJj-RFRtOM_iO8x3Q@mail.gmail.com> |
Hello All, This is a very rough output for processing of Credit/Debit Card Magnetic Stripe data (this is Track 1, Format B), and while it is still a work in progress, it does take the data supplied and breaks it down into the following fields: Account Number (max of 19 characters): Card Holder Name (max of 26 characters): Expiration Date (in MMYY format): Service Code (3 chars): Discretionary data (1 to 4 chars) The Longitudinal redundancy check value (3 chars) Here is the output from the program below: Enter Line for Mag Stripe Testing: %b1234567890123456789^AbCdEfGhIjKlmnopQRStuvwxyz^11171270874?LRC The Line Entered was: %b1234567890123456789^AbCdEfGhIjKlmnopQRStuvwxyz^11171270874?LRC Length of Buffer entered is: 65 Buffer after conversion is: %B1234567890123456789^ABCDEFGHIJKLMNOPQRSTUVWXYZ^11171270874?LRC SUCCESS (SO FAR): Starting sentinel is '%' Ending sentinel is '?' Format Code is 'B' The Account Number is: 1234567890123456789 The Card Holder Name is: ABCDEFGHIJKLMNOPQRSTUVWXYZ Card Holder Expiration Date is: 1117 Card Holder Service Code is: 127 Card Holder Discretionary data is: 0874 The Longitudinal redundancy check value is: LRC Process returned 0 (0x0) execution time : 4.500 s Press any key to continue. This is also filed at the following URL: https://bugzilla.clamav.net/show_bug.cgi?id=11341 The source code is a(n) attachment. It will be modified to check track 2, and also add checking for valid service codes, etc. This is still a work in progress. Bill Parker (wp02855 at gmail dot com) ------------------------------------------------------------------------------ _______________________________________________ Snort-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/snort-devel Archive: http://sourceforge.net/mailarchive/forum.php?forum_name=snort-devel Please visit http://blog.snort.org for the latest news about Snort!
main.c
(text/x-csrc, 6.4 KB)
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
/* function prototypes */
void StringToLower(char *);
void StringToUpper(char *);
void ReverseString(char *);
void StringToLower(char *s)
{
while (*s) {
*s = tolower((unsigned char)*s);
++s;
}
}
void StringToUpper(char *s)
{
while (*s) {
*s = toupper((unsigned char)*s);
++s;
}
}
void ReverseString(char *s)
{
size_t len = strlen(s);
size_t i, j;
if (len > 0)
for (i = 0, j = len - 1; i < j; i++, j--)
s[i] ^= s[j], s[j] ^= s[i], s[i] ^= s[j];
}
int main()
{
char sbuffer[101]; /* Buffer for Mag Stripe Line */
char *sbuf_ptr; /* Buffer Pointer */
char stripe_buf[66]; /* Buffer for working with stripe info */
char account_number[20];
char *acct_num_ptr;
char username[30]; /* the standard shows a maximum of 26 chars for the name */
char *username_ptr;
char expiry_date[5]; /* expiration date in MMYY format */
char *expiry_date_ptr;
char service_code[4]; /* Service Code 3 characters */
char *srv_code_ptr;
char discret_data[5]; /* Discretionary data (1 to 4 chars) */
char *discret_data_ptr;
char lrc[5]; /* the standard shows a maximum of 3 chars for this field */
char *lrc_ptr;
char start_sentinel = '%';
char end_sentinel = '?';
char format_code = 'B';
char field_separator = '^';
int i, j, k; /* variables for future use */
const int BUFLEN = 65; /* Buffer length must be at least 65 chars */
int sbuf_len;
int index;
int stripe_buf_len;
printf("Enter Line for Mag Stripe Testing: ");
fflush(stdout);
fgets(sbuffer, sizeof(sbuffer), stdin);
printf("\nThe Line Entered was: %s\n", sbuffer);
fflush(stdout);
sbuf_ptr = &sbuffer[0];
/* check line for initial minimum length requirement (65 chars min) */
sbuf_len = strlen(sbuffer);
if (sbuf_len < BUFLEN) {
fprintf(stderr, "Warning: Buffer length is too short for mag stripe data stream...\n");
fflush(stdout);
return(EXIT_FAILURE);
}
printf("\nLength of Buffer entered is: %d\n\n", sbuf_len);
fflush(stdout);
StringToUpper(sbuf_ptr);
printf("Buffer after conversion is: %s\n", sbuffer);
fflush(stdout);
/* First Character of buffer must be a %, sbuf_len - 3 must be a ? */
sbuf_ptr = &sbuffer[0]; /* reset buffer pointer to start of string */
if (*sbuf_ptr != start_sentinel) {
fprintf(stderr, "starting sentinel is not '%c'...exiting\n", start_sentinel);
fflush(stdout);
return(EXIT_FAILURE);
}
#if 0
for (i = 0; i < sbuf_len; i++)
printf("Value of sbuffer[%d] is %c\n", i, sbuffer[i]);
fflush(stdout);
#endif
/* this is kind of a kludge, needs better work */
if (sbuffer[sbuf_len - 5] != end_sentinel) {
fprintf(stderr, "Ending sentinel is not '%c'...exiting\n", end_sentinel);
fflush(stdout);
return(EXIT_FAILURE);
}
sbuf_ptr++;
if (*sbuf_ptr != format_code) {
fprintf(stderr, "Mag stripe format code is not letter 'B'...exiting\n");
fflush(stdout);
return(EXIT_FAILURE);
}
sbuf_ptr++;
printf("SUCCESS (SO FAR):\n");
printf("\nStarting sentinel is '%c'\n", start_sentinel);
printf("Ending sentinel is '%c'\n", end_sentinel);
printf("Format Code is '%c'\n", format_code);
fflush(stdout);
/* get the account number (usually the credit/debit card number */
index = 0;
acct_num_ptr = &account_number;
while (*sbuf_ptr != field_separator) {
*acct_num_ptr = *sbuf_ptr;
acct_num_ptr++;
sbuf_ptr++;
}
*acct_num_ptr = '\0'; /* terminate the account number buffer */
sbuf_ptr++; /* bump pointer to skip field separator */
printf("\nThe Account Number is: %s\n", account_number);
fflush(stdout);
/* At this point call Snort SDF CC/DC check for validity */
/* or ClamAV DLP processor for validity check */
/* Get the Account Holder's Name */
username_ptr = &username;
while (*sbuf_ptr != field_separator) {
*username_ptr = *sbuf_ptr;
username_ptr++;
sbuf_ptr++;
}
*username_ptr = '\0'; /* terminate the username buffer */
sbuf_ptr++;
printf("\nThe Card Holder Name is: %s\n", username);
fflush(stdout);
/* Get Expiration Date */
expiry_date_ptr = &expiry_date;
for (i = 0; i < 4; i++) {
*expiry_date_ptr = *sbuf_ptr;
expiry_date_ptr++;
sbuf_ptr++;
#if 0
expiry_date_ptr++;
sbuf_ptr++;
#endif
}
*expiry_date_ptr = '\0'; /* terminate the expiration date buffer */
/* Get Service Code Data */
srv_code_ptr = &service_code;
for (i = 0; i < 3; i++) {
*srv_code_ptr = *sbuf_ptr;
srv_code_ptr++;
sbuf_ptr++;
}
*srv_code_ptr = '\0'; /* terminate the service code buffer */
/* Get PVKI/PVV/CVV/CVC data */
discret_data_ptr = &discret_data;
while (*sbuf_ptr != end_sentinel) {
*discret_data_ptr = *sbuf_ptr;
discret_data_ptr++;
sbuf_ptr++;
}
*discret_data_ptr = '\0'; /* terminate the discretionary data buffer */
sbuf_ptr++; /* bump pointer to skip field separator */
printf("\nCard Holder Expiration Date is: %s\n", expiry_date);
fflush(stdout);
printf("\nCard Holder Service Code is: %s\n", service_code);
fflush(stdout);
printf("\nCard Holder Discretionary data is: %s\n", discret_data);
fflush(stdout);
/* Process Longitudinal redundancy check (LRC) data */
lrc_ptr = &lrc;
while (*sbuf_ptr) {
*lrc_ptr = *sbuf_ptr;
lrc_ptr++;
sbuf_ptr++;
}
*lrc_ptr = '\0'; /* terminate the LRC buffer */
sbuf_ptr = NULL; /* set original buffer pointer to NULL (sanity check) */
printf("\nThe Longitudinal redundancy check value is: %s\n", lrc);
fflush(stdout);
#if 0
ReverseString(sbuf_ptr);
printf("\nString after Reversal is: %s\n", sbuffer);
#endif // 1
return 0;
}