#!/bin/sh # getChallengeResponse.sh - login to my online banking website using the challenge-reponse mechanism # Purpose of this script (work in progress) is to further automate online banking. # More info: http://globalblindspot.blogspot.be/2010/07/getting-emvcap-challengeresponse-to.html # Author: Tom Van Braeckelpin="$1" challenge="$2" if [ -z "$pin" -o `expr length "$pin"` -ne 4 -o -z "$challenge" -o `expr length "$challenge"` -ne 8 ]; then echo "Usage: $0 " echo "Example: $0 3117 12345678" exit 1 fi # Can you guess what this method does ? bintodec() { bin="$1" echo "obase=10; ibase=2; $bin" | bc } # remove < and " " compact() { while read line; do echo "$line" | tr -d '<' | tr -d ' ' done } # args: command to execute on the card execOnCard() { cla="$1" ins="$2" p1="$3" p2="$4" le="$5" data="$6" tosend="${cla}${ins}${p1}${p2}${le}${data}" #echo "Sending $tosend" >&2 echo "$tosend" | scriptor 2>/dev/null | grep -A 10000 "<" # does not work: # echo "$cla $ins $p1 $p2 $le $data" | scriptor 2>/dev/null | grep "<" } execOnCardRespond() { cla="$1" ins="$2" p1="$3" p2="$4" le="$5" data="$6" result=$(execOnCard $cla $ins $p1 $p2 $le $data) ; echo "result = $result" >&2 # get length in hex length=$(echo "$result" | cut -d ' ' -f 3); #echo "length = $length" execOnCard 00 c0 00 00 $length | compact } # Can you guess what this method does ? hextobin() { hex="$1" echo "ibase=16; obase=2; $hex" | bc } # do a read data with the correct length... readData() { p2="$1" recordLength=$(execOnCard 80 ca 9f $p2 00 | cut -d ' ' -f 3) #echo "recordLength = $recordLength" >&2 # cut off first bytes (status code, length) # cut off last bytes (9000Normalprocessing) # for some reason we NEED CLA 80 here, 00 doesn't work... execOnCard 80 ca 9f $p2 $recordLength | compact | tail -c +7 | head -c -23 echo } readRecord() { p1="$1" p2="$2" errorWithLength=$(execOnCard 00 b2 $p1 $p2 00) #echo "errorWithLength = $errorWithLength" recordLength=$(echo "$errorWithLength" | cut -d ' ' -f 3) #echo "recordLength = $recordLength" execOnCard 00 b2 $p1 $p2 $recordLength | compact } readRecords() { SFI="$1" # five most significant bits recNr="$2" # second byte lastRecNr="$3" # third byte if [ "$SFI" = "1" ]; then p2=0c # (sfi << 3) + 4 else echo "I don't know p2 !" sleep 3 fi # READ RECORD(s) for i in `seq $recNr $lastRecNr`; do readRecord 0$i $p2 done } zeropadfront() { targetLength="$1" # echo "targetLength = $targetLength" while read line; do # echo "got line $line" length=$(expr length "$line") while [ $length -lt $targetLength ]; do line="0${line}" length=$(expr length "$line") done echo "$line" done } ################################################################# ###################### EXECUTION STARTS HERE #################### ################################################################# # reset execOnCard reset #select file/application aid=A0000000048002 # securecode aut #aid=A0000000043060 # maestro (debit) response=$(execOnCardRespond 00 a4 04 00 07 ${aid}) echo $response # this is needed, otherwise the commands below fail... PDOL=$(echo "$response" | grep -o -E "9F38........" | tail -c +7) echo "PDOL = $PDOL" # for securecode get a PDOL of "9F3501" (eg "9F38039F3501") # this is the "Terminal Type" - don't know the value, but I use 00... # get processing options: # - Application Interchange Profile (AIP) # - Application File Locator (AFL) if [ -z "$PDOL" ]; then response=$(execOnCardRespond 80 a8 00 00 02 8300); echo $response # eg: ...94080801030110010201 AIP=3800 # this means "initiate", "data auth", RFU AFLs="08010301 10010201" else # PDOL specifies one tag with value of 1 byte, but I don't know which value... response=$(execOnCardRespond 80 a8 00 00 03 830100); echo $response # 770E82021000940808010100080404009000:Normalprocessing. AIP=1000 # this means "initiate" AFLs="08010100 08040400" fi echo "Found AIP = $AIP and AFLs = $AFLs" # Read SecureCode records and extract valueable info cardinfo=$(readRecords 1 1 1) PAN=$(expr substr "$cardinfo" 9 18) echo "Application Primary Account Number (PAN) = $PAN" authinfo=$(readRecords 1 4 4) bitmap=$(expr substr "$authinfo" 11 22) echo "Proprietary Authentication Challenge-Reponse Bitmap = $bitmap" # This works for maestro: if false; then readRecords 1 1 3 # second group in AFL SFI=10 # five most significant bits recNr=1 # second byte lastRecNr=2 # third byte offlineDataRec=1 # fourth byte # p2=binary(firstbyte)100 left shift 3 OR 100 ??? # p2=binary(firstbyte) shift right 3 # I calculated 84, but it seems to be (13) 14 / (1B) 1C / (23) 24 # and also 03 04 0B 0C but we found those above p2s="14 1C 24" # READ RECORD(s) for p2 in $p2s; do for i in `seq $recNr $lastRecNr`; do echo -n "p2 = $p2, recordNr = $i: " readRecord 0$i $p2 done done fi # get pin try counter length pinTry=$(readData 17) echo "pinTry = $pinTry" if [ "$pinTry" != "02" -a "$pinTry" != "03" ]; then echo "WARNING: pinTry < 2 !" sleep 15 fi # get Application Transaction Counter echo -n "Application Transaction Counter = " readData 36 # get Last Online ATC Register echo -n "Last Online ATC Register = " readData 13 echo -n "Log Entry = " readData 4D echo -n "Log Format = " readData 4F # submit pin execOnCard 00 20 00 80 08 24${pin}FFFFFFFFFF # generate Application RQ Cryptogram # p1=80=Authorisation Request Cryptogram countrycode=0056 # OTF mentions 0000, chip&pin uses 0826 currencycode=0978 # OTF mentions 0000, chip&pin uses 0826 date=$(date +"%y%m%d") CardholderVerificationMethodResults=010002 # 8000000000 = Terminal Verification Codes: Data authentication was not performed (recommended by optimized to fail) # 00 = transaction type # 0000 = ICC Dynamic Number ARQC_response=$(execOnCardRespond 80 AE 80 00 22 000000000000000000000000${countrycode}8000000000${currencycode}${date}00${challenge}0000${CardholderVerificationMethodResults}) echo "ARQC_response = $ARQC_response" CID=$(expr substr "$ARQC_response" 11 2) ATC=$(expr substr "$ARQC_response" 19 4) AC=$(expr substr "$ARQC_response" 29 16) #IAD=$(expr substr "$ARQC_response" 51 15) # testing to see if we get the same response as in chip&pin - we do, so this is OK. # CID=80; ATC=A52D; AC=AD452EF6BA769E4A; IAD=06770A03A48000; bitmap=00001F00000000000FFFFF00000000008000 # generate Application Cryptogram for challenge 12345678 # 5a33 = Authorisation Response Code, generated by terminal or bank (for online stuff) IAuthData=0000000000000000000000000000000000000000 # Issuer Authentication Data (NOT Issuer Application Data !) AC_response=$(execOnCardRespond 80 AE 00 00 2e 5a33000000000000000000000000${countrycode}8000000000${currencycode}${date}00${challenge}0000${CardholderVerificationMethodResults}${IAuthData}) echo "AC_response = $AC_response" #AC_response="$ARQC_response" # Testing which response we need - normally the second one, but let's try this for a laugh CID=$(expr substr "$AC_response" 11 2) ATC=$(expr substr "$AC_response" 19 4) AC=$(expr substr "$AC_response" 29 16) # extract response echo "CID=$CID, ATC=$ATC, AC=$AC, IAD=$IAD" # length of bitmap is used as the target length for the response bitmap_hex_length=$(expr length "$bitmap") bitmap_bin_length=$(expr "$bitmap_hex_length" \* 4) echo bitmap_hex_length=$bitmap_hex_length, bitmap_bin_length=$bitmap_bin_length # Do logical AND with bitmap CIDATCAC_bin=$(hextobin "${CID}${ATC}${AC}${IAD}" | zeropadfront "$bitmap_bin_length") echo "CIDATCAC_bin = $CIDATCAC_bin" bitmap_bin=$(hextobin "$bitmap" | zeropadfront "$bitmap_bin_length") echo " bitmap_bin = $bitmap_bin" # if a bit of bitmap = 1, then we add the bit from CIDATCAC_bin to filtered_bin filtered_bin= for bitpos in `seq 1 $bitmap_bin_length`; do bitmap_bit=$(expr substr "$bitmap_bin" "$bitpos" 1) if [ $bitmap_bit -eq 1 ]; then CIDATCAC_bin_bit=$(expr substr "$CIDATCAC_bin" "$bitpos" 1) filtered_bin=${filtered_bin}${CIDATCAC_bin_bit} fi done echo "filtered_bin = $filtered_bin" # Note: if ATC>0x26(38) then response = 8 characters # if ATC=0xFFFF(65536) then response = 12 characters !!! is this correct ? filtered_dec=$(bintodec $filtered_bin) echo "RESPONSE = $filtered_dec" exit # this is never executed if false; then # Make AND of ARQC and Cap bit Filter: fortis: 77269F2701 00 9F3602 00B7 9F260886F857BEB767E8FB 9F100F 0601560384B0A80701030000000000 kbc: 77269F2701 00 9F3602 0004 9F260831F94BDAB5DF0F38 9F100F 0601560384B0400701030000000000 kbc: 77269F2701 00 9F3602 0005 9F2608B29D6D20BFE004AD 9F100F 0601560384B0400701030000000000 # extracted values output 00 00B7 86F857BEB767E8FB 0601560384B0A80701030000000000 output 00 0004 31F94BDAB5DF0F38 0601560384B0A80701030000000000 bitmask 00 00FF 000000000003FFFF filter .. ..04 ...........30F38 binary 0100 110000111100111000 decimal 1249080 fi Example protocol log: Collected from a NatWest reader and card performing a respond computation (ISO 7816, T=0 protocol). Personal details have been redacted. Command: 00a4040007 (select application) Proc: a4 Data: a0000000048002 Proc: 61 Status: 6112 (more data available) Command: 00c0000012 (application selected) Proc: c0 Data: 6f108407a0000000048002a5055f2d02656e Proc: 90 Status: 9000 (OK) Command: 80a8000002 (initiate transaction) Proc: a8 Data: 8300 Proc: 61 Status: 6108 (more data available) Command: 00c0000008 (transaction initiated) Proc: c0 Data: 8006100008010100 Proc: 90 Status: 9000 (OK) Command: 00b2010c00 (get static data length) Proc: 6c Status: 6c57 (wrong length) Command: 00b2010c57 (read static data) Proc: b2 Data: 7055 8e0a 00000000000000000100 (CVM list) 9f5501 a0 (unknown) 9f5612 00001f00000000000fffff00000000008000 (bit filter) 8c15 9f02069f03069f1a0295055f2a029a039c019f3704 (CDOL1) 8d17 8a029f02069f03069f1a0295055f2a029a039c019f3704 (CDOL2) Proc: 90 Status: 9000 (OK) Command: 80ca9f1700 (get PIN try counter length) Proc: 6c Status: 6c04 (wrong length) Command: 80ca9f1704 (get PIN try counter) Proc: ca Data: 9f170103 (3 remaining tries) Proc: 90 Status: 9000 (OK) PIN entered: ? Command: 0020008008 (verify PIN) Proc: 20 Data: 24xxxxffffffffff Proc: 90 Status: 9000 (OK) Challenge entered: 12345678 Command: 80ae80001d (generate ARQC) Proc: ae Data: 0000000000000000000000000000800000000000000000000012345678 Proc: 61 Status: 6114 (more data available) Command: 00c0000014 (return ARQC) Proc: c0 Data: 80 1280 0042b7f9a572da74caff 06770a03a48000 Proc: 90 Status: 9000 (OK) Command: 80ae00001f (generate AC) Proc: ae Data: 5a330000000000000000000000000000800000000000000000000012345678 Proc: 61 Status: 6114 (more data available) Command: 00c0000014 (return AAC) Proc: c0 Data: 80 1200 00424f1c597723c97d78 06770a03258000 Proc: 90 Status: 9000 (OK) Response returned: 4822527
Various wacky and hacky technological research projects, shared with the world so that restless brains may find peace of mind here.
Posts tonen met het label smartcardsessions. Alle posts tonen
Posts tonen met het label smartcardsessions. Alle posts tonen
vrijdag 31 mei 2013
getChallengeResponse.sh script
maandag 12 juli 2010
Getting EMV/CAP challenge/response to work
Let's recap; I've been sing my Belgian EID smartcard reader to query my KBC debit card. This has been working great, and I'm now able to select the SecureCode application and unlock it by verifying my PIN code.
Now I'm trying to get the challenge/response mechanism to work, so I can have my PC automatically login to KBC Online. This should work by now, but for some reason the response always turns out to be wrong...
Warning: if you're playing with this as well, keep in mind that KBC will only allow 3 failed attempts at logging in. So when you've failed twice, log in using the normal method (that actually works) to reset the login try counter.
According to the specs, we need to generate an Application RQ Cryptogram, and then cancel it by requesting an Application Cryptogram. See my script for the dirty details... much of this work is based on EMV CAP examples from "Chip & PIN is broken".
Now if only I could figure out what's wrong with the responses I'm generating !
Now I'm trying to get the challenge/response mechanism to work, so I can have my PC automatically login to KBC Online. This should work by now, but for some reason the response always turns out to be wrong...
Warning: if you're playing with this as well, keep in mind that KBC will only allow 3 failed attempts at logging in. So when you've failed twice, log in using the normal method (that actually works) to reset the login try counter.
According to the specs, we need to generate an Application RQ Cryptogram, and then cancel it by requesting an Application Cryptogram. See my script for the dirty details... much of this work is based on EMV CAP examples from "Chip & PIN is broken".
Now if only I could figure out what's wrong with the responses I'm generating !
zondag 13 juni 2010
Finding smartcard Application ID's - a brute force approach
I made this handy script to find Application ID's, since I'm investigating one of my debit cards.
#!/bin/sh # This is GPL v3 code. # Author: Tom Van Braeckel# # On my PC, this tries about 22 application ID's / second. # Doing a full scan will take between 3h and 16 days. hex="0 1 2 3 4 5 6 7 8 9 A B C D E F" # 00 = Instruction class # A4 = SELECT FILE # 0400 = mandatory # 07 = length of application id # A00000 = fixed part of application ID prefix="00A4040007A00000" for n1 in $hex; do for n2 in $hex; do for n3 in $hex; do for n4 in $hex; do for n5 in $hex; do for n6 in $hex; do for n7 in $hex; do for n8 in $hex; do totry=$n1$n2$n3$n4$n5$n6$n7$n8 echo -n "Trying ${prefix}${totry}:" echo "${prefix}${totry}" | scriptor 2>/dev/null | grep "<" done done done done done done done done
EMV/CAP Application ID's
AID Name
A0000000031010 VISA Credit A0000000032010 VISA Electron A0000000033010 VISA Interlink A0000000034010 Visa Specific A0000000035010 Visa Specific A0000000038002 Barclays/HBOS A0000000038010 VISA plus A0000000041010 MasterCard Credit A0000000042010 MasterCard Specific A0000000043010 MasterCard Specific A0000000043060 Maestro (Debit) A0000000044010 MasterCard Specific A0000000045010 MasterCard Specific A0000000046000 Cirrus A0000000048002 NatWest or SecureCode Aut A0000000250000 America Express A0000001410001 Pagobancomat A0000002040000 ? A0000002281010 SAMA A0000002771010 INTERAC
dinsdag 1 juni 2010
SmartCardSessions: Welcome
I'm keeping an online, public diary of some of my smartcard experiments here.
Abonneren op:
Posts (Atom)