bool AuthBlock(IsoCard card, int block, bool isAKey = true) { byte type = 0x60; if (!isAKey) { type = 0x61; } CommandApdu apdu = card.ConstructCommandApdu(IsoCase.Case3Short); apdu.CLA = 0xFF; apdu.INS = 0x86; apdu.P1 = 0x00; apdu.P2 = 0x00; apdu.Data = new byte[] { 0x01, //version 0x00, (byte)block, type, //Key type 0x60 TYPE_A, 0x61 TYPE_B 0x00 }; //Key number 0x00 ~ 0x1F Response response = card.Transmit(apdu); if (response.SW1 == (byte)SW1Code.Normal) { return(true); } return(false); }
void UpdateMoney(IsoCard card) { string cfg = CardDumper.GetConfigurationKey("UpdateMoney"); int money = 0; if (!int.TryParse(cfg, out money)) { return; } string data = DumpMoney(card); if (string.IsNullOrEmpty(data)) { return; } int first = money & 0x0000FF; int second = (money >> 8) & 0x0000FF; //9 // 10 byte[] bytes = FromHex(data); bytes[9] = (byte)second; bytes[10] = (byte)first; if (!Write(card, 45, bytes)) { Log("Write failed!"); } DumpMoney(card); }
void DumpCard(IsoCard card) { string uid = ReadUID(card); Log("UID: " + uid); Log("[----------Start of Memory Dump----------]"); int blockSize = 4; for (int sector = 0; sector != 16; ++sector) { Log("----------------Sector " + string.Format("{0:D2}", sector) + "-----------------"); for (int block = 0; block != blockSize; ++block) { int cardBlock = sector * blockSize + block; string data = Read(card, cardBlock); Log("Block " + string.Format("{0:D2}", cardBlock) + ": " + data); } } Log("[-----------End of Memory Dump-----------]"); }
public IsoCard TryConnect(String cardName) { try { IsoCard card = new IsoCard(this.reader); card.Connect(cardName, SCardShareMode.Shared, SCardProtocol.Any); return(card); } catch (PCSCException) { return(null); } }
public List <String> GetConnected() { List <String> ret = new List <String>(); List <String> readers = new List <string>(ctx.GetReaders()); foreach (string s in readers) { IsoCard f = TryConnect(s); if (f == null) { continue; } ret.Add(s); } return(ret); }
string DumpMoney(IsoCard card) { string uid = ReadUID(card); string data = Read(card, 45); if (string.IsNullOrEmpty(data)) { return(""); } string money = data.Substring(18, 4); byte[] binary = FromHex(money); int value = (((int)binary[0]) << 8) | ((int)binary[1]); Log("UID: " + uid + " " + value + " cents"); return(data); }
bool WriteBlock(IsoCard card, int block, byte[] data) { CommandApdu apdu = card.ConstructCommandApdu(IsoCase.Case3Short); apdu.CLA = 0xFF; apdu.Instruction = InstructionCode.UpdateBinary; apdu.P1 = 0x00; apdu.P2 = (byte)block; apdu.Data = data; Response response = card.Transmit(apdu); if (response.SW1 == (byte)SW1Code.Normal) { return(true); } return(false); }
bool LoadKey(IsoCard card, byte[] key) { CommandApdu apdu = card.ConstructCommandApdu(IsoCase.Case3Short); apdu.CLA = 0xFF; apdu.Instruction = InstructionCode.ExternalAuthenticate; apdu.P1 = 0x20; apdu.P2 = 0x00; apdu.Data = key; Response response = card.Transmit(apdu); if (response.SW1 == (byte)SW1Code.Normal) { return(true); } return(false); }
void CardInserted(object sender, CardStatusEventArgs args) { SCardMonitor monitor = (SCardMonitor)sender; Log("CardInserted Event for reader: " + args.ReaderName); try { SCardReader reader = new SCardReader(m_card_context); if (reader.Connect(args.ReaderName, SCardShareMode.Shared, SCardProtocol.Any) == SCardError.Success) { DumpStatus(reader); IsoCard card = new IsoCard(reader); if (CardDumper.IsKeyEnabled("DumpCard")) { DumpCard(card); } if (CardDumper.IsKeyEnabled("DumpMoney")) { DumpMoney(card); } if (!string.IsNullOrEmpty(CardDumper.GetConfigurationKey("UpdateMoney"))) { UpdateMoney(card); } } reader.Disconnect(SCardReaderDisposition.Reset); } catch (Exception ex) { Log("Exception: " + ex.ToString()); } }
bool Write(IsoCard card, int block, byte[] data) { bool ok = false; byte[] key = null; if (m_keys.TryGetValue("A" + block, out key)) { if (LoadKey(card, key) && AuthBlock(card, block, true)) { ok = WriteBlock(card, block, data); } } if (!ok && m_keys.TryGetValue("B" + block, out key)) { if (LoadKey(card, key) && AuthBlock(card, block, false)) { ok = WriteBlock(card, block, data); } } return(ok); }
string ReadUID(IsoCard card) { string ouput = ""; CommandApdu apdu = card.ConstructCommandApdu(IsoCase.Case2Short); apdu.CLA = 0xFF; apdu.Instruction = InstructionCode.GetData; apdu.P1 = 0x00; apdu.P2 = 0x00; apdu.Le = 0x00; Response response = card.Transmit(apdu); if (response.SW1 == (byte)SW1Code.Normal) { byte[] data = response.GetData(); if (data != null) { ouput = ToHex(data); } } return(ouput); }
string Read(IsoCard card, int block) { string ouput = ""; bool ok = false; byte[] key = null; if (m_keys.TryGetValue("A" + block, out key)) { if (LoadKey(card, key)) { if (AuthBlock(card, block, true)) { ouput = ReadBlock(card, block); ok = !string.IsNullOrEmpty(ouput); } } } if (!ok && m_keys.TryGetValue("B" + block, out key)) { // Log("--" + ToHex(key)); if (LoadKey(card, key)) { if (AuthBlock(card, block, false)) { ouput = ReadBlock(card, block); ok = !string.IsNullOrEmpty(ouput); } } } return(ouput); }
static void Main(string[] args) { // Establish PC/SC context SCardContext ctx = new SCardContext(); ctx.Establish(SCardScope.System); // Create a reader object SCardReader reader = new SCardReader(ctx); // Use the first reader that is found string firstreader = ctx.GetReaders()[0]; // Connect to the card IsoCard card = new IsoCard(reader); card.Connect(firstreader, SCardShareMode.Shared, SCardProtocol.Any); // Build a ATR fetch case CommandApdu apdu = card.ConstructCommandApdu( IsoCase.Case2Short); apdu.CLA = 0x00; // Class apdu.INS = 0x84; // Instruction: GET CHALLENGE apdu.P1 = 0x00; // Parameter 1 apdu.P2 = 0x00; // Parameter 2 apdu.Le = 0x08; // Expected length of the returned data // Transmit the Command APDU to the card and receive the response Response resp = card.Transmit(apdu); // Show SW1SW2 from the last response packet (if more than one has been received). Console.WriteLine("SW1: {0:X2} SW2: {1:X2}", resp.SW1, resp.SW2); byte[] data; // First test - get the data from all response APDUs data = resp.GetData(); if (data != null) { Console.Write("CHALLENGE:"); foreach (byte b in data) { Console.Write(" {0:X2}", b); } Console.WriteLine(); } // Second test - get the data from each response APDU. int i = 0; foreach (ResponseApdu respApdu in resp.ResponseApduList) { data = respApdu.GetData(); if (data != null) { Console.Write("APDU ({0}), DATA:", i); foreach (byte b in data) { Console.Write(" {0:X2}", b); } Console.WriteLine(); i++; } } return; }