Create a new instance of ChameleonUltra.
Enable debug mode.
Example usage in Browser (place at the end of body):
<script src="https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/iife/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/iife/plugin/WebbleAdapter.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/iife/plugin/WebserialAdapter.min.js"></script>
<script>
const { ChameleonUltra, WebbleAdapter, WebserialAdapter } = ChameleonUltraJS
const ultraUsb = new ChameleonUltra()
ultraUsb.use(new WebserialAdapter())
const ultraBle = new ChameleonUltra()
ultraBle.use(new WebbleAdapter())
</script>
Example usage in CommonJS:
const { ChameleonUltra } = require('chameleon-ultra.js')
const WebbleAdapter = require('chameleon-ultra.js/plugin/WebbleAdapter')
const WebserialAdapter = require('chameleon-ultra.js/plugin/WebserialAdapter')
const SerialPortAdapter = require('chameleon-ultra.js/plugin/SerialPortAdapter')
const ultraUsb = new ChameleonUltra()
ultraUsb.use(new WebserialAdapter())
const ultraBle = new ChameleonUltra()
ultraBle.use(new WebbleAdapter())
const ultraNode = new ChameleonUltra()
ultraNode.use(new SerialPortAdapter())
Example usage in ESM:
import { ChameleonUltra } from 'chameleon-ultra.js'
import WebbleAdapter from 'chameleon-ultra.js/plugin/WebbleAdapter'
import WebserialAdapter from 'chameleon-ultra.js/plugin/WebserialAdapter'
import SerialPortAdapter from 'chameleon-ultra.js/plugin/SerialPortAdapter'
const ultraUsb = new ChameleonUltra()
ultraUsb.use(new WebserialAdapter())
const ultraBle = new ChameleonUltra()
ultraBle.use(new WebbleAdapter())
const ultraNode = new ChameleonUltra()
ultraNode.use(new SerialPortAdapter())
Static
VERSION_The supported version of SDK.
Readonly
gte: "2.0"Readonly
lt: "3.0"Automatically change the device mode to mode
if the current device mode is not equal to mode
.
Get the ble address of device.
The ble address of device.
async function run (ultra) {
console.log(await ultra.cmdBleGetAddress()) // 'E8:B6:3D:04:B6:FE'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get current ble pairing key of device.
The ble pairing key.
async function run (ultra) {
console.log(await ultra.cmdBleGetPairingKey()) // '123456'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the ble pairing mode of device.
true
if pairing is required to connect to device, otherwise return false
.
async function run (ultra) {
console.log(await ultra.cmdBleGetPairingMode()) // false
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the ble pairing key of device.
The new ble pairing key.
async function run (ultra) {
await ultra.cmdBleSetPairingKey('123456')
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set if the ble pairing is required when connecting to device.
true
to enable pairing mode, false
to disable pairing mode.
async function run (ultra) {
await ultra.cmdBleSetPairingMode(false)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Change device mode to tag reader or tag emulator.
The mode to be changed.
async function run (ultra) {
const { DeviceMode } = window.ChameleonUltraJS
await ultra.cmdChangeDeviceMode(DeviceMode.TAG)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the animation mode of device while wake-up and sleep.
The animation mode of device.
async function run (ultra) {
const { AnimationMode } = window.ChameleonUltraJS
const mode = await ultra.cmdGetAnimationMode()
console.log(AnimationMode[mode]) // 'FULL'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get current firmware version of device.
Current firmware version of device.
async function run (ultra) {
console.log(await ultra.cmdGetAppVersion()) // '1.0'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the battery info of device.
The battery info of device.
async function run (ultra) {
const battery = await ultra.cmdGetBatteryInfo()
console.log(JSON.stringify(battery)) // { "voltage": 4192, "level": 99 }
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the button long press action of specified button.
The button to be get.
The button long press action of specified button.
async function run (ultra) {
const { ButtonAction, ButtonType } = window.ChameleonUltraJS
const btnAction = await ultra.cmdGetButtonLongPressAction(ButtonType.BUTTON_A)
console.log(ButtonAction[btnAction]) // 'CLONE_IC_UID'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the button press action of specified button.
The button to be get.
The button press action of specified button.
async function run (ultra) {
const { ButtonAction, ButtonType } = window.ChameleonUltraJS
const btnAction = await ultra.cmdGetButtonPressAction(ButtonType.BUTTON_A)
console.log(ButtonAction[btnAction]) // 'CYCLE_SLOT_INC'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get chipset id of device in hex format.
Chipset id of device in hex format.
async function run (ultra) {
console.log(await ultra.cmdGetDeviceChipId()) // 'db1c624228d9634c'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get current mode of device.
Current mode of device.
async function run (ultra) {
const { DeviceMode } = window.ChameleonUltraJS
const deviceMode = await ultra.cmdGetDeviceMode()
console.log(DeviceMode[deviceMode]) // 'TAG'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the device is ChameleonUltra or ChameleonLite.
true
if device is ChameleonUltra, false
if device is ChameleonLite.
async function run (ultra) {
const { DeviceModel } = window.ChameleonUltraJS
const model = await ultra.cmdGetDeviceModel()
console.log(DeviceModel[model]) // 'ULTRA'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the settings of device.
The settings of device.
async function run (ultra) {
const settings = await ultra.cmdGetDeviceSettings()
console.log(JSON.stringify(settings)
/**
* {
* "version": 5,
* "animation": 0,
* "buttonPressAction": [1, 2],
* "buttonLongPressAction": [3, 3],
* "blePairingMode": false,
* "blePairingKey": "123456"
* }
*/
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the git version of firmware.
The git version of firmware.
async function run (ultra) {
console.log(await ultra.cmdGetGitVersion()) // '98605be'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the cmds supported by device.
The cmds supported by device.
async function run (ultra) {
const cmds = await ultra.cmdGetSupportedCmds()
console.log(cmds.size) // 67
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the animation mode of device while wake-up and sleep.
The animation mode to be set.
async function run (ultra) {
const { AnimationMode } = window.ChameleonUltraJS
await ultra.cmdSetAnimationMode(AnimationMode.SHORT)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the button long press action of specified button.
The button to be set.
The button long press action to be set.
async function run (ultra) {
const { ButtonAction, ButtonType } = window.ChameleonUltraJS
await ultra.cmdSetButtonLongPressAction(ButtonType.BUTTON_A, ButtonAction.CYCLE_SLOT_INC)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the button press action of specified button.
The button to be set.
The button press action to be set.
async function run (ultra) {
const { ButtonAction, ButtonType } = window.ChameleonUltraJS
await ultra.cmdSetButtonPressAction(ButtonType.BUTTON_A, ButtonAction.CYCLE_SLOT_INC)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Permanently wipes Chameleon to factory settings. This will delete all your slot data and custom settings. There's no going back.
async function run (ultra) {
await ultra.cmdWipeFds()
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
To check if the specified cmd is supported by device.
true
if the specified cmd is supported by device, otherwise return false
.
async function run (ultra) {
console.log(await ultra.isCmdSupported(Cmd.GET_APP_VERSION)) // true
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Check if the firmware version is supported by SDK.
true
if the firmware version is supported, false
otherwise.
async function run (ultra) {
if (await ultra.isSupportedAppVersion()) throw new Error('Firmware version is not supported. Please update the firmware.')
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Change the emulation tag type of specified slot.
async function run (ultra) {
const { Slot, TagType } = window.ChameleonUltraJS
await ultra.cmdSlotChangeTagType(Slot.SLOT_1, TagType.MIFARE_1024)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Delete the nick name of the slot
true
if success, false
if slot name is empty.
async function run (ultra) {
const { Slot, FreqType } = window.ChameleonUltraJS
console.log(await ultra.cmdSlotDeleteFreqName(Slot.SLOT_1, FreqType.HF)) // true
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Delete the emulation tag data of specified freq type in specified slot.
async function run (ultra) {
const { Slot, FreqType } = window.ChameleonUltraJS
await ultra.cmdSlotDeleteFreqType(Slot.SLOT_1, FreqType.HF)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the active emulation tag slot of device.
The active slot of device.
async function run (ultra) {
const { Slot } = window.ChameleonUltraJS
const slot = await ultra.cmdSlotGetActive()
console.log(Slot[slot]) // 'SLOT_1'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the nickname of specified freq type in specified slot.
The nickname of specified freq type in specified slot.
async function run (ultra) {
const { Slot, FreqType } = window.ChameleonUltraJS
const name = await ultra.cmdSlotGetFreqName(Slot.SLOT_1, FreqType.HF)
console.log(name) // 'My Tag'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the slot info of all slots.
The slot info of all slots.
async function run (ultra) {
const slots = await ultra.cmdSlotGetInfo()
console.log(JSON.stringify(slots))
/**
* [
* { "hfTagType": 1001, "lfTagType": 100 },
* { "hfTagType": 1001, "lfTagType": 0 },
* { "hfTagType": 0, "lfTagType": 100 },
* { "hfTagType": 0, "lfTagType": 0 },
* { "hfTagType": 0, "lfTagType": 0 },
* { "hfTagType": 0, "lfTagType": 0 },
* { "hfTagType": 0, "lfTagType": 0 },
* { "hfTagType": 0, "lfTagType": 0 }
* ]
*/
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get enabled slots.
Enabled slots.
async function run (ultra) {
const enabledSlots = await ultra.cmdSlotGetIsEnable()
console.log(JSON.stringify(enabledSlots))
// [
// { "hf": true, "lf": true },
// { "hf": true, "lf": false },
// { "hf": false, "lf": true },
// { "hf": false, "lf": false },
// { "hf": false, "lf": false },
// { "hf": false, "lf": false },
// { "hf": false, "lf": false },
// { "hf": true, "lf": false }
// ]
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Reset the emulation tag data of specified tag type in specified slot to default values.
async function run (ultra) {
const { Slot, TagType } = window.ChameleonUltraJS
await ultra.cmdSlotResetTagType(Slot.SLOT_1, TagType.MIFARE_1024)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
The SlotSettings, hf tag data and lf tag data will be written to persistent storage. But the slot nickname is not affected by this command.
async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
await ultra.cmdMf1EmuWriteBlock(1, Buffer.alloc(16))
await ultra.cmdSlotSaveSettings()
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Change the active emulation tag slot of device.
The slot to be active.
async function run (ultra) {
const { Slot } = window.ChameleonUltraJS
await ultra.cmdSlotSetActive(Slot.SLOT_1)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Enable or disable the specified slot.
async function run (ultra) {
const { FreqType, Slot } = window.ChameleonUltraJS
await ultra.cmdSlotSetEnable(Slot.SLOT_1, FreqType.HF, true)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the nickname of specified freq type in specified slot.
async function run (ultra) {
const { Slot, FreqType } = window.ChameleonUltraJS
await ultra.cmdSlotSetFreqName(Slot.SLOT_1, FreqType.HF, 'My Tag')
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Scan em410x tag and print id
The id of em410x tag.
async function run (ultra) {
const id = await ultra.cmdEm410xScan()
console.log(id.toString('hex')) // 'deadbeef88'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Write id of em410x tag to t55xx tag.
The id of em410x tag.
async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
await ultra.cmdEm410xWriteToT55xx(Buffer.from('deadbeef88', 'hex'))
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Send raw NfcA data to a tag and receive the response.
Optional
activateSet true
to activate RF field. If data
is not empty or autoSelect
is true, activateRfField
will be set to true
.
Optional
appendSet true
to add CRC before sending data.
Optional
autoSet true
to automatically select card before sending data.
Optional
checkSet true
to verify CRC of response and remove. If CRC of response is valid, CRC will be removed from response, otherwise will throw HF_ERR_CRC error.
Optional
data?: BufferThe data to be send. If appendCrc
is true
, the maximum length of data is 62
, otherwise is 64
.
Optional
dataNumber of bits to send. Useful for send partial byte. dataBitLength
is incompatible with appendCrc
.
Optional
keepSet true
to keep the RF field active after sending.
Optional
timeout?: numberDefault value is 1000 ms
. Maximum timeout for reading tag response in ms while waitResponse
is true
.
Optional
waitDefault value is true
. Set false
to skip reading tag response.
The response from tag.
Scan 14a tag, and return basic information. The device mode must be set to READER before using this command.
The basic infomation of scanned tag.
This command will throw an error if tag not scanned or any error occured.
async function run (ultra) {
const antiColl = _.first(await ultra.cmdHf14aScan())
console.log(_.mapValues(antiColl, val => val.toString('hex')))
// { uid: '040dc4420d2981', atqa: '4400', sak: '00', ats: ''}
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the info composed of cmdHf14aScan()
and cmdMf1TestNtLevel()
.
The info about 14a tag and mifare protocol.
async function run (ultra) {
const { Mf1PrngType } = window.ChameleonUltraJS
const tag = _.first(await ultra.hf14aInfo())
console.log(tag.nxpTypeBySak) // 'MIFARE Classic 1K | Plus SE 1K | Plug S 2K | Plus X 2K'
console.log(Mf1PrngType[tag.prngType]) // 'WEAK'
console.log(_.mapValues(tag.antiColl, val => val.toString('hex')))
// { uid: 'dbe3d63d', atqa: '0400', sak: '08', ats: '' }
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the em410x id of actived slot.
The em410x id of actived slot.
async function run (ultra) {
const id = await ultra.cmdEm410xGetEmuId()
console.log(id.toString('hex')) // 'deadbeef88'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the em410x id of actived slot.
The em410x id of actived slot.
async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
await ultra.cmdEm410xSetEmuId(Buffer.from('deadbeef88', 'hex'))
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get anti-collision data from actived slot.
The anti-collision data from actived slot.
async function run (ultra) {
const res = await ultra.cmdHf14aGetAntiCollData()
console.log(JSON.stringify(res))
// {
// "uid": { "type": "Buffer", "data": [222, 173, 190, 239] },
// "atqa": { "type": "Buffer", "data": [4, 0] },
// "sak": { "type": "Buffer", "data": [8] },
// "ats": { "type": "Buffer", "data": [] }
// }
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the mifare anti-collision data of actived slot.
async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
await ultra.cmdHf14aSetAntiCollData({
atqa: Buffer.from('0400', 'hex'),
sak: Buffer.from('08', 'hex'),
uid: Buffer.from('01020304', 'hex')
})
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Magic auth helper function for mifare gen1a tag.
The callback function to be executed after auth.
The result of callback function.
Acquire the data from mifare darkside attack.
The target block.
The target key type.
true
if this is the first attack.
The max sync count of darkside attack.
The data from mifare darkside attack.
async function run (ultra) {
const { Mf1KeyType, DarksideStatus } = window.ChameleonUltraJS
const res1 = await ultra.cmdMf1AcquireDarkside(0, Mf1KeyType.KEY_A, true)
console.log(res1)
const res2 = {
status: `${DarksideStatus[res1.status]} (${res1.status})`,
...(res1.status !== DarksideStatus.OK ? {} : {
ar: res1.ar.toString('hex'),
ks: res1.ks.toString('hex'),
nr: res1.nr.toString('hex'),
nt: res1.nt.toString('hex'),
par: res1.par.toString('hex'),
uid: res1.uid.toString('hex'),
}),
}
console.log(res2)
// {
// "ar": "00000000",
// "ks": "0c0508080f04050a",
// "nr": "00000000",
// "nt": "b346fc3d",
// "par": "0000000000000000",
// "status": "OK (0)",
// "uid": "d3efed0c"
// }
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
If you want to use darkside attack to recover the key, you can use the following example code:
async function run (ultra) {
const { Buffer, DarksideStatus, Mf1KeyType } = window.ChameleonUltraJS
const block = 0
const keyType = Mf1KeyType.KEY_A
const key = await Crypto1.darkside(
async attempt => {
const accquired = await ultra.cmdMf1AcquireDarkside(block, keyType, attempt === 0)
console.log(_.mapValues(accquired, buf => Buffer.isBuffer(buf) ? buf.toString('hex') : buf))
if (acquired.status === DarksideStatus.LUCKY_AUTH_OK) throw new Error('LUCKY_AUTH_OK')
if (acquired.status !== DarksideStatus.OK) throw new Error('card is not vulnerable to Darkside attack')
return accquired
},
async key => {
return await ultra.cmdMf1CheckBlockKey({ block, keyType, key })
},
)
console.log(`key founded: ${key.toString('hex')}`)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Use a known key to do the mifare nested attack.
The info of known key.
The block of known key.
The known key.
The key type of known key.
The info of target key to be attack.
The block of target key.
The key type of target key.
The result of mifare nested attack.
async function run (ultra) {
const { Buffer, Mf1KeyType } = window.ChameleonUltraJS
const key = Buffer.from('FFFFFFFFFFFF', 'hex')
const res1 = await ultra.cmdMf1TestNtDistance({ block: 0, keyType: Mf1KeyType.KEY_A, key })
const res2 = await ultra.cmdMf1AcquireNested(
{ block: 0, keyType: Mf1KeyType.KEY_A, key },
{ block: 4, keyType: Mf1KeyType.KEY_A },
)
const res = {
uid: res1.uid.toString('hex'),
dist: res1.dist.toString('hex'),
atks: _.map(res2, item => ({
nt1: item.nt1.toString('hex'),
nt2: item.nt2.toString('hex'),
par: item.par,
}))
}
console.log(res)
// {
// uid: '877209e1',
// dist: '00000080',
// atks: [
// { nt1: '35141fcb', nt2: '40430522', par: 7 },
// { nt1: 'cff2b3ef', nt2: '825ba8ea', par: 5 },
// ]
// }
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Use a known key to do the mifare static nested attack.
The info of known key.
The block of known key.
The known key.
The key type of known key.
The info of target key to be attack.
The block of target key.
The key type of target key.
The result of mifare static nested attack.
async function run (ultra) {
const { Buffer, Mf1KeyType } = window.ChameleonUltraJS
const key = Buffer.from('FFFFFFFFFFFF', 'hex')
const res1 = await ultra.cmdMf1AcquireStaticNested({
block: 0,
keyType: Mf1KeyType.KEY_A,
key
}, {
block: 4,
keyType: Mf1KeyType.KEY_A
})
const res = {
uid: res1.uid.toString('hex'),
atks: _.map(res1.atks, item => ({ nt1: item.nt1.toString('hex'), nt2: item.nt2.toString('hex') })),
}
console.log(res)
// {
// uid: 'b908a16d',
// atks: [
// { nt1: '01200145', nt2: '81901975' },
// { nt1: '01200145', nt2: 'cdd400f3' },
// ],
// }
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Check if the key is valid for specified block and key type.
The info of key to be checked.
The block of key to be checked.
The key to be checked.
The type of key to be checked.
true
if the key is valid for specified block and key type.
async function run (ultra) {
const { Buffer, Mf1KeyType } = window.ChameleonUltraJS
const key = Buffer.from('FFFFFFFFFFFF', 'hex')
console.log(await ultra.cmdMf1CheckBlockKey({
block: 0,
keyType: Mf1KeyType.KEY_A,
key,
})) // true
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Given a list of keys, check which is the correct key A and key B of the sectors. If you want to check more than 83 keys, you can use mf1CheckKeysOfSectors()
.
found
: 80 bits, 2 bits/sector, the first bit is key A, the second bit is key B, 0b1
represent key is found.sectorKeys
: 80 keys, 2 keys/sector, the first key is key A, the second key is key B. null
represent key is not found.async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
const mask = Buffer.from('00000000FFFFFFFFFFFF', 'hex')
const keys = Buffer.from('FFFFFFFFFFFF\n000000000000\nA0A1A2A3A4A5\nD3F7D3F7D3F7', 'hex').chunk(6)
const tsStart = Date.now()
const result = await ultra.cmdMf1CheckKeysOfSectors({ keys, mask })
console.log(`Time: ${Date.now() - tsStart}ms`)
const replacer = function (k, v) { return Buffer.isBuffer(this[k]) ? this[k].toString('hex') : v }
console.log(JSON.stringify(result, replacer, 2))
}
// {
// "found": "ffffffff000000000000",
// "sectorKeys": [
// "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
// "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
// "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
// "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
// "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
// "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
// "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
// "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
// null, null, null, null,
// null, null, null, null,
// null, null, null, null,
// null, null, null, null,
// null, null, null, null,
// null, null, null, null,
// null, null, null, null,
// null, null, null, null,
// null, null, null, null,
// null, null, null, null,
// null, null, null, null,
// null, null, null, null,
// ]
// }
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the mifare block data of actived slot.
The start block of actived slot.
The count of blocks to be get.
The mifare block data of actived slot.
async function run (ultra) {
const data = await ultra.cmdMf1EmuReadBlock(1)
console.log(data.toString('hex')) // '00000000000000000000000000000000'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the mifare block data of actived slot.
The start block of actived slot.
The data to be set. the length of data should be multiples of 16.
async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
await ultra.cmdMf1EmuWriteBlock(1, Buffer.alloc(16))
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the mode of actived slot that using anti-collision data from block 0 for 4 byte UID tags or not.
The mode of actived slot that using anti-collision data from block 0 for 4 byte UID tags or not.
async function run (ultra) {
console.log(await ultra.cmdMf1GetAntiCollMode()) // false
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the count of mifare MFKey32 detections.
The count of mifare MFKey32 detections.
async function run (ultra) {
console.log(await ultra.cmdMf1GetDetectionCount()) // 0
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the feature of mifare MFKey32 detections is enabled or not.
true
if the feature of mifare MFKey32 detections is enabled, otherwise return false
.
async function run (ultra) {
console.log(await ultra.cmdMf1GetDetectionEnable()) // false
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the data of mifare MFKey32 detections.
The start log of detections to be get.
The mifare MFKey32 detections.
async function run (ultra) {
const logs = await ultra.cmdMf1GetDetectionLogs(0)
console.log(logs)
/**
* {
* "block": 2,
* "isKeyB": 1,
* "isNested": 0,
* "uid": Buffer.from('65535d33', 'hex'),
* "nt": Buffer.from('cb7b9ed9', 'hex'),
* "nr": Buffer.from('5a8ffec6', 'hex'),
* "ar": Buffer.from('5c7c6f89', 'hex'),
* }
*/
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the mifare settings of actived slot.
The mifare settings of actived slot.
async function run (ultra) {
const mf1Settings = await ultra.cmdMf1GetEmuSettings()
console.log(JSON.stringify(mf1Settings))
/**
* {
* "detection": false,
* "gen1a": false,
* "gen2": false,
* "antiColl": false,
* "write": 0
* }
*/
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the mifare gen1a mode of actived slot.
The mifare gen1a mode of actived slot.
async function run (ultra) {
console.log(await ultra.cmdMf1GetGen1aMode()) // false
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the mifare gen2 mode of actived slot.
The mifare gen2 mode of actived slot.
async function run (ultra) {
console.log(await ultra.cmdMf1GetGen2Mode()) // false
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get the mifare write mode of actived slot.
The mifare write mode of actived slot.
async function run (ultra) {
console.log(await ultra.cmdMf1GetWriteMode()) // 0
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Test whether it is mifare classic tag.
true
if tag is mifare classic tag, otherwise return false
.
async function run (ultra) {
console.log(await ultra.cmdMf1IsSupport()) // true
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Read block data from a mifare tag.
The block to be read and the key info of the block.
The block to be read.
The key of the block.
The key type of the block.
The block data read from a mifare tag.
async function run (ultra) {
const { Buffer, Mf1KeyType } = window.ChameleonUltraJS
const key = Buffer.from('FFFFFFFFFFFF', 'hex')
const block1 = await ultra.cmdMf1ReadBlock({
block: 1,
keyType: Mf1KeyType.KEY_A,
key,
})
console.log(block1.toString('hex')) // '00000000000000000000000000000000'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the mode of actived slot that using anti-collision data from block 0 for 4 byte UID tags or not.
true
to enable the mode, false
to disable the mode.
async function run (ultra) {
await ultra.cmdMf1SetAntiCollMode(false)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Enable or disable the mifare MFKey32 detection and clear the data of detections.
true
to enable the detection, false
to disable the detection.
async function run (ultra) {
await ultra.cmdMf1SetDetectionEnable(true)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the mifare gen1a mode of actived slot.
true
to enable the gen1a mode, false
to disable the gen1a mode.
async function run (ultra) {
await ultra.cmdMf1SetGen1aMode(false)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the mifare gen2 mode of actived slot.
true
to enable the gen2 mode, false
to disable the gen2 mode.
async function run (ultra) {
await ultra.cmdMf1SetGen2Mode(false)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set the mifare write mode of actived slot.
The mifare write mode of actived slot.
async function run (ultra) {
const { Mf1EmuWriteMode } = window.ChameleonUltraJS
await ultra.cmdMf1SetWriteMode(Mf1EmuWriteMode.NORMAL)
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Dectect the nt distance of mifare protocol.
The info of known key.
The block of known key.
The known key.
The key type of known key.
The nt distance of mifare protocol.
async function run (ultra) {
const { Buffer, Mf1KeyType } = window.ChameleonUltraJS
const key = Buffer.from('FFFFFFFFFFFF', 'hex')
const res1 = await ultra.cmdMf1TestNtDistance({ block: 0, keyType: Mf1KeyType.KEY_A, key })
const res2 = await ultra.cmdMf1AcquireNested(
{ block: 0, keyType: Mf1KeyType.KEY_A, key },
{ block: 4, keyType: Mf1KeyType.KEY_A },
)
const res = {
uid: res1.uid.toString('hex'),
dist: res1.dist.toString('hex'),
atks: _.map(res2, item => ({
nt1: item.nt1.toString('hex'),
nt2: item.nt2.toString('hex'),
par: item.par,
}))
}
console.log(res)
// {
// uid: '877209e1',
// dist: '00000080',
// atks: [
// { nt1: '35141fcb', nt2: '40430522', par: 7 },
// { nt1: 'cff2b3ef', nt2: '825ba8ea', par: 5 },
// ]
// }
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Check the nt level of mifare protocol.
The nt level of mifare protocol.
async function run (ultra) {
const { Mf1PrngType } = window.ChameleonUltraJS
console.log(Mf1PrngType[await ultra.cmdMf1TestPrngType()]) // 'WEAK'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
MIFARE Classic manipulate value block
X
(0
~ 2147483647
) from src to dstX
(0
~ 2147483647
) from src to dstThe key info of src block.
The block of src block.
The key of src block.
The key type of src block.
The operator of value block.
The operand of value block.
The key info of dst block.
The block of dst block.
The key of dst block.
The key type of dst block.
async function run (ultra) {
const { Buffer, Mf1KeyType, Mf1VblockOperator } = window.ChameleonUltraJS
const key = Buffer.from('FFFFFFFFFFFF', 'hex')
const src = { block: 4, keyType: Mf1KeyType.KEY_A, key }
await ultra.mf1VblockSetValue(src, { value: 2 })
console.log(await ultra.mf1VblockGetValue(src))
await ultra.cmdMf1VblockManipulate(
{ block: 4, keyType: Mf1KeyType.KEY_A, key },
Mf1VblockOperator.DECREMENT, 1,
{ block: 4, keyType: Mf1KeyType.KEY_A, key },
)
console.log(await ultra.mf1VblockGetValue(src))
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Write data to a mifare tag.
The block to be written and the key info of the block.
The block to be written.
The block data to be written.
The key of the block.
The key type of the block.
async function run (ultra) {
const { Buffer, Mf1KeyType } = window.ChameleonUltraJS
const key = Buffer.from('FFFFFFFFFFFF', 'hex')
const block1 = Buffer.from('00000000000000000000000000000000', 'hex')
await ultra.cmdMf1WriteBlock({
block: 1,
keyType: Mf1KeyType.KEY_A,
key,
data: block1,
})
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Mifare Classic check keys of sectors.
Optional
chunkkeys
will be chunked by this size.
The keys to be checked.
Optional
mask?: BufferThe mask of sectors. 80 bits, 2 bits/sector, the first bit is key A, the second bit is key B, 0b1 represent to skip checking the key.
Optional
maxThe max sectors to be check.
Optional
onThe callback function to be invoked before checking every chunk of keys.
Given a list of keys, check which is the correct key A and key B of the sector.
The sector number to be checked.
The keys dictionary.
The Key A and Key B of the sector.
async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
const keys = Buffer.from('FFFFFFFFFFFF\n000000000000\nA0A1A2A3A4A5\nD3F7D3F7D3F7', 'hex').chunk(6)
const sectorKey = await ultra.mf1CheckSectorKeys(0, keys)
console.log(_.mapValues(sectorKey, key => key.toString('hex')))
// { "96": "ffffffffffff", "97": "ffffffffffff" }
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Read blocks from Mifare Classic Gen1a.
The start block of Mifare Classic Gen1a.
The amount of blocks to read.
The blocks data.
async function run (ultra) {
const card = await ultra.mf1Gen1aReadBlocks(0, 64)
console.log(_.map(card.chunk(16), chunk => chunk.toString('hex')).join('\n'))
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Write blocks to Mifare Classic Gen1a.
The start block of Mifare Classic Gen1a.
The blocks data to write.
async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
await ultra.mf1Gen1aWriteBlocks(1, new Buffer(16))
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Check acl bytes of ACL, block or sector.
Data of ACL, block or sector.
true
if the acl bytes is valid, false
otherwise.
async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
console.log(ultra.mf1IsValidAcl(Buffer.from('ff078069', 'hex'))) // true
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Read the sector data of Mifare Classic by given keys.
The sector number to be read.
The keys dictionary.
The sector data and the read status of each block.
async function run (ultra) {
const { Buffer, Mf1KeyType } = window.ChameleonUltraJS
const keys = Buffer.from('FFFFFFFFFFFF\n000000000000\nA0A1A2A3A4A5\nD3F7D3F7D3F7', 'hex').chunk(6)
const { data, success } = await ultra.mf1ReadSectorByKeys(0, keys)
console.log({ data: data.toString('hex'), success })
// { "data": "...", "success": [true, true, true, true] }
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Get value from opts
block (MIFARE Classic value block)
The key info of opts
block.
The block of opts
block.
The key of opts
block.
The key type of opts
block.
The value and address of opts
block.
async function run (ultra) {
const { Buffer, Mf1KeyType, Mf1VblockOperator } = window.ChameleonUltraJS
const key = Buffer.from('FFFFFFFFFFFF', 'hex')
const src = { block: 4, keyType: Mf1KeyType.KEY_A, key }
await ultra.mf1VblockSetValue(src, { value: 2 })
console.log(await ultra.mf1VblockGetValue(src))
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Set value X (-2147483647 ~ 2147483647) to dst
block (MIFARE Classic value block)
The key info of dst
block.
The block of dst
block.
The key of dst
block.
The key type of dst
block.
The value and address to be set.
Optional
adr?: numberThe address to be set. Default is dst.block
.
Optional
value?: numberThe value to be set. Default is 0
.
async function run (ultra) {
const { Buffer, Mf1KeyType, Mf1VblockOperator } = window.ChameleonUltraJS
const key = Buffer.from('FFFFFFFFFFFF', 'hex')
const src = { block: 4, keyType: Mf1KeyType.KEY_A, key }
await ultra.mf1VblockSetValue(src, { value: 2 })
console.log(await ultra.mf1VblockGetValue(src))
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Write the sector data of Mifare Classic by given keys.
the write status of each block.
async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
const keys = Buffer.from('FFFFFFFFFFFF\n000000000000\nA0A1A2A3A4A5\nD3F7D3F7D3F7', 'hex').chunk(6)
const data = Buffer.concat([
Buffer.from('00000000000000000000000000000000', 'hex'),
Buffer.from('00000000000000000000000000000000', 'hex'),
Buffer.from('00000000000000000000000000000000', 'hex'),
Buffer.from('ffffffffffffff078069ffffffffffff', 'hex'),
])
const { success } = await ultra.mf1WriteSectorByKeys(1, keys, data)
console.log(success)
// [true, true, true, true]
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Static
mf1Get the blockNo of sector trailer.
The sector number.
The blockNo of sector trailer.
async function run () {
const { ChameleonUltra } = window.ChameleonUltraJS
console.log(ChameleonUltra.mf1TrailerBlockNoOfSector(0))
// 3
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Read 4 pages (16 bytes) from Mifare Ultralight
page number to read
4 pages (16 bytes)
MF0ICU1 MIFARE Ultralight contactless single-ticket IC
async function run (ultra) {
const data = await ultra.mfuReadPages({ pageOffset: 0 })
console.log(data.toString('hex')) // '040dc445420d2981e7480000e1100600'
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Write 1 page (4 bytes) to Mifare Ultralight
MF0ICU1 MIFARE Ultralight contactless single-ticket IC
async function run (ultra) {
const { Buffer } = window.ChameleonUltraJS
const data = await ultra.mfuWritePage({ pageOffset: 9, data: Buffer.from('00000000', 'hex') })
}
await run(vm.ultra) // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
Register a hook.
The hook name.
The function to register.
Invoke a hook with context.
The hook name.
The context will be passed to every middleware.
Optional
next: MiddlewareComposeFnThe next middleware function.
The return value depent on the middlewares
Register a plugin.
The plugin to register.
Optional
option: anyThe option to pass to plugin.install().
Internal
debugInternal
deviceInternal
hooksInternal
isInternal
loggerInternal
pluginsOptional
Internal
portOptional
Internal
rxInternal
supportedInternal
Calculate the LRC byte of a buffer.
Internal
Read a response from device.
Internal
Send a command to device.
The command to be sent to device.
Optional
data?: Buffer<= 512 bytes
, the data to be sent. This payload depends on the exact command being used. See Packet payloads for more infomation.
Optional
status?: RespStatusThe status is always 0x0000
.
The core library of "chameleon-ultra.js". The instance of this class must use exactly one adapter plugin to communication to ChameleonUltra.