mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-21 22:03:19 -07:00
Adds lf hid pack
and lf hid unpack
offline commands.
These are used to pack and unpack the bit length, facility code and card number from "short" HID Prox IDs. This also simplifies some repeated code that is used to parse hex digits in lfhid, and adds basic client-side validation to the `lf hid clone` and `lf hid sim` commands, for when an ID that is too long is entered.
This commit is contained in:
parent
fdee1ffa84
commit
f87f5a7433
2 changed files with 236 additions and 56 deletions
|
@ -18,9 +18,142 @@
|
|||
#include "cmdparser.h"
|
||||
#include "cmddata.h" //for g_debugMode, demodbuff cmds
|
||||
#include "lfdemod.h" // for HIDdemodFSK
|
||||
#include "util.h" // for param_get8,32
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
||||
/**
|
||||
* Packs a "short" (<38-bit) HID ID from component parts.
|
||||
*
|
||||
* This only works with 26, 34, 35 and 37 bit card IDs.
|
||||
*
|
||||
* Returns false on invalid inputs.
|
||||
*/
|
||||
bool pack_short_hid(/* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const short_hid_info *info) {
|
||||
uint32_t high = 0, low = 0;
|
||||
|
||||
switch (info->fmtLen) {
|
||||
case 26:
|
||||
low |= (info->cardnum & 0xffff) << 1;
|
||||
low |= (info->fc & 0xff) << 17;
|
||||
break;
|
||||
|
||||
case 34:
|
||||
low |= (info->cardnum & 0xffff) << 1;
|
||||
low |= (info->fc & 0x7fff) << 17;
|
||||
high |= (info->fc & 0x8000) >> 15;
|
||||
break;
|
||||
|
||||
case 35:
|
||||
low |= (info->cardnum & 0xfffff) << 1;
|
||||
low |= (info->fc & 0x7ff) << 21;
|
||||
high |= (info->fc & 0x800) >> 11;
|
||||
break;
|
||||
|
||||
case 37:
|
||||
low |= (info->cardnum & 0x7ffff) << 1;
|
||||
low |= (info->fc & 0xfff) << 20;
|
||||
high |= (info->fc & 0xf000) >> 12;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Invalid / unsupported length
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the highest bit
|
||||
if (info->fmtLen != 37) {
|
||||
// Bit 37 is always set
|
||||
high |= 0x20;
|
||||
|
||||
// Set the bit corresponding to the length.
|
||||
if (info->fmtLen < 32) {
|
||||
low |= 1 << info->fmtLen;
|
||||
} else {
|
||||
high |= 1 << (info->fmtLen - 32);
|
||||
}
|
||||
}
|
||||
|
||||
// Return result only if successful.
|
||||
*hi = high;
|
||||
*lo = low;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unpacks a "short" (<38-bit) HID ID into its component parts.
|
||||
*
|
||||
* This only works with 26, 34, 35 and 37 bit card IDs.
|
||||
*
|
||||
* Returns false on invalid inputs.
|
||||
*/
|
||||
bool unpack_short_hid(short_hid_info *out, uint32_t hi, uint32_t lo) {
|
||||
memset(out, 0, sizeof(short_hid_info));
|
||||
|
||||
if (((hi >> 5) & 1) == 1) {
|
||||
// if bit 38 is set then < 37 bit format is used
|
||||
uint32_t lo2 = 0;
|
||||
// get bits 21-37 to check for format len bit
|
||||
lo2 = (((hi & 31) << 12) | (lo >> 20));
|
||||
uint8_t idx3 = 1;
|
||||
// find last bit set to 1 (format len bit)
|
||||
while (lo2 > 1) {
|
||||
lo2 = lo2 >> 1;
|
||||
idx3++;
|
||||
}
|
||||
|
||||
out->fmtLen = idx3 + 19;
|
||||
|
||||
switch (out->fmtLen) {
|
||||
case 26:
|
||||
out->cardnum = (lo >> 1) & 0xFFFF;
|
||||
out->fc = (lo >> 17) & 0xFF;
|
||||
break;
|
||||
|
||||
case 34:
|
||||
out->cardnum = (lo >> 1) & 0xFFFF;
|
||||
out->fc = ((hi & 1) << 15) | (lo >> 17);
|
||||
break;
|
||||
|
||||
case 35:
|
||||
out->cardnum = (lo >> 1) & 0xFFFFF;
|
||||
out->fc = ((hi & 1) << 11) | (lo >> 21);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// if bit 38 is not set then 37 bit format is used
|
||||
out->fmtLen = 37;
|
||||
out->cardnum = (lo >> 1) & 0x7FFFF;
|
||||
out->fc = ((hi & 0xF) << 12) | (lo >> 20);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a hex string to component "hi" and "lo" 32-bit integers, one nibble
|
||||
* at a time.
|
||||
*
|
||||
* Returns the number of nibbles (4 bits) entered.
|
||||
*/
|
||||
int hexstring_to_int64(/* out */ uint32_t* hi, /* out */ uint32_t* lo, const char* str) {
|
||||
// TODO: Replace this with param_gethex when it supports arbitrary length
|
||||
// inputs.
|
||||
int n = 0, i = 0;
|
||||
|
||||
while (sscanf(&str[i++], "%1x", &n ) == 1) {
|
||||
*hi = (*hi << 4) | (*lo >> 28);
|
||||
*lo = (*lo << 4) | (n & 0xf);
|
||||
}
|
||||
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
//by marshmellow (based on existing demod + holiman's refactor)
|
||||
//HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
|
||||
//print full HID Prox ID and some bit format details if found
|
||||
|
@ -60,45 +193,14 @@ int CmdFSKdemodHID(const char *Cmd)
|
|||
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
|
||||
}
|
||||
else { //standard HID tags <38 bits
|
||||
uint8_t fmtLen = 0;
|
||||
uint32_t fc = 0;
|
||||
uint32_t cardnum = 0;
|
||||
if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used
|
||||
uint32_t lo2=0;
|
||||
lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit
|
||||
uint8_t idx3 = 1;
|
||||
while(lo2>1){ //find last bit set to 1 (format len bit)
|
||||
lo2=lo2>>1;
|
||||
idx3++;
|
||||
}
|
||||
fmtLen =idx3+19;
|
||||
fc =0;
|
||||
cardnum=0;
|
||||
if(fmtLen==26){
|
||||
cardnum = (lo>>1)&0xFFFF;
|
||||
fc = (lo>>17)&0xFF;
|
||||
}
|
||||
if(fmtLen==34){
|
||||
cardnum = (lo>>1)&0xFFFF;
|
||||
fc= ((hi&1)<<15)|(lo>>17);
|
||||
}
|
||||
if(fmtLen==35){
|
||||
cardnum = (lo>>1)&0xFFFFF;
|
||||
fc = ((hi&1)<<11)|(lo>>21);
|
||||
}
|
||||
}
|
||||
else { //if bit 38 is not set then 37 bit format is used
|
||||
fmtLen = 37;
|
||||
fc = 0;
|
||||
cardnum = 0;
|
||||
if(fmtLen == 37){
|
||||
cardnum = (lo>>1)&0x7FFFF;
|
||||
fc = ((hi&0xF)<<12)|(lo>>20);
|
||||
}
|
||||
}
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
|
||||
short_hid_info card_info;
|
||||
bool ret = unpack_short_hid(&card_info, (uint32_t)hi, (uint32_t)lo);
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
|
||||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
(unsigned int) fmtLen, (unsigned int) fc, (unsigned int) cardnum);
|
||||
card_info.fmtLen, card_info.fc, card_info.cardnum);
|
||||
if (!ret) {
|
||||
PrintAndLog("Invalid or unsupported tag length.");
|
||||
}
|
||||
}
|
||||
setDemodBuf(BitStream,BitLen,idx);
|
||||
setClockGrid(50, waveIdx + (idx*50));
|
||||
|
@ -112,7 +214,7 @@ int CmdFSKdemodHID(const char *Cmd)
|
|||
int CmdHIDReadFSK(const char *Cmd)
|
||||
{
|
||||
int findone=0;
|
||||
if(Cmd[0]=='1') findone=1;
|
||||
if(Cmd[0]=='1') findone=1;
|
||||
UsbCommand c={CMD_HID_DEMOD_FSK};
|
||||
c.arg[0]=findone;
|
||||
SendCommand(&c);
|
||||
|
@ -121,30 +223,30 @@ int CmdHIDReadFSK(const char *Cmd)
|
|||
|
||||
int CmdHIDSim(const char *Cmd)
|
||||
{
|
||||
uint32_t hi = 0, lo = 0;
|
||||
int n = 0, i = 0;
|
||||
uint32_t hi = 0, lo = 0;
|
||||
hexstring_to_int64(&hi, &lo, Cmd);
|
||||
if (hi >= 0x40) {
|
||||
PrintAndLog("This looks like a long tag ID. Use 'lf simfsk' for long tags. Aborting!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (n & 0xf);
|
||||
}
|
||||
PrintAndLog("Emulating tag with ID %x%08x", hi, lo);
|
||||
PrintAndLog("Press pm3-button to abort simulation");
|
||||
|
||||
PrintAndLog("Emulating tag with ID %x%08x", hi, lo);
|
||||
PrintAndLog("Press pm3-button to abort simulation");
|
||||
|
||||
UsbCommand c = {CMD_HID_SIM_TAG, {hi, lo, 0}};
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
UsbCommand c = {CMD_HID_SIM_TAG, {hi, lo, 0}};
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHIDClone(const char *Cmd)
|
||||
{
|
||||
unsigned int hi2 = 0, hi = 0, lo = 0;
|
||||
int n = 0, i = 0;
|
||||
UsbCommand c;
|
||||
|
||||
if (strchr(Cmd,'l') != 0) {
|
||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
||||
int n = 0, i = 0;
|
||||
|
||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
||||
hi2 = (hi2 << 4) | (hi >> 28);
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (n & 0xf);
|
||||
|
@ -155,9 +257,10 @@ int CmdHIDClone(const char *Cmd)
|
|||
c.d.asBytes[0] = 1;
|
||||
}
|
||||
else {
|
||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (n & 0xf);
|
||||
hexstring_to_int64(&hi, &lo, Cmd);
|
||||
if (hi >= 0x40) {
|
||||
PrintAndLog("This looks like a long tag ID. Aborting!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
PrintAndLog("Cloning tag with ID %x%08x", hi, lo);
|
||||
|
@ -175,6 +278,63 @@ int CmdHIDClone(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHIDPack(const char *Cmd) {
|
||||
uint32_t hi = 0, lo = 0;
|
||||
short_hid_info card_info;
|
||||
|
||||
if (strlen(Cmd)<3) {
|
||||
PrintAndLog("Usage: lf hid pack <length> <facility code (decimal)> <card number (decimal)>");
|
||||
PrintAndLog(" sample: lf hid pack 34 111 2345");
|
||||
return 0;
|
||||
}
|
||||
|
||||
card_info.fmtLen = param_get8(Cmd, 0);
|
||||
card_info.fc = param_get32ex(Cmd, 1, 0, 10);
|
||||
card_info.cardnum = param_get32ex(Cmd, 2, 0, 10);
|
||||
|
||||
bool ret = pack_short_hid(&hi, &lo, &card_info);
|
||||
|
||||
if (ret) {
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
|
||||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
card_info.fmtLen, card_info.fc, card_info.cardnum);
|
||||
} else {
|
||||
PrintAndLog("Invalid or unsupported tag length.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHIDUnpack(const char *Cmd)
|
||||
{
|
||||
uint32_t hi = 0, lo = 0;
|
||||
if (strlen(Cmd)<1) {
|
||||
PrintAndLog("Usage: lf hid unpack <ID>");
|
||||
PrintAndLog(" sample: lf hid unpack 2400de1252");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hexstring_to_int64(&hi, &lo, Cmd);
|
||||
if (hi >= 0x40) {
|
||||
PrintAndLog("This looks like a long tag ID. Aborting!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
short_hid_info card_info;
|
||||
bool ret = unpack_short_hid(&card_info, hi, lo);
|
||||
|
||||
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
|
||||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
card_info.fmtLen, card_info.fc, card_info.cardnum);
|
||||
|
||||
if (!ret) {
|
||||
PrintAndLog("Invalid or unsupported tag length.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
|
@ -182,6 +342,8 @@ static command_t CommandTable[] =
|
|||
{"read", CmdHIDReadFSK, 0, "['1'] Realtime HID FSK Read from antenna (option '1' for one tag only)"},
|
||||
{"sim", CmdHIDSim, 0, "<ID> -- HID tag simulator"},
|
||||
{"clone", CmdHIDClone, 0, "<ID> ['l'] -- Clone HID to T55x7 (tag must be in antenna)(option 'l' for 84bit ID)"},
|
||||
{"pack", CmdHIDPack, 1, "<len> <fc> <num> -- packs a <38 bit (short) HID ID from its length, facility code and card number"},
|
||||
{"unpack", CmdHIDUnpack, 1, "<ID> -- unpacks a <38 bit (short) HID ID to its length, facility code and card number"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -11,10 +11,28 @@
|
|||
#ifndef CMDLFHID_H__
|
||||
#define CMDLFHID_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Structure for unpacked "short" (<38 bits) HID Prox tags.
|
||||
typedef struct {
|
||||
// Format length, in bits.
|
||||
uint8_t fmtLen;
|
||||
// Facility code.
|
||||
uint32_t fc;
|
||||
// Card number.
|
||||
uint32_t cardnum;
|
||||
} short_hid_info;
|
||||
|
||||
bool pack_short_hid(/* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const short_hid_info *info);
|
||||
bool unpack_short_hid(short_hid_info* out, uint32_t hi, uint32_t lo);
|
||||
|
||||
int CmdLFHID(const char *Cmd);
|
||||
int CmdFSKdemodHID(const char *Cmd);
|
||||
int CmdHIDReadDemod(const char *Cmd);
|
||||
int CmdHIDSim(const char *Cmd);
|
||||
int CmdHIDClone(const char *Cmd);
|
||||
int CmdHIDPack(const char *Cmd);
|
||||
int CmdHIDUnpack(const char *Cmd);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue