iT邦幫忙

2024 iThome 鐵人賽

DAY 18
0

Day 18 M1 卡片的完整模擬及拷貝

有些門禁系統除了讀取卡號之外,還會讀取卡片內的資料,這時候如果想要開啟這類的門禁,就需要完整的模擬或拷貝卡片的資料。

使用變色龍完整模擬 M1 卡

如果我們已經有 M1 卡片的完整資料,就可以使用變色龍裝置完整模擬 M1 卡片,以下是一個完整模擬 M1 卡片的範例程式碼:

// 在測試網頁的開發者工具中執行 https://taichunmin.idv.tw/chameleon-ultra.js/test.html
await (async ultra => {
  // 載入需要的常數
  const { Buffer, DeviceMode, FreqType, Mf1EmuWriteMode, Slot, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
  const slot = Slot.SLOT_1 // 使用卡槽 1

  await ultra.cmdSlotChangeTagType(slot, TagType.MIFARE_1024) // 設定卡槽為 M1 卡片類型
  await ultra.cmdSlotResetTagType(slot, TagType.MIFARE_1024) // 重設卡槽資料
  await ultra.cmdSlotSetEnable(slot, FreqType.HF, true) // 啟用卡槽的高頻模擬
  await ultra.cmdSlotSetActive(slot) // 切換到指定的卡槽
  await ultra.cmdMf1SetAntiCollMode(false) // 設定卡槽使用額外設定的防碰撞資料
  await ultra.cmdMf1SetDetectionEnable(false) // 關閉卡槽的偵測功能
  await ultra.cmdMf1SetWriteMode(Mf1EmuWriteMode.NORMAL) // 設定卡槽的寫入模式

  // 關閉 Gen1A 和 Gen2 魔術卡模擬
  await ultra.cmdMf1SetGen1aMode(false)
  await ultra.cmdMf1SetGen2Mode(false)

  // 設定防碰撞資料
  await ultra.cmdHf14aSetAntiCollData({
    atqa: Buffer.from('0400', 'hex'),
    sak: Buffer.from('08', 'hex'),
    uid: Buffer.from('136d4a3d', 'hex'),
    ats: Buffer.from('', 'hex'),
  })

  // 產生一個空白 M1 卡的資料並寫入變色龍
  const dump = Buffer.alloc(1024)
  dump.set(Buffer.from('136d4a3d090804000000000000000000', 'hex'), 0) // block 0
  const blkAcl = Buffer.from('FFFFFFFFFFFFFF078069FFFFFFFFFFFF', 'hex')
  for (let i = 0; i < 16; i++) dump.set(blkAcl, i * 64 + 48) // block 4n+3
  for (const chunk of dump.chunk(256)) await ultra.cmdMf1EmuWriteBlock(chunk.byteOffset / 16, chunk)

  // 儲存設定並切換裝置模式
  await ultra.cmdSlotSaveSettings()
  await ultra.cmdChangeDeviceMode(DeviceMode.TAG)
})(vm.ultra)

把 M1 卡片的資料拷貝到 UID 魔術卡

如果想要成本更低的選擇,也可以使用變色龍把 M1 卡片的資料拷貝到 UID 魔術卡內,但因為 UID 魔術卡問世的時間較早,所以如果遇到會挑卡的讀卡機,可能需要多試試其他的魔術卡。請把一個 UID 魔術卡放在變色龍裝置的正面,然後執行以下的程式碼:

// 在測試網頁的開發者工具中執行 https://taichunmin.idv.tw/chameleon-ultra.js/test.html
await (async ultra => {
  const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')

  // 產生一個空白 M1 卡的資料並寫入 UID 魔術卡
  const dump = Buffer.alloc(1024)
  dump.set(Buffer.from('136d4a3d090804000000000000000000', 'hex'), 0) // block 0
  const blkAcl = Buffer.from('FFFFFFFFFFFFFF078069FFFFFFFFFFFF', 'hex')
  for (let i = 0; i < 16; i++) dump.set(blkAcl, i * 64 + 48) // block 4n+3

  // 使用 UID 魔術卡的後門指令寫入所有區塊
  await ultra.mf1Gen1aWriteBlocks(0, dump)
})(vm.ultra)

把 M1 卡片的資料拷貝到 CUID 魔術卡

CUID 魔術卡需要有正確的金鑰及存取權限才能寫入,一個非加密的 CUID 卡金鑰通常是 FFFFFFFFFFFF,在寫入資料到 CUID 魔術卡時,請務必再三確認即將寫入的資料,因為寫錯資料可能會導致魔術卡鎖死 (俗稱變磚)。請把一個非加密的 CUID 魔術卡放在變色龍裝置的正面,然後執行以下的程式碼:

// 在測試網頁的開發者工具中執行 https://taichunmin.idv.tw/chameleon-ultra.js/test.html
await (async ultra => {
  const { Buffer, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')

  // 產生一個空白 M1 卡的資料並寫入 CUID 魔術卡
  const dump = Buffer.alloc(1024)
  dump.set(Buffer.from('136d4a3d090804000000000000000000', 'hex'), 0) // block 0
  const blkAcl = Buffer.from('FFFFFFFFFFFFFF078069FFFFFFFFFFFF', 'hex')
  for (let i = 0; i < 16; i++) dump.set(blkAcl, i * 64 + 48) // block 4n+3

  const keys = [Buffer.from('FFFFFFFFFFFF', 'hex')]
  const sectors = dump.chunk(64)
  let successCnt = 0
  for (let i = 0; i < 16; i++) {
    const { success } = await ultra.mf1WriteSectorByKeys(i, keys, sectors[i])
    successCnt += _.sumBy(success, isBlockSuccess => isBlockSuccess ? 1 : 0)
  }
  console.log(`成功寫入 ${successCnt} 個區塊`)
})(vm.ultra)

如果寫入完成後,要特別確認成功的數量是不是 64 個區塊,如果不是就代表有部分區塊寫入失敗,下圖是均民故意放了一張 UID 魔術卡在變色龍裝置的正面,因為區塊 0 無法使用普通的寫入指令,所以只成功寫入了 63 個區塊:


上一篇
Day 17 讀取 M1 卡片的資料
下一篇
Day 19 針對 M1 卡半加密卡或全加密卡的攻擊 ①
系列文
免安裝!一起用 JS 來控制開源的 NFC 讀卡機變色龍吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言