Intro
So its been nearly a month since I last put a blog post up and I have been working on some stuff in my free time between work (been traveling to the US and took a weekend off to visit some friends in Canada). I’m not particularly in the mood to write a new post, but you know how it is, if I don’t start writing it I’ll never get round to it.
Essentially I have always been fascinated by the idea of being able to ‘hack’ with/into physical things, whether it be the Arduino and my watering system (btw you can see those stats at http://andrewmohawk.dyndns.org/AWS/), changing data on RFID cards or being that sneaky kid jackpotting ATM machines.
I started looking at magnetic stripes, mostly because they are *everywhere*, from bank cards, customer loyalty and even parking systems.
Overview
The basic gist of the system is that there are many tiny magnets or magnetic particles (usually iron oxide) which are magnetized in a specific manner within a magstripe. Essentially you take the card (or think of it as many magnets) and put it next to a magnetic reader (card reader) which then reads the fields. These fields are then taken to good ol 1′s and 0′s and used within backend systems after a bit of decoding.
The magnetic stripe on a card is actually made up of 3 different ‘stripes’ or tracks (usually - different types of cards will have a different number of tracks), right above each other. Each of these tracks can hold different amounts of data and for the basic breakdown you can read up about em at http://www.gae.ucm.es/~padilla/extrawork/tracks.html and http://www.ded.co.uk/magnetic-stripe-card-standards/
TL;DR – Track 2/3 = Numbers, Track1 = UPPERCASE,numbers
Reading
Most magstripes use whats known as F2F/Aiken Biphase/BMC encoding, which determines whether something is a 1 or a 0 by looking at the change within a particular ‘phase’ (the time taken for one cycle). The time for a phase is identified by a series of 0′s at the beginning of each track (essentially just allowing the reader to say okay i see them coming past at x ms). This is known as self-clocking and allows readers to read cards that are pushed through by a human rather than say that of a tape player where it is a fixed speed.
This blog post very nicely describes how the reading works: http://www.qualifilms.com/blog/computer-science/2009/06/back-to-basics-reverse-engineering-of-a-non-standard-magstripe-part-one/ with images too!
TL;DR It works it out from the changes in the phase and does the timing from the initial 0′s
This diagram explains it best:
Clik here to view.

Reading a Magnetic Stripe
Building a Reader
So first things first, I needed to be able to successfully *read* magnetic stripes as an audio file so that I could start playing with them. The easiest way to do this was simply to create a magnetic stripe ‘reader’, there are a few posts on this and they basically come in the form of two options:
- Buy one (you can simply purchase a reader practically anywhere and then take it apart to get straight audio out – rather than the decoded wav
- Build one (this tech was used all over tape players way back so you can strip em to make one)
Because of my limited (read no) budget, I decided to build one from an old tape player.
Taking apart a Tape player
Initially I started by going to many different second hand stores, thrift shops and so on to look for a radio with tape player to use for this. Surprisingly people seem to have just thrown most of them away and I couldn’t find *any* near where I stay. However I have read about other people who have found plenty at second hand stores/tips etc. So look around. I found a really cheap one for R80 at a cheap chinese store near me:
Anyway, I skillfully (read unskillfully) began disassembling (read destroying) my R80 tape player to get to the read head:
Clik here to view.

The original Tape Player
Clik here to view.

Disassembly
Clik here to view.

Disassembly
So after I had carefully (read completely uncarefully, possibly drunk and with all sorts of arb hammering/pulling and breaking) taken apart the packaging I could get to the juicy bits, the actual tape reading mechanism and specifically what I was looking for – the read head:
Clik here to view.

Read Head (in silver)
Next was the process of wiring up the read head (in silver) to the pc. Essentially the one side you need a mono jack (or take a stereo jack and wire a single wire to both sides of it – like i did) which will go into the PC to record the audio. These jacks can be taken from any old set of headphones or you can go and buy one at an electronics store (super cheap). The other side of the cable is simply wired to either side of the magnetic read head as below:
Clik here to view.

Magnetic Read head
- Image may be NSFW.
Clik here to view. - Mono Jack
Reading cards:
The next stage after setting up the read head to a mono jack is to read the magnetic data on a card. As said before the ‘tracks’ are actually all on top of each other for generic cards. This page gives you a lot of really good information on the layout of cards and definitely recommended reading.
TL;DR: tracks are as follows:
0.223″ | TRACK | Recording Density (Bits per inch) |
Character Configuration (including parity bit) |
Information Content (inclusing control characters) |
0.110″ | 1 IATA | 210 | 7 bits per character | 79 alphanumeric charcters |
0.110″ | 2 ABA | 210 | 5 bits per character | 40 numeric characters |
0.110″ | 3 THRIFT | 210 | 5 bits per character | 107 numeric characters |
Essentially this means that if you wish to get the track information off you need to use a ruler to get the distance from the card correct and slide the magnetic read head along the edge of the ruler. This is a painful process as the ruler often moves or you are just above or below the track.
The way I have found to get it to work the best, is to simply find a second hand/broken/cheap TTL/other reader and modify it to have the magnetic read head go straight into the pc, something like this:
Clik here to view.

Modified TTL Reader
Clik here to view.

Modified TTL Reader
Working with Audio
Now you have a the reader setup, or a painful ruler setup the next step is to get the audio out. Fire up any old sound recorder (I like audacity), connect the Mono plug into the mic jack, hit record and swipe away!
I put up a sample of a generic customer loyality card at soundcloud: http://soundcloud.com/andrew-3/card-swipe/s-MvlVg
Within audacity you can see it as:
Clik here to view.

loyality-card
Zooming in to the card swipe you can see the data a lot clearer:
Clik here to view.

loyality-card-zoomed
(the data above is the ‘clocking’ zeros followed by the first bits of the card)
How the audio works
The ‘audio’ is really just the encoded data, essentially a number of zero’s are seen at the front of the track so that the readers can determine the speed at which the card is moving through and ultimately the time it takes for 1 complete cycle. After it has got this ‘synched’ it will then start determining 1′s and 0′s by looking at whether the wave has changed within the specific period. This is also called Differential Manchester Encode / Bimark Phase Code / Aiken Biphase or F2F.
Its almost definitely best explained in images, and these great ones have been stolen from This blog:
Clik here to view.

Aiken Biphase
Clik here to view.

Aiken Biphase
As you can see above in the first two periods the wave has changed (the period is highlighted in red) and is subsequently a 1 where as in the 3rd and 5th phase it has remained the same (not specific to a high or a low) and is a 0.
Decoding the Audio
Major Malfunction has a great selection of python tools over at alcrypto.co.uk ( you’ll need to find the links), one of these being dab.py (Decode Aiken Biphase) – this script takes all the hard work (described previously) in getting the binary data out:
Clik here to view.

Decode Aiken Biphase
Decoding the Binary
So the binary is in the format of a 5 bit character (4 bits for the data and 1 bit for odd-parity checking) and works something like this:
Binary data: 11001
First four for data: 1100
Odd-Parity bit: 1
Looking at the above its first important to know that the parity bit (the last 1) is calculated by making sure there are an odd number of 1′s in the five bit sequence.
Next you can look at the ‘data’ which is 1100. The data is encoded with the least significant bit first, so the in essence it is read backwards and the actual data is 0011. This data can then be taken to decimal (0111 = 3), it is then shifted up 48 characters in the ASCII character set to return the ASCII value, thus the decimal value is 51 which is a 3.
I whipped up a PHP script to do this for the data I got out previously which returns as follows:
Clik here to view.

Decoding Track3
As you can see in the above screenshot this decodes nicely to “;7353280041358181=491252200000999?” and the first part of that being the number printed on my loyalty card:
Clik here to view.

Loyalty Card
Code
The code is available on pastebin for those interested: http://pastebin.com/h9eVqRxz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | <?php // AndrewMohawk // andrew@andrewmohawk.com // http://www.andrewmohawk.com /* Decode Track 2/3 data from binary */ $binary = "<yourBinaryHere>"; // this function by mtroy dot student at gmail dot com taken from http://php.net/manual/en/function.strpos.php function strpos_r($haystack, $needle) { if(strlen($needle) > strlen($haystack)) trigger_error(sprintf("%s: length of argument 2 must be <= argument 1", __FUNCTION__), E_USER_WARNING); $seeks = array(); while($seek = strrpos($haystack, $needle)) { array_push($seeks, $seek); $haystack = substr($haystack, 0, $seek); } return $seeks; } function processBinary($binary) { $AsciiOutput = ""; //find start sentinal $start_sentinal = strpos($binary,"11010"); if($start_sentinal === false) { echo "Could not find start sentinal\n"; return false; } //find end sentinal $end_sentinal = false; $end_sentinals = strpos_r($binary,"11111"); if(count($end_sentinals) == 0) { echo "Could not find end sentinal\n"; return false; } //Check end sentinal is on a 5 bit boundry foreach($end_sentinals as $es) { $es = $es; if(($es - $start_sentinal) % 5 == 0) { $end_sentinal = $es; } } if($end_sentinal == false) { echo "End sentinal not on correct boundry\n"; return false; } //Lets decode the data: $bit_length = 5; // 4 bits for data, 1 bit for odd-parity or LRC checking $data = substr($binary,$start_sentinal,($end_sentinal-$start_sentinal+5)); $currentBits = ""; $currentNum = 0; $finalString = ""; for($i=0;$i<strlen($data);$i++) { if(strlen($currentBits) < $bit_length) { $currentBits .= $data[$i]; } if(strlen($currentBits) == $bit_length) { $parityBit = $currentBits[4]; $dataBits = substr($currentBits,0,4); $asciiChar = 0; for($x=0;$x<4;$x++) { $currentNum += $dataBits[$x]; } $dec = bindec($dataBits); $dec = str_pad($dec, 2, "0", STR_PAD_LEFT); // just so output is nice $asciiChar = chr(bindec(strrev($dataBits))+48); // reverse the binary (since its LSB first) then convert to dec, add 48 and then take it to ASCII echo "$currentBits - Data ($dataBits) Parity($parityBit) Decimal ($dec) Ascii($asciiChar)"; if(($currentNum + $parityBit) % 2 == false) { echo " __ Parity: Invalid"; } else { echo " __ Parity: Valid"; } $AsciiOutput .= $asciiChar; echo "\n"; $currentBits = ""; $currentNum = 0; } } echo "\n\nTotal Out (ascii): $AsciiOutput\n"; } echo "Trying One way:\n\n"; if (processBinary($binary) == false) { //reverse. echo "\n\n"; echo "Trying The Reverse:\n\n"; processBinary(strrev($binary)); } |
Going Onwards:
So understanding the basics of how magnetic stripes work and how the data is encoded means that should I come into contact with other formats I know what to look for and can mess with them. Also knowing the above means I can write something to encode the data, generate wav files and build a spoofer to replay the attack :)
I’ll write a follow up sometime with spoofing magnetic stripes, here is a short video of me playing audio (since thats what it really is right?) from a spoofer to my magnetic read head:
-AM