mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Merge pull request #2449 from FreqTheWhat/Defcon32RFCTF
Add `--emu` and `--issue` support to `hf iclass encode`
This commit is contained in:
commit
17ab8d52b1
3 changed files with 118 additions and 24 deletions
|
@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file.
|
||||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
- Added --issue and (--emu)lator support to `hf iclass encode` command (@micsen)
|
||||||
|
- Added custom CTF Wiegand format from Defcon32 with comments (@micsen)
|
||||||
- Added native output grabbing for Python and Lua: less hacky than `output_grabber.py`, should work on ProxSpace as well (@doegox)
|
- Added native output grabbing for Python and Lua: less hacky than `output_grabber.py`, should work on ProxSpace as well (@doegox)
|
||||||
- Changed `hf mf chk/fchk`: added option `--no-default` to skip loading the usual ~61 hardcoded keys (@doegox)
|
- Changed `hf mf chk/fchk`: added option `--no-default` to skip loading the usual ~61 hardcoded keys (@doegox)
|
||||||
- Fixed `hf mf wipe` to detect properly write errors (@doegox)
|
- Fixed `hf mf wipe` to detect properly write errors (@doegox)
|
||||||
|
|
|
@ -4579,20 +4579,24 @@ static int CmdHFiClassEncode(const char *Cmd) {
|
||||||
"Use either --bin or --wiegand/--fc/--cn",
|
"Use either --bin or --wiegand/--fc/--cn",
|
||||||
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337 (H10301)\n"
|
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337 (H10301)\n"
|
||||||
"hf iclass encode -w H10301 --fc 31 --cn 337 --ki 0 -> FC 31 CN 337 (H10301)\n"
|
"hf iclass encode -w H10301 --fc 31 --cn 337 --ki 0 -> FC 31 CN 337 (H10301)\n"
|
||||||
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337 (H10301), writing w elite key"
|
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337 (H10301), writing w elite key\n"
|
||||||
|
"hf iclass encode -w H10301 --fc 31 --cn 337 --emu -> Writes the ecoded data to emulator memory\n"
|
||||||
|
"When using emulator you have to first load a credential into emulator memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_str0(NULL, "bin", "<bin>", "Binary string i.e 0001001001"),
|
arg_str0(NULL, "bin", "<bin>", "Binary string i.e 0001001001"),
|
||||||
arg_int1(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
|
arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
|
||||||
arg_lit0(NULL, "credit", "key is assumed to be the credit key"),
|
arg_lit0(NULL, "credit", "key is assumed to be the credit key"),
|
||||||
arg_lit0(NULL, "elite", "elite computations applied to key"),
|
arg_lit0(NULL, "elite", "elite computations applied to key"),
|
||||||
arg_lit0(NULL, "raw", "no computations applied to key"),
|
arg_lit0(NULL, "raw", "no computations applied to key"),
|
||||||
arg_str0(NULL, "enckey", "<hex>", "3DES transport key, 16 hex bytes"),
|
arg_str0(NULL, "enckey", "<hex>", "3DES transport key, 16 hex bytes"),
|
||||||
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
|
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
|
||||||
arg_u64_0(NULL, "cn", "<dec>", "card number"),
|
arg_u64_0(NULL, "cn", "<dec>", "card number"),
|
||||||
|
arg_u64_0(NULL, "issue", "<dec>", "issue level"),
|
||||||
arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
|
arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
|
||||||
|
arg_lit0(NULL, "emu", "Write to emulation memory instead of card"),
|
||||||
arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"),
|
arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"),
|
||||||
arg_lit0("v", NULL, "verbose (print encoded blocks)"),
|
arg_lit0("v", NULL, "verbose (print encoded blocks)"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
|
@ -4605,9 +4609,18 @@ static int CmdHFiClassEncode(const char *Cmd) {
|
||||||
CLIGetStrWithReturn(ctx, 1, bin, &bin_len);
|
CLIGetStrWithReturn(ctx, 1, bin, &bin_len);
|
||||||
|
|
||||||
int key_nr = arg_get_int_def(ctx, 2, -1);
|
int key_nr = arg_get_int_def(ctx, 2, -1);
|
||||||
bool auth = false;
|
bool use_emulator_memory = arg_get_lit(ctx, 11);
|
||||||
|
|
||||||
|
bool auth = false;
|
||||||
uint8_t key[8] = {0};
|
uint8_t key[8] = {0};
|
||||||
|
|
||||||
|
// If we use emulator memory skip key requirement
|
||||||
|
if (!use_emulator_memory) {
|
||||||
|
if (key_nr < 0) {
|
||||||
|
PrintAndLogEx(ERR, "Missing required arg for --ki or --emu");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
if (key_nr >= 0) {
|
if (key_nr >= 0) {
|
||||||
if (key_nr < ICLASS_KEYS_MAX) {
|
if (key_nr < ICLASS_KEYS_MAX) {
|
||||||
auth = true;
|
auth = true;
|
||||||
|
@ -4619,6 +4632,7 @@ static int CmdHFiClassEncode(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool use_credit_key = arg_get_lit(ctx, 3);
|
bool use_credit_key = arg_get_lit(ctx, 3);
|
||||||
bool elite = arg_get_lit(ctx, 4);
|
bool elite = arg_get_lit(ctx, 4);
|
||||||
|
@ -4635,13 +4649,15 @@ static int CmdHFiClassEncode(const char *Cmd) {
|
||||||
memset(&card, 0, sizeof(wiegand_card_t));
|
memset(&card, 0, sizeof(wiegand_card_t));
|
||||||
card.FacilityCode = arg_get_u32_def(ctx, 7, 0);
|
card.FacilityCode = arg_get_u32_def(ctx, 7, 0);
|
||||||
card.CardNumber = arg_get_u32_def(ctx, 8, 0);
|
card.CardNumber = arg_get_u32_def(ctx, 8, 0);
|
||||||
|
card.IssueLevel = arg_get_u32_def(ctx, 9, 0);
|
||||||
|
|
||||||
char format[16] = {0};
|
char format[16] = {0};
|
||||||
int format_len = 0;
|
int format_len = 0;
|
||||||
CLIParamStrToBuf(arg_get_str(ctx, 9), (uint8_t *)format, sizeof(format), &format_len);
|
|
||||||
|
|
||||||
bool shallow_mod = arg_get_lit(ctx, 10);
|
CLIParamStrToBuf(arg_get_str(ctx, 10), (uint8_t *)format, sizeof(format), &format_len);
|
||||||
bool verbose = arg_get_lit(ctx, 11);
|
|
||||||
|
bool shallow_mod = arg_get_lit(ctx, 12);
|
||||||
|
bool verbose = arg_get_lit(ctx, 13);
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
@ -4669,7 +4685,12 @@ static int CmdHFiClassEncode(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_enc_key == false) {
|
if (have_enc_key == false) {
|
||||||
|
// The IsCardHelperPresent function clears the emulator memory
|
||||||
|
if (use_emulator_memory) {
|
||||||
|
use_sc = false;
|
||||||
|
} else {
|
||||||
use_sc = IsCardHelperPresent(false);
|
use_sc = IsCardHelperPresent(false);
|
||||||
|
}
|
||||||
if (use_sc == false) {
|
if (use_sc == false) {
|
||||||
size_t keylen = 0;
|
size_t keylen = 0;
|
||||||
int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&enckeyptr, &keylen);
|
int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&enckeyptr, &keylen);
|
||||||
|
@ -4774,6 +4795,12 @@ static int CmdHFiClassEncode(const char *Cmd) {
|
||||||
|
|
||||||
int isok = PM3_SUCCESS;
|
int isok = PM3_SUCCESS;
|
||||||
// write
|
// write
|
||||||
|
if (use_emulator_memory) {
|
||||||
|
uint16_t byte_sent = 0;
|
||||||
|
iclass_upload_emul(credential, sizeof(credential), 6 * PICOPASS_BLOCK_SIZE, &byte_sent);
|
||||||
|
PrintAndLogEx(SUCCESS, "uploaded " _YELLOW_("%d") " bytes to emulator memory", byte_sent);
|
||||||
|
PrintAndLogEx(HINT, "You are now ready to simulate. See " _YELLOW_("`hf iclass sim -h`"));
|
||||||
|
} else {
|
||||||
for (uint8_t i = 0; i < 4; i++) {
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
isok = iclass_write_block(6 + i, credential + (i * 8), NULL, key, use_credit_key, elite, rawkey, false, false, auth, shallow_mod);
|
isok = iclass_write_block(6 + i, credential + (i * 8), NULL, key, use_credit_key, elite, rawkey, false, false, auth, shallow_mod);
|
||||||
switch (isok) {
|
switch (isok) {
|
||||||
|
@ -4785,6 +4812,7 @@ static int CmdHFiClassEncode(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return isok;
|
return isok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,69 @@
|
||||||
#include "commonutil.h"
|
#include "commonutil.h"
|
||||||
|
|
||||||
|
|
||||||
|
static bool Pack_Defcon32(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
|
||||||
|
memset(packed, 0, sizeof(wiegand_message_t));
|
||||||
|
if (card->FacilityCode > 0x00FFFF) return false; // Can't encode FC.
|
||||||
|
if (card->CardNumber > 0x0fffff) return false; // Can't encode CN.
|
||||||
|
if (card->IssueLevel > 0x00000F) return false; // Can't encode Issue
|
||||||
|
if (card->OEM > 0) return false; // Not used in this format
|
||||||
|
|
||||||
|
packed->Length = 42;
|
||||||
|
/*
|
||||||
|
By implementing this format I hope to make the CTF easier for people to get into next year
|
||||||
|
//~~The wiegand data consists of 3 32 bit units that we need to split the data between Bottom and Mid since we have a 42 bit format~~
|
||||||
|
We can use the set linear field function instead this seems to be easier.
|
||||||
|
|Mid part| | Bot part of the packed data |
|
||||||
|
PFFFFFFFFF FFFFFFFIIIICCCCCCCCCCCCCCCCCCCCP
|
||||||
|
1111111111 11111111111000000000000000001000
|
||||||
|
FC 111111111 1111111 = FF FF
|
||||||
|
//FC Mid 111111111 0000000 = FF 80 These where used to split data between bot/mid
|
||||||
|
//FC Bot 000000000 1111111 = 00 7F
|
||||||
|
Issuance 1111 = 0F
|
||||||
|
Card Number 11111111111111111111 = 0FFFFF
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Referenced from MSB
|
||||||
|
set_linear_field(packed, card->CardNumber, 21, 20); // 20 bit
|
||||||
|
set_linear_field(packed, card->IssueLevel, 17, 4); // 4 bit
|
||||||
|
set_linear_field(packed, card->FacilityCode, 1, 16); // 16 bits
|
||||||
|
|
||||||
|
// Parity calc
|
||||||
|
//0123456789|0123456789|0123456789|0123456789|01
|
||||||
|
//E E E E E |E E E E E |EO O O O O| O O O O O| O
|
||||||
|
set_bit_by_position(packed,
|
||||||
|
evenparity32(
|
||||||
|
get_nonlinear_field(packed, 16, (uint8_t[]) {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}))
|
||||||
|
, 0);
|
||||||
|
|
||||||
|
set_bit_by_position(packed,
|
||||||
|
oddparity32(
|
||||||
|
get_nonlinear_field(packed, 16, (uint8_t[]) {21, 23, 25, 27, 29, 31, 33, 35, 37, 39}))
|
||||||
|
, 41);
|
||||||
|
if (preamble)
|
||||||
|
return add_HID_header(packed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Unpack_Defcon32(wiegand_message_t *packed, wiegand_card_t *card) {
|
||||||
|
memset(card, 0, sizeof(wiegand_card_t));
|
||||||
|
|
||||||
|
if (packed->Length != 42) return false; // Wrong length? Stop here.
|
||||||
|
|
||||||
|
card->FacilityCode = get_linear_field(packed, 1, 16);
|
||||||
|
card->IssueLevel = get_linear_field(packed, 17, 4);
|
||||||
|
card->CardNumber = get_linear_field(packed, 21, 20);
|
||||||
|
|
||||||
|
card->ParityValid =
|
||||||
|
(get_bit_by_position(packed, 41) == oddparity32(
|
||||||
|
get_nonlinear_field(packed, 16, (uint8_t[]) {21, 23, 25, 27, 29, 31, 33, 35, 37, 39})))&&
|
||||||
|
(get_bit_by_position(packed, 0) ==
|
||||||
|
evenparity32(get_nonlinear_field(packed, 16, (uint8_t[]) {2, 4, 6, 8, 10, 12, 14, 16, 18, 20})));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool Pack_H10301(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
|
static bool Pack_H10301(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
|
||||||
memset(packed, 0, sizeof(wiegand_message_t));
|
memset(packed, 0, sizeof(wiegand_message_t));
|
||||||
|
|
||||||
|
@ -1474,6 +1537,7 @@ static const cardformat_t FormatTable[] = {
|
||||||
{"C1k48s", Pack_C1k48s, Unpack_C1k48s, "HID Corporate 1000 48-bit std", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
|
{"C1k48s", Pack_C1k48s, Unpack_C1k48s, "HID Corporate 1000 48-bit std", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
|
||||||
{"BC40", Pack_bc40, Unpack_bc40, "Bundy TimeClock 40-bit", {1, 1, 0, 1, 1}}, // from
|
{"BC40", Pack_bc40, Unpack_bc40, "Bundy TimeClock 40-bit", {1, 1, 0, 1, 1}}, // from
|
||||||
{"Avig56", Pack_Avig56, Unpack_Avig56, "Avigilon 56-bit", {1, 1, 0, 0, 1}},
|
{"Avig56", Pack_Avig56, Unpack_Avig56, "Avigilon 56-bit", {1, 1, 0, 0, 1}},
|
||||||
|
{"Defcon32", Pack_Defcon32, Unpack_Defcon32, "Custom Defcon RFCTF 42 BIT format", {1, 1, 1, 0, 1}}, // Created by (@micsen) for the CTF
|
||||||
{NULL, NULL, NULL, NULL, {0, 0, 0, 0, 0}} // Must null terminate array
|
{NULL, NULL, NULL, NULL, {0, 0, 0, 0, 0}} // Must null terminate array
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue