I really should have written this after ZaCon (november last year), but I’m lazy. However I have been asked to give a brief overview of the same talk at ITWeb this year so I figure I may as well finish this article and get it out :P
So in the first blog post I discussed the basics of Magnetic stripes and how the tech works. I like it because its fundamentally simple (perhaps like myself ;).
This entry is going to cover spoofing, from building a spoofer to having something read the entries. Ideally you want to have a magreader at this stage, either one of the nifty USB ones that act as an HID device or one that you built that can read the tracks you are interested in. Below is a cheap TTL reader I got (cost about R150, thats ~$20):
This is really just so that you can “listen” to what your spoofer can generate. Magnetic stripe spoofers have been done all over the place, so please don’t think I did this, you can see some great examples HERE and HERE. Essentially however the system is dead simple, you have the ‘sound’ that you wish to play (as discussed previously), an amplifier that can crank up the volume to the level that its going to get picked up and an electromagnet (it sounds fancy, its just wire coiled around a piece of metal – more later).
First up you want to build an amplifier. This seems incredibly daunting to someone who knows f-all about hardware (thats me!), however its not nearly as complicated as what I thought. I built one from an LM386 chip (it seems to be the easiest/most common), the layout for it looks like so:
But really you can find a whole bunch on the net, just hit up the google machine.
Really when it comes down to it, you only need:
- 220 uF cap
- 0.05 uF cap
- Mono Jack
- 9v Battery
Here you can see mine, complete with terrible wiring,soldering and running on a 9v battery, luck and good feelings:
Best way to test the amplifier is to get an old school PC speaker, hook it up and play some audio through it, adjust the pot to check your volume control works and you are good to go. The sound quality isnt that great, but heck it works if you ever need a speaker system too :P
The next step is to create the electromagnet, essentially what it does is that when current is passed through the coil of wire that is wrapped around a ferromagnetic object an electromagnetic field is created . By turning this on and off rapidly we can create the differences we have seen previously in how magstripes work. So for this part our partlist is as follows:
- Coil of thin wire (as thin as you can get without it becoming a hairball — I have 2 at home)
- Ferromagnetic core, I just used some plain old sheet steel
I read a number of the other magstripe spoof tutorials and it seems that the easiest way was to use either a rectangular piece of steel or an ‘I’ shaped piece of steel (the I makes it easier to wrap the wire around). First thing I did was get these cut out I managed to get a bunch of different strips out, I then used a cut up 2L coke bottle and put the strips in some deoxidene to get them clean:
So once I had nicely cleaned pieces I needed to cover them in very thin wire. Initially I bought what seemed to be hair width hair (0.1 mm enamel/copper wire), my advice to anyone trying to use this is WALK AWAY SCREAMING. Literally I ended up both breaking the wire on the edges of the steel or ending up with a birdsnest where I couldnt actually thread the wire. However if you are looking to punish someone, I recommend this.
So I went to another electronics store, bought some 0.25 copper wire and some white marker tape to blunt the edges and started winding till I had a nice electromagnet:
Now I finally had both my electromagnet and amp together, I really just need to connect the two together. Now the previous video probably makes a bit more sense, essentially what I did was connect the amp to the electromagnet to the output from my pc (at that stage playing Dead Kennedys – California Über Alles ), then on a seperate pc I used the previous magnetic read head connected to another computers microphone input and set the computer to play everything that came into that port. The result was me being able to play audio from one pc to another via my electromagnet:
Now we had the ability to play ‘audio’ through the amplifier and electromagnet AND if you remember from the previous blog entry magstripes really are just audio we had a few options with what we could do:
- Replay a card – Since magnetic cards are just a single track and usually not changed during an entry swipe we could make a quick copy of a card and replay it to a reader
- Brute force a card – If a cards value is “accesslevel#1”, naturally we could change that from 1 to be 1-99999 and generate audio for just that
IMPORTANT: As we have a single magnetic field we are creating we can only replay a SINGLE track at a time, this means that while its great for something like access control and other systems that generally use one track you arent going to be able to spoof to a reader that is looking for all 3. However with that being said, if you play the tracks back to back often a reader will still see it as the ‘same card’, in practice however its very unlikely that you will come across this.
Adam Laurie (Major Malfunction) – an amazing researcher – previously created a few files (found in the same places as referenced in the last blog post) to not only take wav files apart and give you the ability to identify the data contained within it, but ALSO the ability to create these wavs. Here I created a quick wav file of a sample track 1 for a card, “%B0126672737012367^MOHAWK/ANDREW.MR ^120119850000555 ?” :
After that I got a nice clean audio file out:
The one thing you will instantly notice is that my audio file does not look ANYTHING like the previous audio files we had, these are all square waves where previous they were scintillating sine waves! This is due to the fact that in the code you will notice (# sinewaves need to be half waves to work – can’t be bothered to # figure it out now!), however they work perfectly well as the readers are not decoding the actual waves but the gaps inbetween.
Naturally generating the audio this way is a bit of a pain having to first create the magstripe binary string and then create the wav file, so I combined the two into a script I will discuss later. For now I had the audio, I had the amp and I had the electromagnet, on to testing! While testing/debugging I found it very useful to use the audio from the original magstripe ‘audio’ reader created from the TTL device, but later I got my hands on one of the many cheap USB type readers available and could then hear if it was working correctly (it beeps) as well as see the decoded signal on the screen (its simply an HID device and ‘types’ the output to the screen).
Some Problems: So before I get to the final section of replaying and brute forcing, there are a few problems you should note with this. Firstly as discussed previously you cannot spoof multiple tracks at once. The second major problem is the volume output from your amp, as the readers essentially are reading your ‘song’ if the sound is clipping (is too loud) or is too soft the reader will essentially not be able to ‘hear’ your data. You would have seen from my ZaCon talk that my demo failed and that was because I accidentally moved the volume level down on my ipod from 100% (which everything was configured for) to 95%, and such a small volume difference can be all the well.. difference. Lastly readers often have a specific timeout they regard for a card swipe (a time they think the slowest swipe will take) which means that when brute forcing you will need to have a delay between each individual “card” or the device wont give you a positive/negative for it.
Replaying is pretty trivial, simply record the audio in the method described in the previous post or using the TTL reader you built and then replay it through the amp to the electromagnet, remember to keep the electromagnet close enough to the read head that it can simulate a card passing and the read head can pick this up. To be fair I’d almost never do this, its far easier to simply purchase something like an MSR605 (I picked one up on eBay for relatively cheap) and simply create your own card – Ive done this with many hotel room cards/access control systems without ever having a problem. It means you look a lot less suspicious as you dont have any electronic devices plugged into the gate and if it doesnt work you can quite easily walk away :) It also means that if you do figure out something say that escalates your access control you can simply “write” that card and use that.
While replaying and spoofing is great, it means you still need access to a card and will always be using that card with its limitations. Many access control systems are trivially implemented and will either be configured individually on the entry system to allow certain cards (such as allow cards 00001/2/3/4/5) or be centrally linked to something that identifies a user (such as a student number for a university – information which can be found publicly). With this in mind the possibility of gaining access becomes a lot more realistic when bruteforcing (presuming of course you have access to a card for the system you are looking into).
So after mangling the scripts for my ZaCon talk (I hope this is okay with MM – I did include all his copyright etc) I came up with this:
''' This script was hacked together using Major Malfunctions cab.py and cmsb.py, licenses from those as follows: # # cmsb.py: Create MagStripe Binary # Convert ASCII data to ABA/IATA binary with LRC # Inspired by dmsb.c by Joseph Battaglia <email@example.com> # # Copyright 2006,2007 Major Malfunction <firstname.lastname@example.org> # version 0.1 (IATA only) # http://www.alcrypto.co.uk/ # Distributed under the terms of the GNU General Public License v2 # version 0.2 (add ABA capability, characterset checking) # Parts Copyright 2007 Mansour Moufid <email@example.com> # Distributed under the terms of the GNU General Public License v3 # cab.py: Create Aiken Biphase # create a WAV file with arbitrary data in it # # Copyright(c) 2006, Major Malfunction <firstname.lastname@example.org> # http://www.alcrypto.co.uk # # inspired by 'dab.c' by Joseph Battaglia <email@example.com> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # # version 0.1: # just get the thing working with fixed WAV and other parameters! Password gen stuff thanks to Nadeem Douba ( @ndouba ) ''' import sys import string from operator import * import wave import sys from struct import * from math import * def _baseN(num, base, numerals): if not num: return numerals if num < 0: return '-' + _baseN((-1) * num, base, numerals) if not 2 <= base <= len(numerals): raise ValueError('Base must be between 2-%d' % len(numerals)) left_digits = num // base if left_digits == 0: return numerals[num % base] else: return _baseN(left_digits, base, numerals) + numerals[num % base] def baseN(num, numerals="0123456789abcdefghijklmnopqrstuvwxyz", padding=0): n = _baseN(num, len(numerals), numerals) l = len(n) if l < padding: n = '%s%s' % (numerals * (padding - l), n) return n def createSquareWav(wavFile,freq,data,reverse,delay): frequency= int(freq) - 1 if reverse == True: newdata=  n= len(data) - 1 while n >= 0: newdata.append(data[n]) n= n - 1 data= newdata peak= 32767 wavedata =  #Trailing space for x in range(int(22050 * delay)): wavedata.append('\x00\x00') #wavFile.writeframes('\x00\x00') for x in range(20): wavedata.append(pack("h",0)) #wavFile.writeframes(pack("h",0)) # write the actual data # square wave for now n= 0 writedata= peak while n < len(data): if data[n] == '1': for x in range(2): writedata= -writedata for y in range(frequency/4): wavedata.append(pack("h",writedata)) #wavFile.writeframes(pack("h",writedata)) if data[n] == '0': writedata= -writedata for y in range(frequency/2): wavedata.append(pack("h",writedata)) #wavFile.writeframes(pack("h",writedata)) n= n + 1 #for x in range(32000): # wavFile.writeframes('\x00\x00') for x in range(int(22050 * delay)): wavedata.append('\x00\x00') #Doing it this way takes some tests I did from 1min 15secs to 2seconds!!!!!!! value_str = ''.join(wavedata) wavFile.writeframes(value_str) def createAikenBiphase(tracknum,data,padding): if int(tracknum) == 1: bits = 7 base= 32 max= 63 elif int(tracknum) == 2 or int(tracknum) == 3: bits = 5 base= 48 max= 15 zero = '' lrc =  for x in range(bits): zero += "0" lrc.append(0) output = '' #padding = 0 for x in range(padding): output += zero for x in range( len(data) ): raw = ord(data[x]) - base if raw < 0 or raw > max: print 'Illegal character:', chr(raw+base) sys.exit(False) parity = 1 for y in range(bits-1): output += str(raw >> y & 1) parity += raw >> y & 1 lrc[y] = xor(lrc[y], raw >> y & 1) output += chr((parity % 2) + ord('0')) parity = 1 for x in range(bits - 1): output += chr(lrc[x] + ord('0')) parity += lrc[x] output += chr((parity % 2) + ord('0')) return output if len(sys.argv) < 5: print "createWavs.py v0.01" print "Usage: %s OutputFile.wav <[r]everse> <delay_at_front_and_back> " % sys.argv print "Samples defaults to 15, Padding to 0" print "* = Try all in range for track, eg, T2 = 0,1,2,3,4,5,6,7,8,9,:,;,<,=,>,?" sys.exit(False) print "-------------------------------------------------" print " Marty McFly's Wav Generator " print " Generating Aiken Biphase Wav Files " print " by Andrew MacPherson (@AndrewMohawk) " print "-------------------------------------------------" tracknum = int(sys.argv) data = sys.argv padding = 0 if(len(sys.argv) > 4): padding = int(sys.argv) samplesPerBit = 15 if(len(sys.argv) > 5): samplesPerBit = int(sys.argv) reverse = False if(len(sys.argv) > 6) and (sys.argv == 'r'): reverse = True delay=0 if(len(sys.argv) > 7): delay = float(sys.argv) results =  numStars = data.count("*") print "[+] Found %s number of brute force fields" % numStars bruteForceList = ; if(tracknum == 1): for z in range(32,95): bruteForceList.append(chr(z)) if(tracknum == 2 or tracknum ==3): for z in range(48,64): bruteForceList.append(chr(z)) #print bruteForceList #exit(0) #bruteForceList = ['A','B'] if (numStars > 0): print "[+] Generating Aiken Biphase... " pfmt = data i = 0 while True: n = baseN(i, bruteForceList, numStars) if len(n) > numStars: break tmp = pfmt for c in n: tmp = tmp.replace('*', c, 1) #results.append(tmp) results.append(createAikenBiphase(tracknum,tmp,padding)) i += 1 else: results.append(createAikenBiphase(tracknum,data,padding)) print "[+] Generated %s Results" % len(results) print "[+] Building consecutive wav file.." wavFile=wave.open(sys.argv,"w") params= (1, 2, 22050, 0L, 'NONE', 'not compressed') wavFile.setparams(params) for r in results: createSquareWav(wavFile,samplesPerBit,r,reverse,delay) wavFile.close()
Essentially the script allowed you to create a longer wave file that you would play to the device with the following options:
* Track Number (remember we can only do 1 at a time)
* How many padding 0’s we should use
* How many samples per bit we would create in the audio file (essentially how big the gaps are)
* Reversing of the data (y/n)
* Delay inbetween tracks to ensure that you give the reader enough time to process it.
I could then place a * within the data which would try every possible combination for that point (depending on which track you were using) and get a ‘brute force’ wav file back :)
From here I could then connect everything up, create a wav file which I put onto an audio player (simply so I wasnt using a laptop) and with a tiny device brute force my way in. Here is a video of it in action with an old bank card and my ipod:
(You will note my amp here looks a lot fancier – someone else kindly built me a new one after having a look at mine! )
Magstripes are old tech and are definitely susceptible to brute force and replay attacks via a few Rands (or dollars) of equipment. There are limitations that can make this a lot harder such as:
1. Checking that multiple tracks are being read at once (it costs more for the readers, but its access we are talking about)
2. Logging possible brute force attempts (and having higher read timeouts, costing attackers time when trying to brute force)
3. Lockout conditions if a card is used multiple times in an unusual manner (although this could provide a DoS scenario for an attacker)
4. Encryption on the card data means that the person brute forcing would need to figure out how your data is encrypted first