This commit is contained in:
root 2020-03-11 04:43:47 -04:00
commit 693b2bc3d0
62 changed files with 1138 additions and 989 deletions

View file

@ -3,6 +3,9 @@ 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...
## [unreleased][unreleased]
- Change `script run hf_bruteforce -s start_id -e end_id -t timeout -x mifare_card_type` - The hf_bruteforce card script now requires Mifare type (mfc or mfu) (@dunderhay)
- Updated `hf_bruteforce.lua` script - added support for brute forcing Mifare Ultralight EV1 cards (@dunderhay)
- Added `hf mf personlize` - personalize the UID of a Mifare Classic EV1 card (@pwpiwi)
- Change - hint texts added to all lf clone commands (@iceman1001)
- Change `lf keri demod` - adjusted the internal id. (@mwalker33)
- Added seamless integration with cryptohelper (@iceman1001)
@ -35,7 +38,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added `commands.md` - document with all proxmark client commands. Generated with XX_internal_command_dump_markdown_XX. (@iceman1001)
- Change `lf pac clone` - new option `c <card id>` to allow cloning PAC/Stanley tag from card ID (@danshuk)
- Change `lf pac read` - decoded PAC/Stanley card ID (@danshuk)
- Change mifare classic keytable output refactored and uses colors (@iceman1001)
- Change mifare classic keytable output refactored and uses colors (@iceman1001)
- Fix `hf mf nested` - now writes the correct blockno (@iceman1001)
- Change `lf t55xx dump` - now supports saving to JSON (@iceman1001)
- Change `hf mf chk | fchk` faster authentication by lower timeout limit. (@pwpiwi)
@ -605,8 +608,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Updated the Reveng 1.31 sourcecode to 1.40 from Reveng project homepage (@iceman1001)
- Added possibility to write direct to a Legic Prime Tag (MIM256/1024) without using values from the `BigBuffer` -> `hf legic writeRaw <addr> <value>` (@icsom)
- Added possibility to decrease DCF values at address 0x05 & 0x06 on a Legic Prime Tag
DCF-value will be pulled from the BigBuffer (address 0x05 & 0x06) so you have to
load the data into the BigBuffer before with `hf legic load <path/to/legic.dump>` & then
DCF-value will be pulled from the BigBuffer (address 0x05 & 0x06) so you have to
load the data into the BigBuffer before with `hf legic load <path/to/legic.dump>` & then
write the DCF-Values (both at once) with `hf legic write 0x05 0x02` (@icsom)
- Added script `legic.lua` for display and edit Data of Legic-Prime Tags (@icsom)
- Added the experimental HITAG_S support (@spenneb)

View file

@ -11,10 +11,10 @@
| FAQ's & Updates | Installation | Use of the Proxmark |
| ------------------- |:-------------------:| -------------------:|
|[What has changed?](#what-has-changed) | [Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)|
|[Development](#development) | [Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) |
|[Why didn't you base it on official Proxmark3 Master?](#why-didnt-you-base-it-on-official-proxmark3-master)| [Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)|
|[Proxmark3 GUI](#proxmark3-gui)|[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)|
|[What has changed?](#what-has-changed) | **[Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md)** | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)|
|[Development](#development) | **[Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md)** | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) |
|[Why didn't you base it on official Proxmark3 Master?](#why-didnt-you-base-it-on-official-proxmark3-master)| **[Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md)** | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)|
|[Proxmark3 GUI](#proxmark3-gui)|**[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)**|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)|
|[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) |[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)|
|[Notes on UART](/doc/uart_notes.md)|[Maintainers](/doc/md/Development/Maintainers.md)|[Command Cheat sheet](/doc/cheatsheet.md)|
|[Notes on frame format](/doc/new_frame_format.md)||[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)|

View file

@ -45,7 +45,7 @@
* This module emits debug strings during normal operation -- so try it out in
* the lab connected to PM3 client before taking it into the field.
*
* To delete the trace data from flash:
* To delete the trace data from flash:
*
* Caveats / notes:
* - Trace buffer will be cleared on starting stand-alone mode. Data in flash
@ -97,7 +97,7 @@ void RunMod() {
if (trace_len > 0) {
Dbprintf("[!] Trace length (bytes) = %u", trace_len);
uint8_t* trace_buffer = BigBuf_get_addr();
uint8_t *trace_buffer = BigBuf_get_addr();
if (!exists_in_spiffs(HF_14ASNIFF_LOGFILE)) {
rdv40_spiffs_write(
HF_14ASNIFF_LOGFILE, trace_buffer, trace_len, RDV40_SPIFFS_SAFETY_SAFE);
@ -117,7 +117,7 @@ void RunMod() {
SpinErr(LED_A, 200, 5);
SpinDelay(100);
LEDsoff();
SpinDelay(300);
DownloadTraceInstructions();

View file

@ -63,7 +63,7 @@ void DownloadLogInstructions() {
bool log_exists;
void append(uint8_t* entry, size_t entry_len) {
void append(uint8_t *entry, size_t entry_len) {
LED_B_ON();
if (log_exists == false) {
@ -106,22 +106,22 @@ uint32_t IceEM410xdemod() {
if (size == 128) {
sprintf((char *)entry, "EM XL TAG ID: %06lx%08lx%08lx - (%05ld_%03ld_%08ld)\n",
hi,
(uint32_t)(lo >> 32),
(uint32_t)lo,
(uint32_t)(lo & 0xFFFF),
(uint32_t)((lo >> 16LL) & 0xFF),
(uint32_t)(lo & 0xFFFFFF));
hi,
(uint32_t)(lo >> 32),
(uint32_t)lo,
(uint32_t)(lo & 0xFFFF),
(uint32_t)((lo >> 16LL) & 0xFF),
(uint32_t)(lo & 0xFFFFFF));
} else {
sprintf((char *)entry, "EM TAG ID: %02lx%08lx - (%05ld_%03ld_%08ld)\n",
(uint32_t)(lo >> 32),
(uint32_t)lo,
(uint32_t)(lo & 0xFFFF),
(uint32_t)((lo >> 16LL) & 0xFF),
(uint32_t)(lo & 0xFFFFFF));
(uint32_t)(lo >> 32),
(uint32_t)lo,
(uint32_t)(lo & 0xFFFF),
(uint32_t)((lo >> 16LL) & 0xFF),
(uint32_t)(lo & 0xFFFFFF));
}
append(entry, strlen((char*)entry));
append(entry, strlen((char *)entry));
Dbprintf("%s", entry);
BigBuf_free();
return PM3_SUCCESS;
@ -173,7 +173,7 @@ uint32_t IceAWIDdemod() {
}
}
append(entry, strlen((char*)entry));
append(entry, strlen((char *)entry));
Dbprintf("%s", entry);
BigBuf_free();
return PM3_SUCCESS;
@ -210,14 +210,14 @@ uint32_t IceIOdemod() {
memset(entry, 0, sizeof(entry));
sprintf((char *)entry, "IO Prox XSF(%02d)%02x:%05d (%08lx%08lx)\n"
, version
, facilitycode
, number
, hi
, lo
);
, version
, facilitycode
, number
, hi
, lo
);
append(entry, strlen((char*)entry));
append(entry, strlen((char *)entry));
Dbprintf("%s", entry);
BigBuf_free();
return PM3_SUCCESS;
@ -250,13 +250,13 @@ uint32_t IceHIDDemod() {
if (hi2 != 0) { //extra large HID tags 88/192 bits
sprintf((char *)entry, "HID large: %lx%08lx%08lx (%ld)\n",
hi2,
hi,
lo,
(lo >> 1) & 0xFFFF
);
hi2,
hi,
lo,
(lo >> 1) & 0xFFFF
);
append(entry, strlen((char*)entry));
append(entry, strlen((char *)entry));
} else { //standard HID tags 44/96 bits
uint8_t bitlen = 0;
@ -297,15 +297,15 @@ uint32_t IceHIDDemod() {
}
sprintf((char *)entry, "HID: %lx%08lx (%ld) Format: %d bit FC: %ld Card: %ld\n",
hi,
lo,
(lo >> 1) & 0xFFFF,
bitlen,
fac,
cardnum
);
hi,
lo,
(lo >> 1) & 0xFFFF,
bitlen,
fac,
cardnum
);
append(entry, strlen((char*)entry));
append(entry, strlen((char *)entry));
}
Dbprintf("%s", entry);
@ -349,7 +349,7 @@ void RunMod() {
uint32_t res;
// since we steal 12800 from bigbuffer, no need to sample it.
// since we steal 12800 from bigbuffer, no need to sample it.
DoAcquisition_config(false, 28000);
res = IceHIDDemod();
if (res == PM3_SUCCESS) {

View file

@ -42,6 +42,7 @@
#include "Standalone/standalone.h"
#include "util.h"
#include "ticks.h"
#include "commonutil.h"
#ifdef WITH_LCD
#include "LCD.h"
@ -548,7 +549,7 @@ void ListenReaderField(uint8_t limit) {
// iceman, useless, since we are measuring readerfield, not our field. My tests shows a max of 20v from a reader.
hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40);
#else
hf_av = hf_max = AvgAdc(ADC_CHAN_HF);
hf_av = hf_max = AvgAdc(ADC_CHAN_HF);
#endif
Dbprintf("HF 13.56MHz Baseline: %dmV", (MAX_ADC_HF_VOLTAGE * hf_av) >> 10);
hf_baseline = hf_av;
@ -721,10 +722,15 @@ static void PacketReceived(PacketCommandNG *packet) {
setT55xxConfig(packet->oldarg[0], (t55xx_configurations_t *) packet->data.asBytes);
break;
}
case CMD_LF_SAMPLING_GET_CONFIG: {
case CMD_LF_SAMPLING_PRINT_CONFIG: {
printConfig();
break;
}
case CMD_LF_SAMPLING_GET_CONFIG: {
sample_config *config = getSamplingConfig();
reply_ng(CMD_LF_SAMPLING_GET_CONFIG, PM3_SUCCESS, (uint8_t *)config, sizeof(sample_config));
break;
}
case CMD_LF_SAMPLING_SET_CONFIG: {
sample_config c;
memcpy(&c, packet->data.asBytes, sizeof(sample_config));
@ -1242,6 +1248,17 @@ static void PacketReceived(PacketCommandNG *packet) {
// SniffMifare(packet->oldarg[0]);
// break;
// }
case CMD_HF_MIFARE_PERSONALIZE_UID: {
struct p {
uint8_t keytype;
uint8_t pers_option;
uint8_t key[6];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
uint64_t authkey = bytes_to_num(payload->key, 6);
MifarePersonalizeUID(payload->keytype, payload->pers_option, authkey);
break;
}
case CMD_HF_MIFARE_SETMOD: {
MifareSetMod(packet->data.asBytes);
break;

View file

@ -408,7 +408,7 @@ void fix_ac_decoding(uint8_t *input, size_t len) {
*/
// looks at number of received bits.
// looks at number of received bits.
// 0 = collision?
// 32 = good response
bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool hitag_s) {
@ -582,15 +582,15 @@ bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *t
Dbhexdump(4, logdata_1, false);
bSuccessful = true;
return false;
/*
// read next page of card until done
tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE
tx[1] = blocknr << 4;
crc = hitag_crc(tx, 12);
tx[1] |= crc >> 4;
tx[2] = crc << 4;
*txlen = 20;
*/
/*
// read next page of card until done
tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE
tx[1] = blocknr << 4;
crc = hitag_crc(tx, 12);
tx[1] |= crc >> 4;
tx[2] = crc << 4;
*txlen = 20;
*/
}
}
break;
@ -1091,7 +1091,7 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
uint32_t block = 0;
for (size_t i = 0; i < 12; i++) {
// num2bytes?
// num2bytes?
for (size_t j = 0; j < 4; j++) {
block <<= 8;
block |= tag.sectors[i][j];
@ -1105,30 +1105,30 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
size_t nrzs = 0, periods = 0;
// uint32_t command_start = 0, command_duration = 0;
// int16_t checked = 0;
// int16_t checked = 0;
// SIMULATE
while (!BUTTON_PRESS()) {
LED_D_ON();
// lf_reset_counter();
LED_A_OFF();
WDT_HIT();
/*
// only every 1000th times, in order to save time when collecting samples.
if (checked == 100) {
if (data_available()) {
checked = -1;
break;
} else {
checked = 0;
}
}
++checked;
*/
/*
// only every 1000th times, in order to save time when collecting samples.
if (checked == 100) {
if (data_available()) {
checked = -1;
break;
} else {
checked = 0;
}
}
++checked;
*/
rxlen = 0;
@ -1220,8 +1220,8 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
if (nrzs < 5) {
Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs);
continue;
} else {
for (size_t i = 0; i < 5; i++){
} else {
for (size_t i = 0; i < 5; i++) {
if (nrz_samples[i] != 1) {
Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one", i);
}
@ -1229,7 +1229,7 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
}
// Pack the response into a byte array
for (size_t i = 5; i < 37; i++){
for (size_t i = 5; i < 37; i++) {
uint8_t bit = nrz_samples[i];
rx[rxlen / 8] |= bit << (7 - (rxlen % 8));
rxlen++;
@ -1401,7 +1401,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
// hitagS settings
t_wait_1 = 204;
t_wait_2 = 128;
/*tag_size = 256;*/
flipped_bit = 0;
tag_size = 8;
DBG DbpString("Configured for hitagS reader");
@ -1657,7 +1656,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
uint32_t command_start = 0;
uint32_t command_duration = 0;
uint32_t response_start = 0;
uint32_t response_duration = 0;
uint32_t response_duration = 0;
uint8_t rx[HITAG_FRAME_LEN];
size_t rxlen = 0;
uint8_t txbuf[HITAG_FRAME_LEN];
@ -1731,14 +1730,14 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
tag_size = 8;
DbpString("Configured for hitagS writer");
} else if (htf < 20) {
// hitag1 settings
// hitag1 settings
t_wait_1 = 204;
t_wait_2 = 128;
tag_size = 256;
flipped_bit = 0;
DbpString("Configured for hitag1 writer");
} else if (htf < 30) {
// hitag2 settings
// hitag2 settings
t_wait_1 = HITAG_T_WAIT_1_MIN;
t_wait_2 = HITAG_T_WAIT_2_MIN;
tag_size = 48;
@ -1783,7 +1782,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
}
}
// Wait for t_wait_2 carrier periods after the last tag bit before transmitting,
// Wait for t_wait_2 carrier periods after the last tag bit before transmitting,
lf_wait_periods(t_wait_2);
command_start += t_wait_2;

View file

@ -38,70 +38,60 @@ bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) {
uint8_t temp[20];
int i;
uint8_t *spaceptr = NULL;
// get uid as hexstring
if(!hitag2_get_uid(uidhex))
{
if (!hitag2_get_uid(uidhex)) {
UserMessage("Cannot get UID\r\n");
return false;
}
// convert uid hexstring to binarray
hextobinarray(uid, uidhex);
// convert nR and aR hexstrings to binarray
spaceptr = strchr(nrarhex, ' ');
if (!spaceptr)
{
if (!spaceptr) {
UserMessage("Please supply a valid nR aR pair\r\n");
return false;
}
*spaceptr = 0x00;
if (hextobinarray(nrar, nrarhex) != 32)
{
if (hextobinarray(nrar, nrarhex) != 32) {
UserMessage("nR is not 32 bits long\r\n");
return false;
}
if (hextobinarray(nrar + 32, spaceptr + 1) != 32)
{
if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
UserMessage("aR is not 32 bits long\r\n");
return false;
}
// find a valid encrypted command
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar))
{
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) {
UserMessage("Cannot find a valid encrypted command\r\n");
return false;
}
// find the 'read page 0' command and recover key stream
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid))
{
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) {
UserMessage("Cannot find encrypted 'read page0' command\r\n");
return false;
}
// empty the response string
response[0] = 0x00;
// read all pages using key stream
for (i=0; i<8; i++)
{
if (hitag2crack_read_page(pagehex, i, nrar, keybits))
{
for (i = 0; i < 8; i++) {
if (hitag2crack_read_page(pagehex, i, nrar, keybits)) {
sprintf(temp, "%1d: %s\r\n", i, pagehex);
}
else
{
} else {
sprintf(temp, "%1d:\r\n", i);
}
// add page string to response
strcat(response, temp);
}
return true;
}
@ -113,16 +103,16 @@ bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) {
bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) {
uint8_t guess[10];
uint8_t responsestr[9];
// UserMessage("Finding valid encrypted command:");
// we're going to hold bits 5, 7, 8 and 9 and brute force the rest
// e.g. x x x x x 0 x 0 0 0
for (uint8_t a=0; a<2; a++) {
for (uint8_t b=0; b<2; b++) {
for (uint8_t c=0; c<2; c++) {
for (uint8_t d=0; d<2; d++) {
for (uint8_t e=0; e<2; e++) {
for (uint8_t g=0; g<2; g++) {
for (uint8_t a = 0; a < 2; a++) {
for (uint8_t b = 0; b < 2; b++) {
for (uint8_t c = 0; c < 2; c++) {
for (uint8_t d = 0; d < 2; d++) {
for (uint8_t e = 0; e < 2; e++) {
for (uint8_t g = 0; g < 2; g++) {
// build binarray
guess[0] = a;
guess[1] = b;
@ -175,65 +165,50 @@ bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8
UserMessage("Finding 'read page 0' command:");
// we're going to brute the missing 4 bits of the valid encrypted command
for (a=0; a<2; a++)
{
for (b=0; b<2; b++)
{
for (c=0; c<2; c++)
{
for (d=0; d<2; d++)
{
for (a = 0; a < 2; a++) {
for (b = 0; b < 2; b++) {
for (c = 0; c < 2; c++) {
for (d = 0; d < 2; d++) {
// create our guess by bit flipping the pattern of bits
// representing the inverted bit and the 3 page bits
// in both the non-inverted and inverted parts of the
// encrypted command.
memcpy(guess, e_firstcmd, 10);
if (a)
{
if (a) {
guess[5] = !guess[5];
guess[0] = !guess[0];
}
if (b)
{
if (b) {
guess[7] = !guess[7];
guess[2] = !guess[2];
}
if (c)
{
if (c) {
guess[8] = !guess[8];
guess[3] = !guess[3];
}
if (d)
{
if (d) {
guess[9] = !guess[9];
guess[4] = !guess[4];
}
// try the guess
if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10))
{
if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) {
// check if it was valid
if (strcmp(responsestr, ERROR_RESPONSE) != 0)
{
if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
// convert response to binarray
hextobinarray(e_uid, responsestr);
// test if the guess was 'read page 0' command
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid))
{
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
return true;
}
}
else
{
} else {
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
#endif
}
}
else
{
#ifdef RFIDLER_DEBUG
} else {
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
#endif
}
@ -262,56 +237,51 @@ bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, u
uint8_t e_ext_cmd[40];
uint8_t responsestr[9];
int i;
// copy encrypted cmd to cipherbits
memcpy(cipherbits, e_cmd, 10);
// copy encrypted uid to cipherbits
memcpy(cipherbits + 10, e_uid, 32);
// copy cmd to plainbits
binstringtobinarray(plainbits, READP0CMD);
// copy uid to plainbits
memcpy(plainbits + 10, uid, 32);
// xor the plainbits with the cipherbits to get keybits
hitag2crack_xor(keybits, plainbits, cipherbits, 42);
// create extended cmd -> 4 * READP0CMD = 40 bits
for (i=0; i<4; i++)
{
for (i = 0; i < 4; i++) {
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
}
// xor extended cmd with keybits
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40);
// send extended encrypted cmd
if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40))
{
if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40)) {
// test if it was valid
if (strcmp(responsestr, ERROR_RESPONSE) != 0)
{
if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
return true;
}
}
else
{
} else {
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
#endif
}
return false;
}
// hitag2crack_xor XORs the source with the pad to produce the target.
// source, target and pad are binarrays of length len.
void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len) {
for (int i=0; i<len; i++) {
for (int i = 0; i < len; i++) {
target[i] = source[i] ^ pad[i];
}
}
@ -329,40 +299,34 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar,
uint8_t e_response[32];
uint8_t response[32];
int i;
if ((pagenum < 0) || (pagenum > 7))
{
if ((pagenum < 0) || (pagenum > 7)) {
UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n");
return false;
}
// create cmd
binstringtobinarray(cmd, READP0CMD);
if (pagenum & 0x1)
{
if (pagenum & 0x1) {
cmd[9] = !cmd[9];
cmd[4] = !cmd[4];
}
if (pagenum & 0x2)
{
if (pagenum & 0x2) {
cmd[8] = !cmd[8];
cmd[3] = !cmd[3];
}
if (pagenum & 0x4)
{
if (pagenum & 0x4) {
cmd[7] = !cmd[7];
cmd[2] = !cmd[2];
}
// encrypt command
hitag2crack_xor(e_cmd, cmd, keybits, 10);
// send encrypted command
if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10))
{
if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10)) {
// check if it is valid
if (strcmp(e_responsestr, ERROR_RESPONSE) != 0)
{
if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) {
// convert to binarray
hextobinarray(e_response, e_responsestr);
// decrypt response
@ -370,17 +334,13 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar,
// convert to hexstring
binarraytohex(responsestr, response, 32);
return true;
}
else
{
} else {
UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
}
}
else
{
} else {
UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n");
}
return false;
}
@ -397,8 +357,7 @@ bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, i
int ret = 0;
// get the UID
if(!hitag2_get_uid(uid))
{
if (!hitag2_get_uid(uid)) {
UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n");
return false;
}
@ -407,22 +366,19 @@ bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, i
CryptoActive = false;
// get the UID again
if(!hitag2_get_uid(uid))
{
if (!hitag2_get_uid(uid)) {
UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n");
return false;
}
// send nrar and receive (useless) encrypted page 3 value
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false))
{
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) {
UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n");
return false;
}
// send encrypted command
if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false))
{
if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) {
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n");
#endif
@ -442,34 +398,29 @@ bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, b
int ret = 0;
// START_AUTH kills active crypto session
CryptoActive= false;
if(!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX))
{
CryptoActive = false;
if (!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) {
UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n");
return false;
}
// skip 1/2 bit to synchronise manchester
HW_Skip_Bits = 1;
ret = read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY);
// check if response was a valid length (5 sync bits + 32 bits response)
if (ret == 37)
{
if (ret == 37) {
// check sync bits
if (memcmp(tmp, Hitag2Sync, 5) != 0)
{
if (memcmp(tmp, Hitag2Sync, 5) != 0) {
UserMessage("hitag2crack_tx_rx: no sync\r\n");
return false;
}
// convert response to hexstring
binarraytohex(responsestr, tmp + 5, 32);
return true;
}
else
{
} else {
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_tx_rx: wrong rx len\r\n");
#endif
@ -485,58 +436,53 @@ bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) {
uint32_t initvector;
uint8_t *spaceptr;
uint8_t *dataptr;
// extract vals from input
dataptr = input;
spaceptr = strchr(dataptr, ' ');
if (!spaceptr)
{
if (!spaceptr) {
UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n");
return false;
}
*spaceptr = 0x00;
if (strlen(dataptr) != 12)
{
if (strlen(dataptr) != 12) {
UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n");
return false;
}
sharedkey = rev64(hexreversetoulonglong(dataptr));
dataptr = spaceptr+1;
dataptr = spaceptr + 1;
spaceptr = strchr(dataptr, ' ');
if (!spaceptr)
{
if (!spaceptr) {
UserMessage("/r/nno UID\r\n");
return false;
}
*spaceptr = 0x00;
if (strlen(dataptr) != 8)
{
if (strlen(dataptr) != 8) {
UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n");
return false;
}
serialnum = rev32(hexreversetoulong(dataptr));
dataptr = spaceptr+1;
if (strlen(dataptr) != 8)
{
dataptr = spaceptr + 1;
if (strlen(dataptr) != 8) {
UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n");
return false;
}
initvector = rev32(hexreversetoulong(dataptr));
// start up crypto engine
hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector);
strcpy(response, "Success\r\n");
return true;
}
@ -545,21 +491,20 @@ bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) {
uint8_t binhex[9];
uint8_t binstr[33];
uint32_t binulong;
if (strlen(hex) != 8)
{
if (strlen(hex) != 8) {
UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n");
return false;
}
binulong = hextoulong(hex);
ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32);
binarraytobinstring(binstr, bin, 32);
binarraytohex(binhex, bin, 32);
// UserMessage("ar = %s\r\n", binstr);
// UserMessage("arhex = %s\r\n", binhex);
strcpy(response, binhex);
return true;
}
@ -570,17 +515,16 @@ bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) {
uint8_t binstr[33];
uint32_t binulong;
int len;
len = strlen(e_binstr);
if (len > 32)
{
if (len > 32) {
UserMessage("\r\nbinary string must be <= 32 bits\r\n");
return false;
}
binstringtobinarray(e_bin, e_binstr);
binulong = binarraytoulong(e_bin, len);
ulongtobinarray(bin, hitag2_crypt(binulong, len), len);
binarraytobinstring(binstr, bin, len);
strcpy(response, binstr);
@ -595,7 +539,7 @@ bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) {
bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) {
return hitag2crack_decrypt_bin(response, e_binstr);
}
// hitag2_keystream uses the first crack algorithm described in the paper,
// Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits
// of keystream.
@ -618,102 +562,90 @@ bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) {
int i;
uint8_t *spaceptr = NULL;
/*
keybits = malloc(2080);
if (!keybits) {
UserMessage("cannot malloc keybits\r\n");
return false;
}
*/
/*
keybits = malloc(2080);
if (!keybits) {
UserMessage("cannot malloc keybits\r\n");
return false;
}
*/
// get uid as hexstring
if(!hitag2_get_uid(uidhex))
{
if (!hitag2_get_uid(uidhex)) {
UserMessage("Cannot get UID\r\n");
return false;
}
// convert uid hexstring to binarray
hextobinarray(uid, uidhex);
// convert nR and aR hexstrings to binarray
spaceptr = strchr(nrarhex, ' ');
if (!spaceptr)
{
if (!spaceptr) {
UserMessage("Please supply a valid nR aR pair\r\n");
return false;
}
*spaceptr = 0x00;
if (hextobinarray(nrar, nrarhex) != 32)
{
if (hextobinarray(nrar, nrarhex) != 32) {
UserMessage("nR is not 32 bits long\r\n");
return false;
}
if (hextobinarray(nrar + 32, spaceptr + 1) != 32)
{
if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
UserMessage("aR is not 32 bits long\r\n");
return false;
}
// find a valid encrypted command
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar))
{
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) {
UserMessage("Cannot find a valid encrypted command\r\n");
return false;
}
// find the 'read page 0' command and recover key stream
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid))
{
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) {
UserMessage("Cannot find encrypted 'read page0' command\r\n");
return false;
}
// using the 40 bits of keystream in keybits, sending commands with ever
// increasing lengths to acquire 2048 bits of key stream.
kslen = 40;
while (kslen < 2048)
{
while (kslen < 2048) {
ksoffset = 0;
if (!hitag2crack_send_auth(nrar))
{
if (!hitag2crack_send_auth(nrar)) {
UserMessage("hitag2crack_send_auth failed\r\n");
return false;
}
// while we have at least 52 bits of keystream, consume it with
// extended read page 0 commands. 52 = 10 (min command len) +
// 32 (response) + 10 (min command len we'll send)
while ((kslen - ksoffset) >= 52)
{
while ((kslen - ksoffset) >= 52) {
// consume the keystream, updating ksoffset as we go
if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar))
{
if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar)) {
UserMessage("hitag2crack_consume_keystream failed\r\n");
return false;
}
}
// send an extended command to retrieve more keystream, updating kslen
// as we go
if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid))
{
if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) {
UserMessage("hitag2crack_extend_keystream failed\r\n");
return false;
}
UserMessage("Recovered %d bits of keystream\r\n", kslen);
}
for (i=0; i<2048; i+=256)
{
for (i = 0; i < 2048; i += 256) {
binarraytohex(keybitshex, keybits + i, 256);
UserMessage("%s\r\n", keybitshex);
}
response[0] = 0x00;
return true;
}
@ -724,8 +656,7 @@ bool hitag2crack_send_auth(uint8_t *nrar) {
uint8_t e_page3str[9];
// get the UID
if(!hitag2_get_uid(uid))
{
if (!hitag2_get_uid(uid)) {
UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n");
return false;
}
@ -734,15 +665,13 @@ bool hitag2crack_send_auth(uint8_t *nrar) {
CryptoActive = false;
// get the UID again
if(!hitag2_get_uid(uid))
{
if (!hitag2_get_uid(uid)) {
UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n");
return false;
}
// send nrar and receive (useless) encrypted page 3 value
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false))
{
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) {
UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n");
return false;
}
@ -767,46 +696,41 @@ bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, u
// 42 = 32 bit response + 10 bit command reserved for next command. conlen
// cannot be longer than 510 bits to fit into the small RWD buffer.
conlen = kslen - *ksoffset - 42;
if (conlen < 10)
{
if (conlen < 10) {
UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n");
return false;
}
// sanitise conlen
if (conlen > 510)
{
if (conlen > 510) {
conlen = 510;
}
// calculate how many repeated commands to send in this extended command.
numcmds = conlen / 10;
// build extended command
for (i=0; i<numcmds; i++)
{
for (i = 0; i < numcmds; i++) {
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
}
// xor extended cmd with keybits
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + *ksoffset, numcmds * 10);
// send encrypted command
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false))
{
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) {
UserMessage("hitag2crack_consume_keystream:\r\n tx/rx cmd failed\r\n");
return false;
}
// test response
if (strcmp(responsestr, ERROR_RESPONSE) == 0)
{
if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
UserMessage("hitag2crack_consume_keystream:\r\n got error response from card\r\n");
return false;
}
// dont bother decrypting the response - we already know the keybits
// update ksoffset with command length and response
*ksoffset += (numcmds * 10) + 32;
}
@ -825,36 +749,32 @@ bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, ui
uint8_t responsestr[9];
uint8_t e_response[32];
int i;
// calc number of command iterations to send
cmdlen = *kslen - ksoffset;
if (cmdlen < 10)
{
if (cmdlen < 10) {
UserMessage("hitag2crack_extend_keystream:\r\n cmdlen < 10\r\n");
return false;
}
numcmds = cmdlen / 10;
// build extended command
for (i=0; i<numcmds; i++)
{
for (i = 0; i < numcmds; i++) {
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
}
// xor extended cmd with keybits
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + ksoffset, numcmds * 10);
// send extended encrypted cmd
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false))
{
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) {
UserMessage("hitag2crack_extend_keystream:\r\n tx/rx cmd failed\r\n");
return false;
}
// test response
if (strcmp(responsestr, ERROR_RESPONSE) == 0)
{
if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
UserMessage("hitag2crack_extend_keystream:\r\n got error response from card\r\n");
return false;
}
@ -867,7 +787,7 @@ bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, ui
// update kslen
*kslen = ksoffset + (numcmds * 10) + 32;
return true;
}
@ -875,49 +795,39 @@ bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, ui
bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive) {
uint8_t tmp[9];
int i;
response[0] = '\0';
// auth to tag
if (hitag2_crypto_auth(tmp, key))
{
if (hitag2_crypto_auth(tmp, key)) {
// read tag, one page at a time
for (i= 0; i <= 7; ++i)
{
if(!read_tag(tmp, i, i))
{
for (i = 0; i <= 7; ++i) {
if (!read_tag(tmp, i, i)) {
// if read fails, it could be because of auth,
// so try to reauth
if (!hitag2_crypto_auth(tmp, key))
{
if (!hitag2_crypto_auth(tmp, key)) {
// if we can't reauth, it's a real failure
return false;
}
// temp failure (probably due to page protections)
strcpy(tmp, "XXXXXXXX");
strcpy(tmp, "XXXXXXXX");
}
// page contents are in tmp
strcat(response, tmp);
}
}
if (interactive)
{
tmp[8]= '\0';
for(i= 0; i <= 7 ; ++i)
{
UserMessageNum("%d: ", i);
memcpy(tmp, response + (i * 8), 8);
UserMessage("%s\r\n", tmp);
}
UserMessage("%s", "\r\n");
if (interactive) {
tmp[8] = '\0';
for (i = 0; i <= 7 ; ++i) {
UserMessageNum("%d: ", i);
memcpy(tmp, response + (i * 8), 8);
UserMessage("%s\r\n", tmp);
}
else
{
hitag2_nvm_store_tag(response);
}
return true;
}
else
{
UserMessage("%s", "\r\n");
} else {
hitag2_nvm_store_tag(response);
}
return true;
} else {
return false;
}
}

View file

@ -1952,11 +1952,11 @@ void check_challenges(bool file_given, uint8_t *data) {
u1++;
} else if (STATE == 2 && rxlen >= 44) {
Dbprintf("Challenge success: %02X%02X%02X%02X %02X%02X%02X%02X",
unlocker[u1 - 1][0], unlocker[u1 - 1][1],
unlocker[u1 - 1][2], unlocker[u1 - 1][3],
unlocker[u1 - 1][4], unlocker[u1 - 1][5],
unlocker[u1 - 1][6], unlocker[u1 - 1][7]);
Dbprintf("Challenge success: %02X%02X%02X%02X %02X%02X%02X%02X",
unlocker[u1 - 1][0], unlocker[u1 - 1][1],
unlocker[u1 - 1][2], unlocker[u1 - 1][3],
unlocker[u1 - 1][4], unlocker[u1 - 1][5],
unlocker[u1 - 1][6], unlocker[u1 - 1][7]);
STATE = 0;
}

View file

@ -1817,15 +1817,15 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
++check;
// test if the field exists
#if defined RDV4
#if defined RDV4
if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF_RDV40)) {
analogCnt++;
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_RDV40];
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
if (analogCnt >= 32) {
if ((MAX_ADC_HF_VOLTAGE_RDV40 * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
@ -1847,13 +1847,13 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
}
#else
if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) {
analogCnt++;
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF];
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
if (analogCnt >= 32) {
if ((MAX_ADC_HF_VOLTAGE * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {

View file

@ -81,7 +81,7 @@ void setSamplingConfig(sample_config *sc) {
printConfig();
}
sample_config *getSamplingConfig() {
sample_config *getSamplingConfig(void) {
return &config;
}
@ -117,8 +117,8 @@ void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) {
if (use_malloc) {
if (sample_size == NULL || *sample_size == 0 ) {
*sample_size = BigBuf_max_traceLen();
if (sample_size == NULL || *sample_size == 0) {
*sample_size = BigBuf_max_traceLen();
data.buffer = BigBuf_get_addr();
} else {
*sample_size = MIN(*sample_size, BigBuf_max_traceLen());
@ -127,7 +127,7 @@ void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) {
}
} else {
if (sample_size == NULL || *sample_size == 0 ) {
if (sample_size == NULL || *sample_size == 0) {
*sample_size = BigBuf_max_traceLen();
}
data.buffer = BigBuf_get_addr();
@ -221,7 +221,7 @@ void LFSetupFPGAForADC(int divisor, bool reader_field) {
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
// 50ms for the resonant antenna to settle.
if (reader_field)
SpinDelay(50);
SpinDelay(50);
// Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc();

View file

@ -1805,6 +1805,63 @@ void MifareChkKeys_file(uint8_t *fn) {
#endif
}
//-----------------------------------------------------------------------------
// MIFARE Personalize UID. Only for Mifare Classic EV1 7Byte UID
//-----------------------------------------------------------------------------
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key) {
uint16_t isOK = PM3_EUNDEF;
uint8_t uid[10];
uint32_t cuid;
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
set_tracing(true);
LED_A_ON();
while (true) {
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
break;
}
uint8_t block_number = 0;
if (mifare_classic_auth(pcs, cuid, block_number, keyType, key, AUTH_FIRST)) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error");
break;
}
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
int len = mifare_sendcmd_short(pcs, true, MIFARE_EV1_PERSONAL_UID, perso_option, receivedAnswer, receivedAnswerPar, NULL);
if (len != 1 || receivedAnswer[0] != CARD_ACK) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
break;;
}
if (mifare_classic_halt(pcs, cuid)) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
break;
}
isOK = PM3_SUCCESS;
break;
}
crypto1_deinit(pcs);
LED_B_ON();
reply_ng(CMD_HF_MIFARE_PERSONALIZE_UID, isOK, NULL, 0);
LED_B_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
//-----------------------------------------------------------------------------
// Work with emulator memory
//
@ -2276,23 +2333,23 @@ void MifareSetMod(uint8_t *datain) {
while (true) {
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
if (DBGLEVEL >= 1) Dbprintf("Can't select card");
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
break;
}
if (mifare_classic_auth(pcs, cuid, 0, 0, ui64Key, AUTH_FIRST)) {
if (DBGLEVEL >= 1) Dbprintf("Auth error");
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error");
break;
}
int respLen;
if (((respLen = mifare_sendcmd_short(pcs, CRYPT_ALL, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) {
if (DBGLEVEL >= 1) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen);
if (DBGLEVEL >= DBG_ERROR) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen);
break;
}
if (mifare_classic_halt(pcs, cuid)) {
if (DBGLEVEL >= 1) Dbprintf("Halt error");
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error");
break;
}
@ -2304,7 +2361,6 @@ void MifareSetMod(uint8_t *datain) {
LED_B_ON();
reply_ng(CMD_HF_MIFARE_SETMOD, isOK, NULL, 0);
LED_B_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);

View file

@ -45,6 +45,8 @@ void MifareCIdent(); // is "magic chinese" card?
void MifareHasStaticNonce(); // Has the tag a static nonce?
void MifareSetMod(uint8_t *datain);
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key);
void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
void OnSuccessMagic();
void OnErrorMagic(uint8_t reason);

View file

@ -537,13 +537,13 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
// find reader field
if (cardSTATE == MFEMUL_NOFIELD) {
#if defined RDV4
vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
#else
vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
#endif
if (vHf > MF_MINFIELDV) {
cardSTATE_TO_IDLE();
LED_A_ON();

View file

@ -130,7 +130,7 @@ CORESRCS = uart_posix.c \
util_posix.c \
scandir.c \
crc16.c \
comms.c
comms.c
CMDSRCS = crapto1/crapto1.c \
crapto1/crypto1.c \

View file

@ -315,7 +315,7 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) {
}
int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
int ret_val = PM3_SUCCESS;
// We want to mount before multiple operation so the lazy writes/append will not
@ -349,7 +349,7 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
bytes_sent += bytes_in_packet;
PacketResponseNG resp;
uint8_t retry = 3;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
@ -377,7 +377,7 @@ out:
// We want to unmount after these to set things back to normal but more than this
// unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
return ret_val;
}
@ -400,8 +400,8 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
cmdp += 2;
break;
case 'o':
param_getstr(Cmd, cmdp + 1, (char*)destfilename, 32);
if (strlen((char*)destfilename) == 0) {
param_getstr(Cmd, cmdp + 1, (char *)destfilename, 32);
if (strlen((char *)destfilename) == 0) {
PrintAndLogEx(FAILED, "Destination Filename missing or invalid");
errors = true;
}
@ -429,12 +429,12 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
}
res = flashmem_spiffs_load(destfilename, data, datalen);
free(data);
if ( res == PM3_SUCCESS )
if (res == PM3_SUCCESS)
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename);
return res;
}

View file

@ -861,7 +861,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
getMemConfig(mem, chip, &max_blk, &app_areas, &kb);
uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
BLOCK79ENCRYPTION aa1_encryption = (decrypted[(6 * 8) + 7] & 0x03);
for (uint16_t blocknum = 0; blocknum < applimit; ++blocknum) {
@ -894,36 +894,36 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
saveFileJSON(fptr, jsfIclass, decrypted, decryptedlen);
printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen);
// decode block 6
if (memcmp(decrypted + (8*6), empty, 8) != 0 ) {
if (memcmp(decrypted + (8 * 6), empty, 8) != 0) {
if (use_sc) {
DecodeBlock6(decrypted + (8*6));
DecodeBlock6(decrypted + (8 * 6));
}
}
// decode block 7-8-9
if (memcmp(decrypted + (8*7), empty, 8) != 0 ) {
// decode block 7-8-9
if (memcmp(decrypted + (8 * 7), empty, 8) != 0) {
//todo: remove preamble/sentinal
uint32_t top = 0, mid, bot;
mid = bytes_to_num(decrypted + (8*7), 4);
bot = bytes_to_num(decrypted + (8*7) + 4, 4);
mid = bytes_to_num(decrypted + (8 * 7), 4);
bot = bytes_to_num(decrypted + (8 * 7) + 4, 4);
PrintAndLogEx(INFO, "Block 7 binary");
PrintAndLogEx(INFO, "Block 7 binary");
char hexstr[8+1] = {0};
hex_to_buffer((uint8_t *)hexstr, decrypted + (8*7), 8, sizeof(hexstr) - 1, 0, 0, true);
char binstr[8*8+1] = {0};
char hexstr[8 + 1] = {0};
hex_to_buffer((uint8_t *)hexstr, decrypted + (8 * 7), 8, sizeof(hexstr) - 1, 0, 0, true);
char binstr[8 * 8 + 1] = {0};
hextobinstring(binstr, hexstr);
uint8_t i=0;
while (i<strlen(binstr) && binstr[i++] == '0');
uint8_t i = 0;
while (i < strlen(binstr) && binstr[i++] == '0');
PrintAndLogEx(SUCCESS, "%s", binstr + i);
PrintAndLogEx(INFO, "Wiegand decode");
wiegand_message_t packed = initialize_message_object(top, mid, bot);
HIDTryUnpack(&packed, true);
@ -931,7 +931,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
} else {
PrintAndLogEx(INFO, "No credential found.");
}
free(decrypted);
free(fptr);
}
@ -1757,7 +1757,7 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
}
PrintAndLogEx(SUCCESS, "block %02X: %s\n", blockno, sprint_hex(result->blockdata, sizeof(result->blockdata)));
if (blockno == 6) {
if (IsCryptoHelperPresent()) {
DecodeBlock6(result->blockdata);

View file

@ -218,15 +218,15 @@ static int lto_rdbl(uint8_t blk, uint8_t *block_responce, uint8_t *block_cnt_res
uint16_t resp_len = 18;
uint8_t rdbl_cmd[] = {0x30, blk};
uint8_t rdbl_cnt_cmd[] ={0x80};
uint8_t rdbl_cnt_cmd[] = {0x80};
int status = lto_send_cmd_raw(rdbl_cmd, sizeof(rdbl_cmd), block_responce, &resp_len, true, false, verbose);
if (status == PM3_ETIMEOUT || status == PM3_ESOFT ) {
if (status == PM3_ETIMEOUT || status == PM3_ESOFT) {
return PM3_EWRONGANSVER; // READ BLOCK failed
}
status = lto_send_cmd_raw(rdbl_cnt_cmd, sizeof(rdbl_cnt_cmd), block_cnt_responce, &resp_len, false, false, verbose);
if (status == PM3_ETIMEOUT || status == PM3_ESOFT ) {
if (status == PM3_ETIMEOUT || status == PM3_ESOFT) {
return PM3_EWRONGANSVER; // READ BLOCK CONTINUE failed
}
@ -252,7 +252,7 @@ int rdblLTO(uint8_t st_blk, uint8_t end_blk, bool verbose) {
uint8_t block_data_d16_d31[18];
uint8_t block_data[32];
for(uint8_t i = st_blk; i < end_blk + 1; i++) {
for (uint8_t i = st_blk; i < end_blk + 1; i++) {
ret_val = lto_rdbl(i, block_data_d00_d15, block_data_d16_d31, verbose);
@ -286,8 +286,8 @@ static int CmdHfLTOReadBlock(const char *Cmd) {
case 'h':
return usage_lto_rdbl();
case 's':
st_blk = param_get8(Cmd, cmdp+1);
if ( end_blk < st_blk ) {
st_blk = param_get8(Cmd, cmdp + 1);
if (end_blk < st_blk) {
errors = true;
break;
}
@ -295,10 +295,11 @@ static int CmdHfLTOReadBlock(const char *Cmd) {
break;
case 'e':
end_blk = param_get8(Cmd, cmdp+1);
if ( end_blk < st_blk ) {
end_blk = param_get8(Cmd, cmdp + 1);
if (end_blk < st_blk) {
errors = true;
break; }
break;
}
cmdp += 2;
break;
@ -328,7 +329,7 @@ static int lto_wrbl(uint8_t blk, uint8_t *data, bool verbose) {
for (int i = 0; i < 16; i++) {
wrbl_d00_d15[i] = data[i];
wrbl_d16_d31[i] = data[i+16];
wrbl_d16_d31[i] = data[i + 16];
}
int status = lto_send_cmd_raw(wrbl_cmd, sizeof(wrbl_cmd), resp, &resp_len, true, false, verbose);
@ -390,15 +391,15 @@ static int CmdHfLTOWriteBlock(const char *Cmd) {
case 'h':
return usage_lto_wrbl();
case 'b':
blk = param_get8(Cmd, cmdp+1);
blk = param_get8(Cmd, cmdp + 1);
b_opt_selected = true;
cmdp += 2;
break;
case 'd':
if (param_gethex(Cmd, cmdp+1, blkData, 64)) {
if (param_gethex(Cmd, cmdp + 1, blkData, 64)) {
PrintAndLogEx(WARNING, "block data must include 64 HEX symbols");
errors = true;
break;
break;
}
d_opt_selected = true;
cmdp += 2;
@ -409,7 +410,7 @@ static int CmdHfLTOWriteBlock(const char *Cmd) {
break;
}
}
//Validations
if (errors) {
usage_lto_wrbl();
@ -440,7 +441,7 @@ int dumpLTO(uint8_t *dump, bool verbose) {
uint8_t block_data_d00_d15[18];
uint8_t block_data_d16_d31[18];
for(uint8_t i = 0; i < 255; i++) {
for (uint8_t i = 0; i < 255; i++) {
ret_val = lto_rdbl(i, block_data_d00_d15, block_data_d16_d31, verbose);
@ -504,10 +505,10 @@ static int CmdHfLTODump(const char *Cmd) {
int ret_val = dumpLTO(dump, true);
if (ret_val != PM3_SUCCESS) {
free(dump);
return ret_val;
return ret_val;
}
// save to file
// save to file
if (filename[0] == '\0') {
memcpy(serial_number, sprint_hex_inrow(dump, sizeof(serial_number)), sizeof(serial_number));
char tmp_name[17] = "hf_lto_";
@ -538,10 +539,10 @@ int restoreLTO(uint8_t *dump_data, bool verbose) {
return ret_val;
}
uint8_t blkData[32] = {0};
uint8_t blkData[32] = {0};
//Block address 0 and 1 are read-only
for(uint8_t blk = 2; blk < 255; blk++) {
for (uint8_t blk = 2; blk < 255; blk++) {
for (int i = 0; i < 32; i++) {
blkData[i] = dump_data[i + blk * 32];
@ -550,7 +551,7 @@ int restoreLTO(uint8_t *dump_data, bool verbose) {
ret_val = lto_wrbl(blk, blkData, verbose);
if (ret_val == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "BLK %03d: " _YELLOW_("write success"), blk);
PrintAndLogEx(SUCCESS, "BLK %03d: " _YELLOW_("write success"), blk);
} else {
lto_switch_off_field();
return ret_val;
@ -566,7 +567,7 @@ static int CmdHfLTRestore(const char *Cmd) {
uint8_t cmdp = 0;
bool errors = false;
int is_data_loaded = PM3_ESOFT;
char filename[FILE_PATH_SIZE] = {0};
char extension[FILE_PATH_SIZE] = {0};
@ -623,7 +624,7 @@ static int CmdHfLTRestore(const char *Cmd) {
} else {
return PM3_EFILE;
}
}
static command_t CommandTable[] = {

View file

@ -3129,7 +3129,7 @@ out:
}
sector_t *k_sector = NULL;
uint8_t k_sectorsCount = 16;
uint8_t k_sectorsCount = 40;
void showSectorTable() {
if (k_sector != NULL) {
@ -4798,6 +4798,95 @@ static int CmdHFMFNDEF(const char *Cmd) {
return PM3_SUCCESS;
}
int CmdHFMFPersonalize(const char *cmd) {
CLIParserInit("hf mf personalize",
"Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.",
"Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n"
"\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n"
"\thf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n"
"\thf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n"
"\thf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A\n");
void *argtable[] = {
arg_param_begin,
arg_str0("tT", "keytype", "<A|B>", "key type (A or B) to authenticate sector 0 (default: A)"),
arg_str0("kK", "key", "<key (hex 6 Bytes)>", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"),
arg_str1(NULL, NULL, "<UIDF0|UIDF1|UIDF2|UIDF3>", "Personalization Option"),
arg_param_end
};
CLIExecWithReturn(cmd, argtable, true);
char keytypestr[2] = "a";
uint8_t keytype = 0x00;
int keytypestr_len;
int res = CLIParamStrToBuf(arg_get_str(1), (uint8_t *)keytypestr, 1, &keytypestr_len);
str_lower(keytypestr);
if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'b')) {
PrintAndLogEx(ERR, "ERROR: not a valid key type. Key type must be A or B");
CLIParserFree();
return PM3_EINVARG;
}
if (keytypestr[0] == 'b') {
keytype = 0x01;
}
uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
int key_len;
res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len);
if (res || (!res && key_len > 0 && key_len != 6)) {
PrintAndLogEx(ERR, "ERROR: not a valid key. Key must be 12 hex digits");
CLIParserFree();
return PM3_EINVARG;
}
char pers_optionstr[6];
int opt_len;
uint8_t pers_option;
res = CLIParamStrToBuf(arg_get_str(3), (uint8_t *)pers_optionstr, 5, &opt_len);
str_lower(pers_optionstr);
if (res || (!res && opt_len > 0 && opt_len != 5)
|| (strncmp(pers_optionstr, "uidf0", 5) && strncmp(pers_optionstr, "uidf1", 5) && strncmp(pers_optionstr, "uidf2", 5) && strncmp(pers_optionstr, "uidf3", 5))) {
PrintAndLogEx(ERR, "ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3");
CLIParserFree();
return PM3_EINVARG;
}
if (!strncmp(pers_optionstr, "uidf0", 5)) {
pers_option = MIFARE_EV1_UIDF0;
} else if (!strncmp(pers_optionstr, "uidf1", 5)) {
pers_option = MIFARE_EV1_UIDF1;
} else if (!strncmp(pers_optionstr, "uidf2", 5)) {
pers_option = MIFARE_EV1_UIDF2;
} else {
pers_option = MIFARE_EV1_UIDF3;
}
CLIParserFree();
clearCommandBuffer();
struct {
uint8_t keytype;
uint8_t pers_option;
uint8_t key[6];
} PACKED payload;
payload.keytype = keytype;
payload.pers_option = pers_option;
memcpy(payload.key, key, 6);
SendCommandNG(CMD_HF_MIFARE_PERSONALIZE_UID, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_HF_MIFARE_PERSONALIZE_UID, &resp, 2500)) return PM3_ETIMEOUT;
PrintAndLogEx(SUCCESS, "Personalization %s", resp.status == PM3_SUCCESS ? "SUCCEEDED" : "FAILED");
return PM3_SUCCESS;
}
static int CmdHF14AMfList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
return CmdTraceList("mf");
@ -4845,7 +4934,7 @@ static command_t CommandTable[] = {
{"-----------", CmdHelp, IfPm3Iso14443a, ""},
{"mad", CmdHF14AMfMAD, IfPm3Iso14443a, "Checks and prints MAD"},
{"ndef", CmdHFMFNDEF, IfPm3Iso14443a, "Prints NDEF records from card"},
{"personalize", CmdHFMFPersonalize, IfPm3Iso14443a, "Personalize UID (Mifare Classic EV1 only)"},
{"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},
{NULL, NULL, NULL, NULL}
};

View file

@ -1505,7 +1505,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_
SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0);
return 1;
}
// error during nested_hard
if (resp.oldarg[0]) {
if (nonce_file_write) {
@ -2034,7 +2034,7 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) {
// create mutexes for accessing the statelist cache and our "book of work"
pthread_mutex_init(&statelist_cache_mutex, NULL);
pthread_mutex_init(&book_of_work_mutex, NULL);
init_statelist_cache();
init_book_of_work();

View file

@ -457,6 +457,24 @@ int CmdFlexdemod(const char *Cmd) {
return PM3_SUCCESS;
}
int lf_getconfig(sample_config *config) {
if (!session.pm3_present) return PM3_ENOTTY;
if (config == NULL)
return PM3_EINVARG;
clearCommandBuffer();
SendCommandNG(CMD_LF_SAMPLING_GET_CONFIG, NULL, 0);
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_SAMPLING_GET_CONFIG, &resp, 2000)) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
memcpy(config, resp.data.asBytes, sizeof(sample_config));
return PM3_SUCCESS;
}
int lf_config(sample_config *config) {
if (!session.pm3_present) return PM3_ENOTTY;
@ -464,7 +482,7 @@ int lf_config(sample_config *config) {
if (config != NULL)
SendCommandNG(CMD_LF_SAMPLING_SET_CONFIG, (uint8_t *)config, sizeof(sample_config));
else
SendCommandNG(CMD_LF_SAMPLING_GET_CONFIG, NULL, 0);
SendCommandNG(CMD_LF_SAMPLING_PRINT_CONFIG, NULL, 0);
return PM3_SUCCESS;
}
@ -1333,7 +1351,7 @@ static command_t CommandTable[] = {
{"fdx", CmdLFFdx, AlwaysAvailable, "{ FDX-B RFIDs... }"},
{"gallagher", CmdLFGallagher, AlwaysAvailable, "{ GALLAGHER RFIDs... }"},
{"gproxii", CmdLFGuard, AlwaysAvailable, "{ Guardall Prox II RFIDs... }"},
{"hid", CmdLFHID, AlwaysAvailable, "{ HID RFIDs... }"},
{"hid", CmdLFHID, AlwaysAvailable, "{ HID Prox RFIDs... }"},
{"hitag", CmdLFHitag, AlwaysAvailable, "{ Hitag CHIPs... }"},
{"indala", CmdLFINDALA, AlwaysAvailable, "{ Indala RFIDs... }"},
{"io", CmdLFIO, AlwaysAvailable, "{ ioProx RFIDs... }"},

View file

@ -34,5 +34,6 @@ int CmdLFfind(const char *Cmd);
int lf_read(bool verbose, uint32_t samples);
int lf_config(sample_config *config);
int lf_getconfig(sample_config *config);
#endif

View file

@ -1039,9 +1039,9 @@ static int CmdEM4x50Write(const char *Cmd) {
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_lf_em4x50_write();
PrintAndLogEx(NORMAL, "no implemented yet");
//
//
// PrintAndLogEx(SUCCESS, "Done");
// PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x50_read`") "to verify");
// PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x50_read`") "to verify");
return PM3_SUCCESS;
}
@ -1440,7 +1440,7 @@ static int CmdEM4x05Write(const char *Cmd) {
int status = demodEM4x05resp(&dummy);
if (status == PM3_SUCCESS)
PrintAndLogEx(SUCCESS, "Success writing to tag");
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x05_read`") "to verify");
return status;

View file

@ -187,7 +187,10 @@ static int CmdGuardClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Guardall to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber);
print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf gprox read`") "to verify");
return res;
}
static int CmdGuardSim(const char *Cmd) {

View file

@ -346,7 +346,7 @@ static int CmdHIDClone(const char *Cmd) {
clearCommandBuffer();
SendCommandMIX(CMD_LF_HID_CLONE, hi2, hi, lo, longid, sizeof(longid));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf hid read`") "to verify");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf hid read`") "to verify");
return PM3_SUCCESS;
}
@ -450,7 +450,7 @@ static int CmdHIDBrute(const char *Cmd) {
PrintAndLogEx(INFO, "ISSUE#........... %u", cn_hi.IssueLevel);
PrintAndLogEx(INFO, "Facility#........ %u", cn_hi.FacilityCode);
PrintAndLogEx(INFO, "Card#............ %" PRIu64, cn_hi.CardNumber);
switch( direction) {
switch (direction) {
case 0:
PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("BOTH"));
break;
@ -460,7 +460,8 @@ static int CmdHIDBrute(const char *Cmd) {
case 2:
PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("DOWN"));
break;
default: break;
default:
break;
}
}
PrintAndLogEx(INFO, "Brute-forcing HID reader");
@ -495,7 +496,7 @@ static int CmdHIDBrute(const char *Cmd) {
fin_hi = true;
}
}
// do one down
if (direction != 1) {
if (cn_low.CardNumber > 0) {
@ -507,7 +508,7 @@ static int CmdHIDBrute(const char *Cmd) {
}
switch (direction) {
case 0:
case 0:
if (fin_hi && fin_low) {
exitloop = true;
}
@ -518,7 +519,8 @@ static int CmdHIDBrute(const char *Cmd) {
case 2:
exitloop = fin_low;
break;
default: break;
default:
break;
}
} while (exitloop == false);

View file

@ -28,6 +28,8 @@
#include "protocols.h" // t55 defines
#include "cmdlft55xx.h" // verifywrite
#define INDALA_ARR_LEN 64
static int CmdHelp(const char *Cmd);
//large 224 bit indala formats (different preamble too...)
@ -140,7 +142,7 @@ static void decodeHeden2L(uint8_t *bits) {
if (bits[offset + 7]) cardnumber += 16384;
if (bits[offset + 23]) cardnumber += 32768;
PrintAndLogEx(SUCCESS, "\tHeden-2L | %u", cardnumber);
PrintAndLogEx(SUCCESS, "\tHeden-2L | " _YELLOW_("%u"), cardnumber);
}
// Indala 26 bit decode
@ -192,7 +194,7 @@ static int CmdIndalaDemod(const char *Cmd) {
if (DemodBufferLen == 64) {
PrintAndLogEx(
SUCCESS
, "Indala Found - bitlength %zu, Raw %x%08x"
, "Indala Found - bitlength %zu, Raw " _YELLOW_("%x%08x")
, DemodBufferLen
, uid1
, uid2
@ -244,14 +246,18 @@ static int CmdIndalaDemod(const char *Cmd) {
checksum |= DemodBuffer[63] << 0; // b1
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "Fmt 26 bit FC " _YELLOW_("%u") ", CN " _YELLOW_("%u") ", checksum %1d%1d"
, fc
, csn
, checksum >> 1 & 0x01
, checksum & 0x01
);
PrintAndLogEx(SUCCESS, "Possible de-scramble patterns");
PrintAndLogEx(SUCCESS, "\tPrinted | __%04d__ [0x%X]", p1, p1);
PrintAndLogEx(SUCCESS, "\tInternal ID | %" PRIu64, foo);
decodeHeden2L(DemodBuffer);
PrintAndLogEx(SUCCESS, "Fmt 26 bit FC %u , CSN %u , checksum %1d%1d", fc, csn, checksum >> 1 & 0x01, checksum & 0x01);
} else {
uint32_t uid3 = bytebits_to_byte(DemodBuffer + 64, 32);
uint32_t uid4 = bytebits_to_byte(DemodBuffer + 96, 32);
@ -542,49 +548,62 @@ static int CmdIndalaSim(const char *Cmd) {
static int CmdIndalaClone(const char *Cmd) {
bool is_long_uid = false, got_cn = false;
bool is_long_uid = false, got_cn = false, got_26 = false;
bool is_t5555 = false;
int32_t cardnumber;
uint32_t blocks[8] = {0};
uint8_t max = 0;
uint8_t data[7 * 4];
int datalen = 0;
uint8_t fc = 0;
uint16_t cn = 0;
CLIParserInit("lf indala clone",
"clone INDALA tag to T55x7 (or to q5/T5555)",
"Examples:\n"
"\tlf indala clone -c 888\n"
"\tlf indala clone --heden 888\n"
"\tlf indala clone --fc 123 --cn 1337\n"
"\tlf indala clone -r a0000000a0002021\n"
"\tlf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
void *argtable[] = {
arg_param_begin,
arg_lit0("lL", "long", "optional - long UID 224 bits"),
arg_int0("cC", "cn", "<decimal>", "Cardnumber for Heden 2L format"),
arg_strx0("rR", "raw", "<hex>", "raw bytes"),
arg_lit0("qQ", "Q5", "optional - specify write to Q5 (t5555 instead of t55x7)"),
arg_lit0("lL", "long", "optional - long UID 224 bits"),
arg_int0("cC", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
arg_strx0("rR", "raw", "<hex>", "raw bytes"),
arg_lit0("qQ", "Q5", "optional - specify write to Q5 (t5555 instead of t55x7)"),
arg_int0("", "fc", "<decimal>", "Facility Code (26 bit format)"),
arg_int0("", "cn", "<decimal>", "Cardnumber (26 bit format)"),
arg_param_end
};
CLIExecWithReturn(Cmd, argtable, false);
is_long_uid = arg_get_lit(1);
if (is_long_uid == false) {
cardnumber = arg_get_int_def(2, -1);
got_cn = (cardnumber != -1);
}
if (got_cn == false) {
CLIGetHexWithReturn(3, data, &datalen);
}
// raw param
CLIGetHexWithReturn(3, data, &datalen);
is_t5555 = arg_get_lit(4);
if (is_long_uid == false) {
// Heden param
cardnumber = arg_get_int_def(2, -1);
got_cn = (cardnumber != -1);
// 26b FC/CN param
fc = arg_get_int_def(5, 0);
cn = arg_get_int_def(6, 0);
got_26 = (fc != 0 && cn != 0);
}
CLIParserFree();
if (is_long_uid) {
// 224 BIT UID
// config for Indala (RF/32;PSK2 with RF/2;Maxblock=7)
PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with RawID %s", sprint_hex(data, datalen));
PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag");
PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen));
if (is_t5555)
blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT);
@ -602,12 +621,41 @@ static int CmdIndalaClone(const char *Cmd) {
} else {
// 64 BIT UID
if (got_cn) {
PrintAndLogEx(INFO, "Using Indala HEDEN cardnumber %u", cardnumber);
encodeHeden2L(data, cardnumber);
datalen = 8;
} else if (got_26) {
PrintAndLogEx(INFO, "Using Indala 26b FC %u CN %u", fc, cn);
// Used with the 26bit FC/CSN
uint8_t *bits = calloc(INDALA_ARR_LEN, sizeof(uint8_t));
if (bits == NULL) {
PrintAndLogEx(WARNING, "Failed to allocate memory");
return PM3_EMALLOC;
}
if (getIndalaBits(fc, cn, bits) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
return PM3_ESOFT;
}
data[0] = bytebits_to_byte(bits, 8);
data[1] = bytebits_to_byte(bits + 8, 8);
data[2] = bytebits_to_byte(bits + 16, 8);
data[3] = bytebits_to_byte(bits + 24, 8);
data[4] = bytebits_to_byte(bits + 32, 8);
data[5] = bytebits_to_byte(bits + 40, 8);
data[6] = bytebits_to_byte(bits + 48, 8);
data[7] = bytebits_to_byte(bits + 56, 8);
datalen = 8;
free(bits);
}
// config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2)
PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with RawID %s", sprint_hex(data, datalen));
PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag");
PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen));
if (is_t5555)
blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | (2 << T5555_MAXBLOCK_SHIFT);
@ -647,6 +695,66 @@ int CmdLFINDALA(const char *Cmd) {
return CmdsParse(CommandTable, Cmd);
}
int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits) {
// preamble
// is there a preamble?
bits[0] = 1;
bits[2] = 1;
bits[32] = 1;
// add fc
bits[57] = ((fc >> 7) & 1); // b8
bits[49] = ((fc >> 6) & 1); // b7
bits[44] = ((fc >> 5) & 1); // b6
bits[47] = ((fc >> 4) & 1); // b5
bits[48] = ((fc >> 3) & 1); // b4
bits[53] = ((fc >> 2) & 1); // b3
bits[39] = ((fc >> 1) & 1); // b2
bits[58] = (fc & 1); // b1
// add cn
bits[42] = ((cn >> 15) & 1); // b16
bits[45] = ((cn >> 14) & 1); // b15 - c
bits[43] = ((cn >> 13) & 1); // b14
bits[40] = ((cn >> 12) & 1); // b13 - c
bits[52] = ((cn >> 11) & 1); // b12
bits[36] = ((cn >> 10) & 1); // b11
bits[35] = ((cn >> 9) & 1); // b10 - c
bits[51] = ((cn >> 8) & 1); // b9 - c
bits[46] = ((cn >> 7) & 1); // b8
bits[33] = ((cn >> 6) & 1); // b7 - c
bits[37] = ((cn >> 5) & 1); // b6 - c
bits[54] = ((cn >> 4) & 1); // b5
bits[56] = ((cn >> 3) & 1); // b4
bits[59] = ((cn >> 2) & 1); // b3 - c
bits[50] = ((cn >> 1) & 1); // b2
bits[41] = (cn & 1); // b1 - c
// checksum
uint8_t chk = 0;
//sum(y2, y4, y7, y8, y10, y11, y14, y16
chk += ((cn >> 14) & 1); //y2 == 75 - 30 = 45
chk += ((cn >> 12) & 1); //y4 == 70 - 30 = 40
chk += ((cn >> 9) & 1); //y7 == 65 - 30 = 35
chk += ((cn >> 8) & 1); //y8 == 81 - 30 = 51
chk += ((cn >> 6) & 1); //y10 == 63 - 30 = 33
chk += ((cn >> 5) & 1); //y11 == 67 - 30 = 37
chk += ((cn >> 2) & 1); //y14 == 89 - 30 = 59
chk += (cn & 1); //y16 == 71 - 30 = 41
if ((chk & 1) == 0) {
bits[62] = 0;
bits[63] = 1;
} else {
bits[62] = 1;
bits[63] = 0;
}
// 92 = 62
// 93 = 63
return PM3_SUCCESS;
}
// redesigned by marshmellow adjusted from existing decode functions
// indala id decoding
int detectIndala(uint8_t *dest, size_t *size, uint8_t *invert) {

View file

@ -19,5 +19,6 @@ int detectIndala26(uint8_t *bitStream, size_t *size, uint8_t *invert);
int detectIndala64(uint8_t *bitStream, size_t *size, uint8_t *invert);
int detectIndala224(uint8_t *bitStream, size_t *size, uint8_t *invert);
int demodIndala(void);
int getIndalaBits(uint8_t fc, uint16_t csn, uint8_t *bits);
#endif

View file

@ -1083,3 +1083,4 @@ fc9839273862
4D8B8B95FDEE
354A787087F1
4a306e62e9b6
B9C874AE63D0

View file

@ -529,7 +529,7 @@ const char ice[] =
" !!: :!! !!: !!: !!: !!: !!! !!: !!!\n : :: :: : : :: ::: : : : : : :: : \n"
_RED_(" . .. .. . . .. ... . . . . . .. . ")
"\n...................................................................\n"
;
;
// Write a file's segments to Flash
int flash_write(flash_file_t *ctx) {
@ -566,8 +566,8 @@ int flash_write(flash_file_t *ctx) {
baddr += block_size;
length -= block_size;
block++;
if ( len < strlen(ice) ) {
if (filter_ansi && !isalpha(ice[len]) ) {
if (len < strlen(ice)) {
if (filter_ansi && !isalpha(ice[len])) {
len++;
} else {
fprintf(stdout, "%c", ice[len++]);

View file

@ -1,27 +1,34 @@
-- Run me like this: proxmark3 /dev/rfcomm0 -l ./hf_bruteforce.lua
-- Run me like this (connected via USB): ./pm3 -l hf_bruteforce.lua
-- Run me like this (connected via Blueshark addon): ./client/proxmark3 /dev/rfcomm0 -l ./hf_bruteforce.lua
local getopt = require('getopt')
copyright = ''
author = 'Keld Norman'
version = 'v1.0.0'
desc = [[
]]
example = [[
-- (the above example would bruteforce card number, starting at 1, ending at 10, and waiting 1 second between each card)
script run hf_bruteforce -s 1 -e 10 -t 1000
]]
author = 'Daniel Underhay (updated), Keld Norman(original)'
version = 'v2.0.0'
usage = [[
script run hf_bruteforce -s start_id -e end_id -t timeout -d direction
pm3 --> script run hf_bruteforce -s start_id -e end_id -t timeout -x mifare_card_type
Arguments:
-h this help
-s 0-0xFFFFFFFF start id
-e 0-0xFFFFFFFF end id
-t 0-99999, pause timeout (ms) between cards (use the word 'pause' to wait for user input)
-t 0-99999, pause timeout (ms) between cards (use the word 'pause' to wait for user input)
-x mfc, mfu mifare type: mfc for Mifare Classic (default) or mfu for Mifare Ultralight EV1
Example:
pm3 --> script run hf_bruteforce -s 0x11223344 -e 0x11223346 -t 1000 -x mfc
Bruteforce a 4 byte UID Mifare classic card number, starting at 11223344, ending at 11223346.
pm3 --> script run hf_bruteforce -s 0x11223344556677 -e 0x11223344556679 -t 1000 -x mfu
Bruteforce a 7 byte UID Mifare Ultralight card number, starting at 11223344556677, ending at 11223344556679.
]]
@ -60,41 +67,49 @@ local function help()
print(usage)
end
---
-- Exit message
local function exitMsg(msg)
--- Print user message
local function msg(msg)
print( string.rep('--',20) )
print('')
print(msg)
print('')
print( string.rep('--',20) )
print()
end
---
-- Start
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local timeout = 0
local start_id = 0
local end_id = 0xFFFFFFFF
local end_id = 0xFFFFFFFFFFFFFF
local mftype = 'mfc'
for o, a in getopt.getopt(args, 'e:s:t:h') do
for o, a in getopt.getopt(args, 'e:s:t:x:h') do
if o == 's' then start_id = a end
if o == 'e' then end_id = a end
if o == 't' then timeout = a end
if o == 'x' then mftype = a end
if o == 'h' then return print(usage) end
end
-- template
local command = 'hf 14a sim t 1 u %08X'
local command = ''
print(' Bruteforcing MFC card numbers from 00000000 to FFFFFFFF using delay: '..timeout)
print('')
print( string.rep('--',20) )
if mftype == 'mfc' then
command = 'hf 14a sim t 1 u %14X'
msg('Bruteforcing Mifare Classic card numbers')
elseif mftype == 'mfu' then
command = 'hf 14a sim t 2 u %14X'
msg('Bruteforcing Mifare Ultralight card numbers')
else
return print(usage)
end
if command == '' then return print(usage) end
for n = start_id, end_id do
local c = string.format( command, n )
print(' Running: "'..c..'"')
print('Running: "'..c..'"')
core.console(c)
core.console('msleep '..timeout);
core.console('hw ping')
@ -102,4 +117,3 @@ local function main(args)
end
main(args)

View file

@ -152,7 +152,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
if (*key != UINT64_C(-1)) {
break;
} else {
PrintAndLogEx(FAILED, "all candidate keys failed. Restarting darkside attack");
PrintAndLogEx(FAILED, "all key candidates failed. Restarting darkside attack");
free(last_keylist);
last_keylist = keylist;
first_run = true;
@ -345,7 +345,7 @@ int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultk
// copy candidatekeys to test key block
memcpy(keyBlock, candidates + i, KEYBLOCK_SIZE);
// check a block of generated candidate keys.
// check a block of generated key candidates.
if (mfCheckKeys(blockNo, keyType, true, KEYS_IN_BLOCK, keyBlock, &key64) == PM3_SUCCESS) {
*resultkey = key64;
found = true;
@ -510,7 +510,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
uint32_t keycnt = statelists[0].len;
if (keycnt == 0) goto out;
PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt);
PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "key candidates", keycnt);
memset(resultKey, 0, 6);
uint64_t key64 = -1;
@ -544,10 +544,10 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
return -5;
}
float bruteforce_per_second = (float)KEYS_IN_BLOCK / (msclock() - start_time) * 1000.0;
if ( i + 1 % 10 == 0)
PrintAndLogEx(INFO, " %6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt , bruteforce_per_second, (keycnt-i) / bruteforce_per_second);
// if (i + 1 % 10 == 0) {
float bruteforce_per_second = (float)(i + max_keys) / ((msclock() - start_time) / 1000.0);
PrintAndLogEx(INFO, "%6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second);
// }
}
@ -644,7 +644,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
uint32_t keycnt = statelists[0].len;
if (keycnt == 0) goto out;
PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt);
PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "key candidates", keycnt);
memset(resultKey, 0, 6);
uint64_t key64 = -1;
@ -653,7 +653,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
uint32_t maxkeysinblock = IfPm3Flash() ? 1000 : KEYS_IN_BLOCK;
uint32_t max_keys_chunk = keycnt > maxkeysinblock ? maxkeysinblock : keycnt;
uint8_t *mem = calloc( (maxkeysinblock * 6) + 5, sizeof(uint8_t));
uint8_t *mem = calloc((maxkeysinblock * 6) + 5, sizeof(uint8_t));
if (mem == NULL) {
free(statelists[0].head.slhead);
return PM3_EMALLOC;
@ -667,7 +667,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
mem[4] = (max_keys_chunk & 0xFF);
uint8_t destfn[32];
strncpy((char*)destfn, "static_nested_000.bin", sizeof(destfn) - 1);
strncpy((char *)destfn, "static_nested_000.bin", sizeof(destfn) - 1);
uint64_t start_time = msclock();
for (uint32_t i = 0; i < keycnt; i += max_keys_chunk) {
@ -689,10 +689,10 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
num_to_bytes(key64, 6, p_keyblock + j * 6);
}
// check a block of generated candidate keys.
// check a block of generated key candidates.
if (IfPm3Flash()) {
// upload to flash.
res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6) );
// upload to flash.
res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6));
if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "SPIFFS upload failed");
free(mem);
@ -705,13 +705,13 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
}
if (res == PM3_SUCCESS) {
p_keyblock = NULL;
free(statelists[0].head.slhead);
free(mem);
p_keyblock = NULL;
free(statelists[0].head.slhead);
free(mem);
num_to_bytes(key64, 6, resultKey);
num_to_bytes(key64, 6, resultKey);
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]",
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]",
package->block,
package->keytype ? 'B' : 'A',
sprint_hex_inrow(resultKey, 6)
@ -723,8 +723,8 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
}
// if (i%10 == 0) {
float bruteforce_per_second = (float)i + max_keys_chunk / (msclock() - start_time) * 1000.0;
PrintAndLogEx(INFO, "Chunk %6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt-i) / bruteforce_per_second);
float bruteforce_per_second = (float)(i + max_keys_chunk) / ((msclock() - start_time) / 1000.0);
PrintAndLogEx(INFO, "%6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second);
// }
}

View file

@ -199,7 +199,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) {
setLayout(layout);
// plot window title
QString pt = QString("[*]Plot [ %1 ]").arg((char*)gui_serial_port_name);
QString pt = QString("[*]Plot [ %1 ]").arg((char *)gui_serial_port_name);
setWindowTitle(pt);
// shows plot window on the screen.
@ -210,7 +210,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) {
controlWidget->resize(size().width(), 200);
// Olverlays / slider window title
QString ct = QString("[*]Slider [ %1 ]").arg((char*)gui_serial_port_name);
QString ct = QString("[*]Slider [ %1 ]").arg((char *)gui_serial_port_name);
controlWidget->setWindowTitle(ct);
controlWidget->show();

View file

@ -29,7 +29,7 @@ bool IsCryptoHelperPresent(void) {
uint8_t resp[20] = {0};
ExchangeAPDUSC(true, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len);
if (strstr("CryptoHelper", (char*)resp) == 0) {
if (strstr("CryptoHelper", (char *)resp) == 0) {
PrintAndLogEx(INFO, "Found smart card helper");
return true;
} else {
@ -56,11 +56,11 @@ static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) {
return false;
}
bool Decrypt(uint8_t *src, uint8_t *dest){
bool Decrypt(uint8_t *src, uint8_t *dest) {
return executeCrypto(CARD_INS_DECRYPT, src, dest);
}
bool Encrypt(uint8_t *src, uint8_t *dest){
bool Encrypt(uint8_t *src, uint8_t *dest) {
return executeCrypto(CARD_INS_ENCRYPT, src, dest);
}

View file

@ -206,7 +206,7 @@ void getHiLo(int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) {
*low = signalprop.low;
}
// prnt("getHiLo fuzzed: High %d | Low %d", *high, *low);
// prnt("getHiLo fuzzed: High %d | Low %d", *high, *low);
}
// by marshmellow

View file

@ -277,6 +277,29 @@ pm3 --> hf mf dump
pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-data.bin
```
Read Mifare Ultralight EV1
```
pm3 --> hf mfu info
```
Clone Mifare Ultralight EV1 Sequence
```
pm3 --> hf mfu dump k FFFFFFFF
pm3 --> script run dumptoemul-mfu -i hf-mfu-XXXX-dump.bin -o hf-mfu-XXXX-dump.eml
pm3 --> hf mfu eload u hf-mfu-XXXX-dump.eml
pm3 --> hf mfu sim t 7 u hf-mfu-XXXX-dump.eml
```
Bruteforce Mifare Classic card numbers from 11223344 to 11223346
```
pm3 --> script run hf_bruteforce -s 0x11223344 -e 0x11223346 -t 1000 -x mfc
```
Bruteforce Mifare Ultralight EV1 card numbers from 11223344556677 to 11223344556679
```
pm3 --> script run hf_bruteforce -s 0x11223344556677 -e 0x11223344556679 -t 1000 -x mfu
```
## Wiegand manipulation
^[Top](#top)

View file

@ -33,7 +33,7 @@ brew upgrade --fetch-HEAD proxmark3
## Flash the BOOTROM & FULLIMAGE
With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark3 as you plug it into a USB port. You can release the button, two of the four LEDs should stay on. You're un bootloader mode, ready for the next step. In case the two LEDs don't stay on when you're releasing the button, you've an old bootloader, start over and keep the button pressed during the whole flashing procedure.
With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark3 as you plug it into a USB port. You can release the button, two of the four LEDs should stay on. You're in bootloader mode, ready for the next step. In case the two LEDs don't stay on when you're releasing the button, you've an old bootloader, start over and keep the button pressed during the whole flashing procedure.
In principle, the helper script `pm3-flash-all` should auto-detect your port, so you can just try:

View file

@ -392,7 +392,8 @@ typedef struct {
#define CMD_LF_T55XX_WAKEUP 0x0224
#define CMD_LF_COTAG_READ 0x0225
#define CMD_LF_T55XX_SET_CONFIG 0x0226
#define CMD_LF_SAMPLING_GET_CONFIG 0x0227
#define CMD_LF_SAMPLING_PRINT_CONFIG 0x0227
#define CMD_LF_SAMPLING_GET_CONFIG 0x0228
#define CMD_LF_T55XX_CHK_PWDS 0x0230
#define CMD_LF_T55XX_DANGERRAW 0x0231
@ -504,6 +505,8 @@ typedef struct {
#define CMD_HF_MIFARE_SNIFF 0x0630
#define CMD_HF_MIFARE_MFKEY 0x0631
#define CMD_HF_MIFARE_PERSONALIZE_UID 0x0632
//ultralightC
#define CMD_HF_MIFAREUC_AUTH 0x0724
//0x0725 and 0x0726 no longer used

View file

@ -163,6 +163,10 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define MIFARE_EV1_PERSONAL_UID 0x40
#define MIFARE_EV1_SETMODE 0x43
#define MIFARE_EV1_UIDF0 0x00
#define MIFARE_EV1_UIDF1 0x40
#define MIFARE_EV1_UIDF2 0x20
#define MIFARE_EV1_UIDF3 0x60
#define MIFARE_ULC_WRITE 0xA2
#define MIFARE_ULC_COMP_WRITE 0xA0
@ -308,7 +312,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define PROTO_HITAG1 10
#define THINFILM 11
#define LTO 12
#define PROTO_HITAG2 13
#define PROTO_HITAG2 13
#define PROTO_HITAGS 14
//-- Picopass fuses
@ -595,7 +599,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define HITAG2_READ_PAGE 0x3 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
#define HITAG2_READ_PAGE_INVERTED 0x1 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
#define HITAG2_WRITE_PAGE 0x2 // page number in bits 5 to 3, page number
#define HITAG2_WRITE_PAGE 0x2 // page number in bits 5 to 3, page number
// HITAG S commands

View file

@ -22,4 +22,4 @@ $(OBJDIR)/libz.a:
tarbin: $(BINS)
$(info [=] TAR ../proxmark3-$(platform)-bin.tar)
$(Q)$(TAR) $(TARFLAGS) ../../proxmark3-$(platform)-bin.tar $(BINS:%=fpga_compress/%) $(WINBINS:%=fpga_compress/%)
$(Q)$(TAR) $(TARFLAGS) ../../proxmark3-$(platform)-bin.tar $(BINS:%=fpga_compress/%) $(WINBINS:%=fpga_compress/%)

View file

@ -142,11 +142,11 @@ typedef int rtccDate;
#ifndef __PIC32MX__
#define __PIC32MX__
#define __PIC32MX__
#endif
#define GetSystemClock() (80000000ul)
#define GetPeripheralClock() (GetSystemClock())
#define GetPeripheralClock() (GetSystemClock())
#define GetInstructionClock() (GetSystemClock())
//#define USE_SELF_POWER_SENSE_IO
@ -322,7 +322,7 @@ typedef int rtccDate;
// spi for SD card
#define SD_CARD_DET LATFbits.LATF0
#define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it
// (held LOW by default - cut solder bridge to GND to free pin if required)
// (held LOW by default - cut solder bridge to GND to free pin if required)
#define SPI_SD SPI_CHANNEL1
#define SPI_SD_BUFF SPI1BUF
#define SPI_SD_STAT SPI1STATbits

View file

@ -229,17 +229,16 @@ static uint32_t hitag2_crypt(uint64_t x);
((S >> (C - 3)) & 8) )
static uint32_t hitag2_crypt(uint64_t s)
{
static uint32_t hitag2_crypt(uint64_t s) {
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
uint32_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08;
bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex);
@ -253,13 +252,12 @@ static uint32_t hitag2_crypt(uint64_t s)
* uint32_t serialnum - 32 bit tag serial number
* uint32_t initvector - 32 bit random IV from reader, part of tag authentication
*/
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector)
{
void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) {
// init state, from serial number and lowest 16 bits of shared key
uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum;
// mix the initialisation vector and highest 32 bits of the shared key
initvector ^= (uint32_t) (sharedkey >> 16);
initvector ^= (uint32_t)(sharedkey >> 16);
// move 16 bits from (IV xor Shared Key) to top of uint64_t state
// these will be XORed in turn with output of the crypto function
@ -320,9 +318,9 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui
// optimise with one 64-bit intermediate
uint64_t temp = state ^ (state >> 1);
pstate->lfsr = state ^ (state >> 6) ^ (state >> 16)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
}
}
@ -338,8 +336,7 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui
* Hitag_State* pstate - in/out, internal cipher state after initialisation
* uint32_t steps - number of bits requested, (capped at 32)
*/
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps)
{
uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps) {
uint64_t state = pstate->shiftreg;
uint32_t result = 0;
uint64_t lfsr = pstate->lfsr;
@ -448,7 +445,7 @@ unsigned hitag2_verifytest()
const uint64_t key = rev64 (0x524B494D4E4FUL);
const uint32_t serial = rev32 (0x69574349);
const uint32_t initvec = rev32 (0x72456E65);
uint32_t i;
Hitag_State state;
@ -471,11 +468,10 @@ unsigned hitag2_verifytest()
#ifdef UNIT_TEST
int main(int argc, char* argv[])
{
int main(int argc, char *argv[]) {
unsigned pass = hitag2_verifytest();
printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL");
printf("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL");
if (pass) {
hitag2_benchtest(10000);

View file

@ -159,9 +159,9 @@ typedef struct {
uint64_t lfsr; // fast lfsr, used to make software faster
} Hitag_State;
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector);
void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector);
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps);
uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps);
unsigned int hitag2_benchtest_gen32();
unsigned int hitag2_benchtest(uint32_t count);

View file

@ -18,7 +18,7 @@
//
// If sorting fails with a 'bus error' then that is likely because your disk I/O can't keep up with
// the read/write demands of the multi-threaded sorting. In this case, reduce the number of sorting
// threads. This will most likely only be a problem with network disks; SATA should be okay;
// threads. This will most likely only be a problem with network disks; SATA should be okay;
// USB2/3 should keep up.
//
// These MUST be a power of 2 for the maths to work - you have been warned!
@ -53,8 +53,7 @@ uint64_t d2[48];
int nsteps2;
// create table entry
void create_table(struct table *t, int d1, int d2)
{
void create_table(struct table *t, int d1, int d2) {
if (!t) {
printf("create_table: t is NULL\n");
exit(1);
@ -83,8 +82,7 @@ void create_table(struct table *t, int d1, int d2)
// create all table entries
void create_tables(struct table *t)
{
void create_tables(struct table *t) {
int i, j;
if (!t) {
@ -92,8 +90,8 @@ void create_tables(struct table *t)
exit(1);
}
for (i=0; i<0x100; i++) {
for (j=0; j<0x100; j++) {
for (i = 0; i < 0x100; i++) {
for (j = 0; j < 0x100; j++) {
create_table(t + ((i * 0x100) + j), i, j);
}
}
@ -101,8 +99,7 @@ void create_tables(struct table *t)
// free the table memory
void free_tables(struct table *t)
{
void free_tables(struct table *t) {
int i;
struct table *ttmp;
@ -111,7 +108,7 @@ void free_tables(struct table *t)
exit(1);
}
for (i=0; i<0x10000; i++) {
for (i = 0; i < 0x10000; i++) {
ttmp = t + i;
free(ttmp->data);
}
@ -120,8 +117,7 @@ void free_tables(struct table *t)
// write (partial) table to file
void writetable(struct table *t1)
{
void writetable(struct table *t1) {
int fd;
if (debug) printf("writetable %s\n", t1->path);
@ -146,8 +142,7 @@ void writetable(struct table *t1)
// store value in table
void store(unsigned char *data)
{
void store(unsigned char *data) {
unsigned char d1, d2;
int offset;
struct table *t1;
@ -171,7 +166,7 @@ void store(unsigned char *data)
if (debug) printf("store, offset = %d, got lock\n", offset);
// store the entry
memcpy(t1->ptr, data+2, 10);
memcpy(t1->ptr, data + 2, 10);
if (debug) printf("store, offset = %d, copied data\n", offset);
@ -199,14 +194,13 @@ void store(unsigned char *data)
}
// writes the ks (keystream) and s (state)
void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg)
{
void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg) {
unsigned char buf[16];
// create buffer
writebuf(buf, ks1, 3);
writebuf(buf+3, ks2, 3);
writebuf(buf+6, shiftreg, 6);
writebuf(buf + 3, ks2, 3);
writebuf(buf + 6, shiftreg, 6);
// store buffer
store(buf);
@ -215,8 +209,7 @@ void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg)
// builds the di table for jumping
void builddi(int steps, int table)
{
void builddi(int steps, int table) {
uint64_t statemask;
int i;
Hitag_State mystate;
@ -237,7 +230,7 @@ void builddi(int steps, int table)
}
// build di states
for (i=0; i<48; i++) {
for (i = 0; i < 48; i++) {
mystate.shiftreg = statemask;
buildlfsr(&mystate);
hitag2_nstep(&mystate, steps);
@ -248,8 +241,7 @@ void builddi(int steps, int table)
}
// jump function - quickly jumps a load of steps
void jumpnsteps(Hitag_State *hstate, int table)
{
void jumpnsteps(Hitag_State *hstate, int table) {
uint64_t output = 0;
uint64_t bitmask;
int i;
@ -271,7 +263,7 @@ void jumpnsteps(Hitag_State *hstate, int table)
// if si is 1, di.si = di; if si is 0, di.si = 0
bitmask = 1;
for (i=0; i<48; i++) {
for (i = 0; i < 48; i++) {
if (hstate->shiftreg & bitmask) {
output = output ^ thisd[i];
}
@ -281,12 +273,11 @@ void jumpnsteps(Hitag_State *hstate, int table)
hstate->shiftreg = output;
buildlfsr(hstate);
}
}
// thread to build a part of the table
void *buildtable(void *d)
{
void *buildtable(void *d) {
Hitag_State hstate;
Hitag_State hstate2;
unsigned long i;
@ -301,7 +292,7 @@ void *buildtable(void *d)
buildlfsr(&hstate);
/* jump to offset using jump table 2 (2048) */
for (i=0; i<index; i++) {
for (i = 0; i < index; i++) {
jumpnsteps(&hstate, 2);
}
@ -319,7 +310,7 @@ void *buildtable(void *d)
}
/* make the entries */
for (i=0; i<maxentries; i++) {
for (i = 0; i < maxentries; i++) {
// copy the current state
hstate2.shiftreg = hstate.shiftreg;
@ -343,8 +334,7 @@ void *buildtable(void *d)
// make 'table/' (unsorted) and 'sorted/' dir structures
void makedirs()
{
void makedirs() {
char path[32];
int i;
@ -357,7 +347,7 @@ void makedirs()
exit(1);
}
for (i=0; i<0x100; i++) {
for (i = 0; i < 0x100; i++) {
sprintf(path, "table/%02x", i);
if (mkdir(path, 0755)) {
printf("cannot make dir %s\n", path);
@ -371,16 +361,14 @@ void makedirs()
}
}
static int datacmp(const void *p1, const void *p2, void *dummy)
{
static int datacmp(const void *p1, const void *p2, void *dummy) {
unsigned char *d1 = (unsigned char *)p1;
unsigned char *d2 = (unsigned char *)p2;
return memcmp(d1, d2, DATASIZE);
}
void *sorttable(void *d)
{
void *sorttable(void *d) {
int i, j;
int fdin;
int fdout;
@ -401,9 +389,9 @@ void *sorttable(void *d)
}
// loop over our first byte values
for (i=(index * space); i<((index + 1) * space); i++) {
for (i = (index * space); i < ((index + 1) * space); i++) {
// loop over all second byte values
for (j=0; j<0x100; j++) {
for (j = 0; j < 0x100; j++) {
printf("sorttable: processing bytes 0x%02x/0x%02x\n", i, j);
@ -464,8 +452,7 @@ void *sorttable(void *d)
return NULL;
}
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
pthread_t threads[NUM_BUILD_THREADS];
void *status;
long i;
@ -493,7 +480,7 @@ int main(int argc, char *argv[])
builddi(2048, 2);
// start the threads
for (i=0; i<NUM_BUILD_THREADS; i++) {
for (i = 0; i < NUM_BUILD_THREADS; i++) {
ret = pthread_create(&(threads[i]), NULL, buildtable, (void *)(i));
if (ret) {
printf("cannot start buildtable thread %ld\n", i);
@ -504,7 +491,7 @@ int main(int argc, char *argv[])
if (debug) printf("main, started buildtable threads\n");
// wait for threads to finish
for (i=0; i<NUM_BUILD_THREADS; i++) {
for (i = 0; i < NUM_BUILD_THREADS; i++) {
ret = pthread_join(threads[i], &status);
if (ret) {
printf("cannot join buildtable thread %ld\n", i);
@ -514,7 +501,7 @@ int main(int argc, char *argv[])
}
// write all remaining files
for (i=0; i<0x10000; i++) {
for (i = 0; i < 0x10000; i++) {
t1 = t + i;
if (t1->ptr > t1->data) {
writetable(t1);
@ -531,7 +518,7 @@ int main(int argc, char *argv[])
// start the threads
for (i=0; i<NUM_SORT_THREADS; i++) {
for (i = 0; i < NUM_SORT_THREADS; i++) {
ret = pthread_create(&(threads[i]), NULL, sorttable, (void *)(i));
if (ret) {
printf("cannot start sorttable thread %ld\n", i);
@ -542,7 +529,7 @@ int main(int argc, char *argv[])
if (debug) printf("main, started sorttable threads\n");
// wait for threads to finish
for (i=0; i<NUM_SORT_THREADS; i++) {
for (i = 0; i < NUM_SORT_THREADS; i++) {
ret = pthread_join(threads[i], &status);
if (ret) {
printf("cannot join sorttable thread %ld\n", i);

View file

@ -6,8 +6,7 @@
#include "ht2crack2utils.h"
int makerandom(char *hex, unsigned int len, int fd)
{
int makerandom(char *hex, unsigned int len, int fd) {
unsigned char raw[32];
int i;
@ -26,7 +25,7 @@ int makerandom(char *hex, unsigned int len, int fd)
exit(1);
}
for (i=0; i<len; i++) {
for (i = 0; i < len; i++) {
sprintf(hex + (2 * i), "%02X", raw[i]);
}
@ -34,8 +33,7 @@ int makerandom(char *hex, unsigned int len, int fd)
}
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
Hitag_State hstate;
char key[32];
char uid[32];
@ -64,7 +62,7 @@ int main(int argc, char *argv[])
}
for (i=0; i<numtests; i++) {
for (i = 0; i < numtests; i++) {
makerandom(key, 6, urandomfd);
makerandom(uid, 4, urandomfd);
@ -84,7 +82,7 @@ int main(int argc, char *argv[])
hitag2_nstep(&hstate, 64);
for (j=0; j<64; j++) {
for (j = 0; j < 64; j++) {
fprintf(fp, "%08X\n", hitag2_nstep(&hstate, 32));
}

View file

@ -17,16 +17,14 @@ struct rngdata {
static int datacmp(const void *p1, const void *p2)
{
static int datacmp(const void *p1, const void *p2) {
unsigned char *d1 = (unsigned char *)p1;
unsigned char *d2 = (unsigned char *)p2;
return memcmp(d1, d2, DATASIZE - 6);
}
int loadrngdata(struct rngdata *r, char *file)
{
int loadrngdata(struct rngdata *r, char *file) {
int fd;
int i, j;
int nibble;
@ -72,7 +70,7 @@ int loadrngdata(struct rngdata *r, char *file)
j = 0;
nibble = 0;
for (i=0; (i<filestat.st_size) && (j < r->len); i++) {
for (i = 0; (i < filestat.st_size) && (j < r->len); i++) {
if ((data[i] != 0x0a) && (data[i] != 0x0d) && (data[i] != 0x20)) {
if (!nibble) {
r->data[j] = hex2bin(data[i]) << 4;
@ -93,8 +91,7 @@ int loadrngdata(struct rngdata *r, char *file)
return 1;
}
int makecand(unsigned char *c, struct rngdata *r, int bitoffset)
{
int makecand(unsigned char *c, struct rngdata *r, int bitoffset) {
int bytenum;
int bitnum;
int i;
@ -107,7 +104,7 @@ int makecand(unsigned char *c, struct rngdata *r, int bitoffset)
bytenum = bitoffset / 8;
bitnum = bitoffset % 8;
for (i=0; i<6; i++) {
for (i = 0; i < 6; i++) {
if (!bitnum) {
c[i] = r->data[bytenum + i];
} else {
@ -120,8 +117,7 @@ int makecand(unsigned char *c, struct rngdata *r, int bitoffset)
// test the candidate against the next or previous rng data
int testcand(unsigned char *f, unsigned char *rt, int fwd)
{
int testcand(unsigned char *f, unsigned char *rt, int fwd) {
Hitag_State hstate;
int i;
uint32_t ks1;
@ -130,8 +126,8 @@ int testcand(unsigned char *f, unsigned char *rt, int fwd)
// build the prng state at the candidate
hstate.shiftreg = 0;
for (i=0; i<6; i++) {
hstate.shiftreg = (hstate.shiftreg << 8) | f[i+4];
for (i = 0; i < 6; i++) {
hstate.shiftreg = (hstate.shiftreg << 8) | f[i + 4];
}
buildlfsr(&hstate);
@ -149,7 +145,7 @@ int testcand(unsigned char *f, unsigned char *rt, int fwd)
ks2 = hitag2_nstep(&hstate, 24);
writebuf(buf, ks1, 3);
writebuf(buf+3, ks2, 3);
writebuf(buf + 3, ks2, 3);
// compare them
if (!memcmp(buf, rt, 6)) {
@ -159,8 +155,7 @@ int testcand(unsigned char *f, unsigned char *rt, int fwd)
}
}
int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, unsigned char *s)
{
int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, unsigned char *s) {
int fd;
struct stat filestat;
char file[64];
@ -193,7 +188,7 @@ int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, u
exit(1);
}
memcpy(item, c+2, 4);
memcpy(item, c + 2, 4);
found = (unsigned char *)bsearch(item, data, filestat.st_size / DATASIZE, DATASIZE, datacmp);
@ -209,13 +204,13 @@ int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, u
while (((found - data) <= (filestat.st_size - DATASIZE)) && (!memcmp(found, item, 4))) {
if (testcand(found, rt, fwd)) {
memcpy(m, c, 2);
memcpy(m+2, found, 4);
memcpy(s, found+4, 6);
memcpy(m + 2, found, 4);
memcpy(s, found + 4, 6);
munmap(data, filestat.st_size);
close(fd);
return 1;
}
}
found = found + DATASIZE;
}
@ -228,8 +223,7 @@ int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, u
}
int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstate, int *bitoffset)
{
int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstate, int *bitoffset) {
int i;
int bitlen;
unsigned char cand[6];
@ -243,7 +237,7 @@ int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstat
bitlen = r->len * 8;
for (i=0; i<=bitlen - 48; i++) {
for (i = 0; i <= bitlen - 48; i++) {
// print progress
if ((i % 100) == 0) {
printf("searching on bit %d\n", i);
@ -283,8 +277,7 @@ int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstat
void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset)
{
void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset) {
int i;
if (!s) {
@ -294,7 +287,7 @@ void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset)
// build prng at recovered offset
hstate->shiftreg = 0;
for (i=0; i<6; i++) {
for (i = 0; i < 6; i++) {
hstate->shiftreg = (hstate->shiftreg << 8) | s[i];
}
@ -313,8 +306,7 @@ void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset)
}
uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr)
{
uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) {
uint64_t key;
uint64_t keyupper;
uint32_t uid;
@ -333,7 +325,7 @@ uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr)
uidtmp = uid;
// rollback and extract bits b
for (i=0; i<32; i++) {
for (i = 0; i < 32; i++) {
hstate->shiftreg = ((hstate->shiftreg) << 1) | ((uidtmp >> 31) & 0x1);
uidtmp = uidtmp << 1;
b = (b << 1) | fnf(hstate->shiftreg);
@ -364,8 +356,7 @@ uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr)
}
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
Hitag_State hstate;
struct rngdata rng;
int bitoffset = 0;
@ -420,7 +411,7 @@ int main(int argc, char *argv[])
printf("\n");
printf("KEY:\t\t");
for (i=0; i<6; i++) {
for (i = 0; i < 6; i++) {
printf("%02X", (int)(key & 0xff));
key = key >> 8;
}

View file

@ -1,13 +1,11 @@
#include "ht2crack2utils.h"
// writes a value into a buffer as a series of bytes
void writebuf(unsigned char *buf, uint64_t val, unsigned int len)
{
void writebuf(unsigned char *buf, uint64_t val, unsigned int len) {
int i;
char c;
for (i=len-1; i>=0; i--)
{
for (i = len - 1; i >= 0; i--) {
c = val & 0xff;
buf[i] = c;
val = val >> 8;
@ -17,18 +15,17 @@ void writebuf(unsigned char *buf, uint64_t val, unsigned int len)
/* simple hexdump for testing purposes */
void shexdump(unsigned char *data, int data_len)
{
void shexdump(unsigned char *data, int data_len) {
int i;
if (!data || (data_len <= 0)) {
printf("shexdump: invalid parameters\n");
return;
}
printf("Hexdump from %p:\n", data);
for (i=0; i<data_len; i++) {
for (i = 0; i < data_len; i++) {
if ((i % HEX_PER_ROW) == 0) {
printf("\n0x%04x: ", i);
}
@ -39,8 +36,7 @@ void shexdump(unsigned char *data, int data_len)
void printbin(unsigned char *c)
{
void printbin(unsigned char *c) {
int i, j;
unsigned char x;
@ -49,9 +45,9 @@ void printbin(unsigned char *c)
return;
}
for (i=0; i<6; i++) {
for (i = 0; i < 6; i++) {
x = c[i];
for (j=0; j<8; j++) {
for (j = 0; j < 8; j++) {
printf("%d", (x & 0x80) >> 7);
x = x << 1;
}
@ -60,14 +56,13 @@ void printbin(unsigned char *c)
}
void printbin2(uint64_t val, unsigned int size)
{
void printbin2(uint64_t val, unsigned int size) {
int i;
uint64_t mask = 1;
mask = mask << (size - 1);
for (i=0; i<size; i++) {
for (i = 0; i < size; i++) {
if (val & mask) {
printf("1");
} else {
@ -78,8 +73,7 @@ void printbin2(uint64_t val, unsigned int size)
}
void printstate(Hitag_State *hstate)
{
void printstate(Hitag_State *hstate) {
printf("shiftreg =\t");
printbin2(hstate->shiftreg, 48);
printf("\n");
@ -89,8 +83,7 @@ void printstate(Hitag_State *hstate)
// convert hex char to binary
unsigned char hex2bin(unsigned char c)
{
unsigned char hex2bin(unsigned char c) {
if ((c >= '0') && (c <= '9')) {
return (c - '0');
} else if ((c >= 'a') && (c <= 'f')) {
@ -103,8 +96,7 @@ unsigned char hex2bin(unsigned char c)
}
// return a single bit from a value
int bitn(uint64_t x, int bit)
{
int bitn(uint64_t x, int bit) {
uint64_t bitmask = 1;
bitmask = bitmask << bit;
@ -118,20 +110,18 @@ int bitn(uint64_t x, int bit)
// the sub-function R that rollback depends upon
int fnR(uint64_t x)
{
int fnR(uint64_t x) {
// renumbered bits because my state is 0-47, not 1-48
return (bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^ bitn(x, 6) ^ bitn(x, 7) ^
bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^
bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47));
bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^
bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47));
}
// the rollback function that lets us go backwards in time
void rollback(Hitag_State *hstate, unsigned int steps)
{
void rollback(Hitag_State *hstate, unsigned int steps) {
int i;
for (i=0; i<steps; i++) {
for (i = 0; i < steps; i++) {
hstate->shiftreg = ((hstate->shiftreg << 1) & 0xffffffffffff) | fnR(hstate->shiftreg);
}
@ -139,24 +129,20 @@ void rollback(Hitag_State *hstate, unsigned int steps)
// the three filter sub-functions that feed fnf
int fa(unsigned int i)
{
int fa(unsigned int i) {
return bitn(0x2C79, i);
}
int fb(unsigned int i)
{
int fb(unsigned int i) {
return bitn(0x6671, i);
}
int fc(unsigned int i)
{
int fc(unsigned int i) {
return bitn(0x7907287B, i);
}
// the filter function that generates a bit of output from the prng state
int fnf(uint64_t s)
{
int fnf(uint64_t s) {
unsigned int x1, x2, x3, x4, x5, x6;
x1 = (bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3);
@ -171,16 +157,15 @@ int fnf(uint64_t s)
}
// builds the lfsr for the prng (quick calcs for hitag2_nstep())
void buildlfsr(Hitag_State *hstate)
{
void buildlfsr(Hitag_State *hstate) {
uint64_t state = hstate->shiftreg;
uint64_t temp;
temp = state ^ (state >> 1);
hstate->lfsr = state ^ (state >> 6) ^ (state >> 16)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
}

View file

@ -336,7 +336,7 @@ extern rtccDate RTC_date; // date structure
#define TAG_TYPE_AWID_26 17
#define TAG_TYPE_EM4X05 18
#define TAG_TYPE_TAMAGOTCHI 19
#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram
#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram
// various

View file

@ -182,7 +182,7 @@ unsigned char getbit(unsigned char byte, unsigned char bit);
void bytestohex(unsigned char *target, unsigned char *source, unsigned int length);
unsigned int manchester_encode(unsigned char *target, unsigned char *source, unsigned int length);
unsigned int manchester_decode(unsigned char *target, unsigned char *source, unsigned int length);
char * strip_newline(char *buff);
char *strip_newline(char *buff);
BOOL command_ack(BOOL data);
BOOL command_nack(BYTE *reason);
BOOL command_unknown(void);

View file

@ -142,19 +142,17 @@ rtccTime RTC_time; // time structure
rtccDate RTC_date; // date structure
// convert byte-reversed 8 digit hex to unsigned long
unsigned long hexreversetoulong(BYTE *hex)
{
unsigned long ret= 0L;
unsigned long hexreversetoulong(BYTE *hex) {
unsigned long ret = 0L;
unsigned int x;
BYTE i;
if(strlen(hex) != 8)
if (strlen(hex) != 8)
return 0L;
for(i= 0 ; i < 4 ; ++i)
{
if(sscanf(hex, "%2X", &x) != 1)
return 0L;
for (i = 0 ; i < 4 ; ++i) {
if (sscanf(hex, "%2X", &x) != 1)
return 0L;
ret += ((unsigned long) x) << i * 8;
hex += 2;
}
@ -162,18 +160,17 @@ unsigned long hexreversetoulong(BYTE *hex)
}
// convert byte-reversed 12 digit hex to unsigned long
unsigned long long hexreversetoulonglong(BYTE *hex)
{
unsigned long long ret= 0LL;
unsigned long long hexreversetoulonglong(BYTE *hex) {
unsigned long long ret = 0LL;
BYTE tmp[9];
// this may seem an odd way to do it, but weird compiler issues were
// this may seem an odd way to do it, but weird compiler issues were
// breaking direct conversion!
tmp[8]= '\0';
tmp[8] = '\0';
memset(tmp + 4, '0', 4);
memcpy(tmp, hex + 8, 4);
ret= hexreversetoulong(tmp);
ret = hexreversetoulong(tmp);
ret <<= 32;
memcpy(tmp, hex, 8);
ret += hexreversetoulong(tmp);

View file

@ -142,11 +142,11 @@ typedef int rtccDate;
#ifndef __PIC32MX__
#define __PIC32MX__
#define __PIC32MX__
#endif
#define GetSystemClock() (80000000ul)
#define GetPeripheralClock() (GetSystemClock())
#define GetPeripheralClock() (GetSystemClock())
#define GetInstructionClock() (GetSystemClock())
//#define USE_SELF_POWER_SENSE_IO
@ -322,7 +322,7 @@ typedef int rtccDate;
// spi for SD card
#define SD_CARD_DET LATFbits.LATF0
#define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it
// (held LOW by default - cut solder bridge to GND to free pin if required)
// (held LOW by default - cut solder bridge to GND to free pin if required)
#define SPI_SD SPI_CHANNEL1
#define SPI_SD_BUFF SPI1BUF
#define SPI_SD_STAT SPI1STATbits

View file

@ -229,17 +229,16 @@ static uint32_t hitag2_crypt(uint64_t x);
((S >> (C - 3)) & 8) )
static uint32_t hitag2_crypt(uint64_t s)
{
static uint32_t hitag2_crypt(uint64_t s) {
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
uint32_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08;
bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex);
@ -253,13 +252,12 @@ static uint32_t hitag2_crypt(uint64_t s)
* uint32_t serialnum - 32 bit tag serial number
* uint32_t initvector - 32 bit random IV from reader, part of tag authentication
*/
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector)
{
void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) {
// init state, from serial number and lowest 16 bits of shared key
uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum;
// mix the initialisation vector and highest 32 bits of the shared key
initvector ^= (uint32_t) (sharedkey >> 16);
initvector ^= (uint32_t)(sharedkey >> 16);
// move 16 bits from (IV xor Shared Key) to top of uint64_t state
// these will be XORed in turn with output of the crypto function
@ -320,9 +318,9 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui
// optimise with one 64-bit intermediate
uint64_t temp = state ^ (state >> 1);
pstate->lfsr = state ^ (state >> 6) ^ (state >> 16)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
}
}
@ -338,8 +336,7 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui
* Hitag_State* pstate - in/out, internal cipher state after initialisation
* uint32_t steps - number of bits requested, (capped at 32)
*/
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps)
{
uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps) {
uint64_t state = pstate->shiftreg;
uint32_t result = 0;
uint64_t lfsr = pstate->lfsr;
@ -446,7 +443,7 @@ unsigned hitag2_verifytest()
const uint64_t key = rev64 (0x524B494D4E4FUL);
const uint32_t serial = rev32 (0x69574349);
const uint32_t initvec = rev32 (0x72456E65);
uint32_t i;
Hitag_State state;
@ -469,11 +466,10 @@ unsigned hitag2_verifytest()
#ifdef UNIT_TEST
int main(int argc, char* argv[])
{
int main(int argc, char *argv[]) {
unsigned pass = hitag2_verifytest();
printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL");
printf("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL");
if (pass) {
hitag2_benchtest(10000);

View file

@ -159,9 +159,9 @@ typedef struct {
uint64_t lfsr; // fast lfsr, used to make software faster
} Hitag_State;
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector);
void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector);
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps);
uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps);
unsigned int hitag2_benchtest_gen32();
unsigned int hitag2_benchtest(uint32_t count);

View file

@ -34,11 +34,10 @@ struct threaddata {
uint64_t klowerrange;
};
void printbin(uint64_t val)
{
void printbin(uint64_t val) {
int i;
for (i=0; i<64; i++) {
for (i = 0; i < 64; i++) {
if (val & 0x8000000000000000) {
printf("1");
} else {
@ -48,8 +47,7 @@ void printbin(uint64_t val)
}
}
void printstate(Hitag_State *hstate)
{
void printstate(Hitag_State *hstate) {
printf("shiftreg =\t");
printbin(hstate->shiftreg);
printf("\n");
@ -70,17 +68,16 @@ void printstate(Hitag_State *hstate)
((S >> (C - 3)) & 8) )
static uint32_t hitag2_crypt(uint64_t s)
{
static uint32_t hitag2_crypt(uint64_t s) {
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
uint32_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08;
bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
return (ht2_function5c >> bitindex) & 1;
@ -89,17 +86,16 @@ static uint32_t hitag2_crypt(uint64_t s)
// this function is a modification of the filter function f, based heavily
// on the hitag2_crypt function in Rfidler
int fnP(uint64_t klowery)
{
int fnP(uint64_t klowery) {
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function4p = 0xAE83; // 1010 1110 1000 0011
uint32_t i;
i = (ht2_function4a >> pickbits2_2 (klowery, 2, 5)) & 1;
i |= ((ht2_function4b << 1) >> pickbits1_1_2 (klowery, 8, 12, 14)) & 0x02;
i |= ((ht2_function4b << 2) >> pickbits1x4 (klowery, 17, 21, 23, 26)) & 0x04;
i |= ((ht2_function4b << 3) >> pickbits2_1_1 (klowery, 28, 31, 33)) & 0x08;
i = (ht2_function4a >> pickbits2_2(klowery, 2, 5)) & 1;
i |= ((ht2_function4b << 1) >> pickbits1_1_2(klowery, 8, 12, 14)) & 0x02;
i |= ((ht2_function4b << 2) >> pickbits1x4(klowery, 17, 21, 23, 26)) & 0x04;
i |= ((ht2_function4b << 3) >> pickbits2_1_1(klowery, 28, 31, 33)) & 0x08;
// modified to use reference implementation approach
// orig fc table is 0x7907287B = 0111 1001 0000 0111 0010 1000 0111 1011
@ -109,8 +105,7 @@ int fnP(uint64_t klowery)
}
// comparison function for sorting/searching Tklower entries
int Tk_cmp(const void *v1, const void *v2)
{
int Tk_cmp(const void *v1, const void *v2) {
const struct Tklower *Tk1 = (struct Tklower *)v1;
const struct Tklower *Tk2 = (struct Tklower *)v2;
@ -148,8 +143,7 @@ int is_kmiddle_badguess(uint64_t z, struct Tklower *Tk, int max, int aR0) {
}
// function to test if a partial key is valid
int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR)
{
int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR) {
uint64_t kupper;
uint64_t key;
Hitag_State hstate;
@ -162,7 +156,7 @@ int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR
normaR = ((revaR >> 24) | ((revaR >> 8) & 0xff00) | ((revaR << 8) & 0xff0000) | (revaR << 24));
// search for remaining 14 bits
for (kupper=0; kupper < 0x3fff; kupper++) {
for (kupper = 0; kupper < 0x3fff; kupper++) {
key = (kupper << 34) | pkey;
hitag2_init(&hstate, key, uid, nR);
b = hitag2_nstep(&hstate, 32);
@ -170,7 +164,7 @@ int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR
*out = key;
return 1;
}
}
}
return 0;
}
@ -205,8 +199,7 @@ int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR
// effectively work out candidates for the lower 34 bits of the key.
void *crack(void *d)
{
void *crack(void *d) {
struct threaddata *data = (struct threaddata *)d;
uint64_t uid;
struct nRaR *TnRaR;
@ -249,11 +242,11 @@ void *crack(void *d)
}
// find keys
for (klower=data->klowerstart; klower < (data->klowerstart + data->klowerrange); klower++) {
for (klower = data->klowerstart; klower < (data->klowerstart + data->klowerrange); klower++) {
printf("trying klower = 0x%05lx\n", klower);
// build table
count = 0;
for (y=0; y<0x40000; y++) {
for (y = 0; y < 0x40000; y++) {
// create klowery
klowery = (y << 16) | klower;
// check for cases where right most bit of fc doesn't matter
@ -268,9 +261,9 @@ void *crack(void *d)
// insert y into shiftreg and extract keystream, reversed order
b = 0;
ytmp = y;
for (j=0; j<2; j++) {
for (j = 0; j < 2; j++) {
hstate.shiftreg = hstate.shiftreg | ((ytmp & 0xffff) << 48);
for (i=0; i<16; i++) {
for (i = 0; i < 16; i++) {
hstate.shiftreg = hstate.shiftreg >> 1;
bit = hitag2_crypt(hstate.shiftreg);
b = (b >> 1) | (bit << 31);
@ -295,11 +288,11 @@ void *crack(void *d)
qsort(Tk, count, sizeof(struct Tklower), Tk_cmp);
// look for matches
for (kmiddle=0; kmiddle<0x40000; kmiddle++) {
for (kmiddle = 0; kmiddle < 0x40000; kmiddle++) {
// loop over nRaR pairs
badguess = 0;
found = 0;
for (i=0; (i<numnrar) && (!badguess); i++) {
for (i = 0; (i < numnrar) && (!badguess); i++) {
z = kmiddle ^ (TnRaR[i].nR & 0x3ffff);
ret = is_kmiddle_badguess(z, Tk, count, TnRaR[i].aR & 0x1);
if (ret == 1) {
@ -314,7 +307,7 @@ void *crack(void *d)
printf("possible partial key found: 0x%012lx\n", ((uint64_t)kmiddle << 16) | klower);
if (testkey(&foundkey, uid, (kmiddle << 16 | klower), TnRaR[0].nR, TnRaR[0].aR) &&
testkey(&foundkey, uid, (kmiddle << 16 | klower), TnRaR[1].nR, TnRaR[1].aR)) {
testkey(&foundkey, uid, (kmiddle << 16 | klower), TnRaR[1].nR, TnRaR[1].aR)) {
// normalise foundkey
revkey = rev64(foundkey);
foundkey = ((revkey >> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000);
@ -331,8 +324,7 @@ void *crack(void *d)
return NULL;
}
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
FILE *fp;
int i;
pthread_t threads[NUM_THREADS];
@ -401,8 +393,8 @@ int main(int argc, char *argv[])
}
*buft2 = 0x00;
if (!strncmp(buf, "0x", 2)) {
TnRaR[numnrar].nR = rev32(hexreversetoulong(buf+2));
TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1+2));
TnRaR[numnrar].nR = rev32(hexreversetoulong(buf + 2));
TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1 + 2));
} else {
TnRaR[numnrar].nR = rev32(hexreversetoulong(buf));
TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1));
@ -423,7 +415,7 @@ int main(int argc, char *argv[])
exit(1);
}
for (i=0; i<NUM_THREADS; i++) {
for (i = 0; i < NUM_THREADS; i++) {
tdata[i].uid = uid;
tdata[i].TnRaR = TnRaR;
tdata[i].numnrar = numnrar;
@ -437,7 +429,7 @@ int main(int argc, char *argv[])
crack(tdata);
} else {
// run full threaded mode
for (i=0; i<NUM_THREADS; i++) {
for (i = 0; i < NUM_THREADS; i++) {
if (pthread_create(&(threads[i]), NULL, crack, (void *)(tdata + i))) {
printf("cannot start thread %d\n", i);
exit(1);
@ -446,7 +438,7 @@ int main(int argc, char *argv[])
}
// wait for threads to finish
for (i=0; i<NUM_THREADS; i++) {
for (i = 0; i < NUM_THREADS; i++) {
if (pthread_join(threads[i], &status)) {
printf("cannot join thread %d\n", i);
exit(1);

View file

@ -9,8 +9,7 @@
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
Hitag_State hstate;
FILE *fp;
char *line = NULL;
@ -51,7 +50,7 @@ int main(int argc, char *argv[])
ar = strchr(line, ' ');
*ar = 0x00;
ar++;
ar[strlen(ar)-1] = 0x00;
ar[strlen(ar) - 1] = 0x00;
if (!strncmp(line, "0x", 2)) {
nr = line + 2;
} else {

View file

@ -336,7 +336,7 @@ extern rtccDate RTC_date; // date structure
#define TAG_TYPE_AWID_26 17
#define TAG_TYPE_EM4X05 18
#define TAG_TYPE_TAMAGOTCHI 19
#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram
#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram
// various

View file

@ -142,19 +142,17 @@ rtccTime RTC_time; // time structure
rtccDate RTC_date; // date structure
// convert byte-reversed 8 digit hex to unsigned long
unsigned long hexreversetoulong(BYTE *hex)
{
unsigned long ret= 0L;
unsigned long hexreversetoulong(BYTE *hex) {
unsigned long ret = 0L;
unsigned int x;
BYTE i;
if(strlen(hex) != 8)
if (strlen(hex) != 8)
return 0L;
for(i= 0 ; i < 4 ; ++i)
{
if(sscanf(hex, "%2X", &x) != 1)
return 0L;
for (i = 0 ; i < 4 ; ++i) {
if (sscanf(hex, "%2X", &x) != 1)
return 0L;
ret += ((unsigned long) x) << i * 8;
hex += 2;
}
@ -162,18 +160,17 @@ unsigned long hexreversetoulong(BYTE *hex)
}
// convert byte-reversed 12 digit hex to unsigned long
unsigned long long hexreversetoulonglong(BYTE *hex)
{
unsigned long long ret= 0LL;
unsigned long long hexreversetoulonglong(BYTE *hex) {
unsigned long long ret = 0LL;
BYTE tmp[9];
// this may seem an odd way to do it, but weird compiler issues were
// this may seem an odd way to do it, but weird compiler issues were
// breaking direct conversion!
tmp[8]= '\0';
tmp[8] = '\0';
memset(tmp + 4, '0', 4);
memcpy(tmp, hex + 8, 4);
ret= hexreversetoulong(tmp);
ret = hexreversetoulong(tmp);
ret <<= 32;
memcpy(tmp, hex, 8);
ret += hexreversetoulong(tmp);

View file

@ -142,11 +142,11 @@ typedef int rtccDate;
#ifndef __PIC32MX__
#define __PIC32MX__
#define __PIC32MX__
#endif
#define GetSystemClock() (80000000ul)
#define GetPeripheralClock() (GetSystemClock())
#define GetPeripheralClock() (GetSystemClock())
#define GetInstructionClock() (GetSystemClock())
//#define USE_SELF_POWER_SENSE_IO
@ -322,7 +322,7 @@ typedef int rtccDate;
// spi for SD card
#define SD_CARD_DET LATFbits.LATF0
#define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it
// (held LOW by default - cut solder bridge to GND to free pin if required)
// (held LOW by default - cut solder bridge to GND to free pin if required)
#define SPI_SD SPI_CHANNEL1
#define SPI_SD_BUFF SPI1BUF
#define SPI_SD_STAT SPI1STATbits

View file

@ -229,17 +229,16 @@ static uint32_t hitag2_crypt(uint64_t x);
((S >> (C - 3)) & 8) )
static uint32_t hitag2_crypt(uint64_t s)
{
static uint32_t hitag2_crypt(uint64_t s) {
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
uint32_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08;
bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex);
@ -253,13 +252,12 @@ static uint32_t hitag2_crypt(uint64_t s)
* uint32_t serialnum - 32 bit tag serial number
* uint32_t initvector - 32 bit random IV from reader, part of tag authentication
*/
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector)
{
void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) {
// init state, from serial number and lowest 16 bits of shared key
uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum;
// mix the initialisation vector and highest 32 bits of the shared key
initvector ^= (uint32_t) (sharedkey >> 16);
initvector ^= (uint32_t)(sharedkey >> 16);
// move 16 bits from (IV xor Shared Key) to top of uint64_t state
// these will be XORed in turn with output of the crypto function
@ -320,9 +318,9 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui
// optimise with one 64-bit intermediate
uint64_t temp = state ^ (state >> 1);
pstate->lfsr = state ^ (state >> 6) ^ (state >> 16)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
}
}
@ -338,8 +336,7 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui
* Hitag_State* pstate - in/out, internal cipher state after initialisation
* uint32_t steps - number of bits requested, (capped at 32)
*/
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps)
{
uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps) {
uint64_t state = pstate->shiftreg;
uint32_t result = 0;
uint64_t lfsr = pstate->lfsr;
@ -446,7 +443,7 @@ unsigned hitag2_verifytest()
const uint64_t key = rev64 (0x524B494D4E4FUL);
const uint32_t serial = rev32 (0x69574349);
const uint32_t initvec = rev32 (0x72456E65);
uint32_t i;
Hitag_State state;
@ -469,11 +466,10 @@ unsigned hitag2_verifytest()
#ifdef UNIT_TEST
int main(int argc, char* argv[])
{
int main(int argc, char *argv[]) {
unsigned pass = hitag2_verifytest();
printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL");
printf("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL");
if (pass) {
hitag2_benchtest(10000);

View file

@ -159,9 +159,9 @@ typedef struct {
uint64_t lfsr; // fast lfsr, used to make software faster
} Hitag_State;
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector);
void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector);
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps);
uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps);
unsigned int hitag2_benchtest_gen32();
unsigned int hitag2_benchtest(uint32_t count);

View file

@ -1,13 +1,11 @@
#include "ht2crack2utils.h"
// writes a value into a buffer as a series of bytes
void writebuf(unsigned char *buf, uint64_t val, unsigned int len)
{
void writebuf(unsigned char *buf, uint64_t val, unsigned int len) {
int i;
char c;
for (i=len-1; i>=0; i--)
{
for (i = len - 1; i >= 0; i--) {
c = val & 0xff;
buf[i] = c;
val = val >> 8;
@ -17,18 +15,17 @@ void writebuf(unsigned char *buf, uint64_t val, unsigned int len)
/* simple hexdump for testing purposes */
void shexdump(unsigned char *data, int data_len)
{
void shexdump(unsigned char *data, int data_len) {
int i;
if (!data || (data_len <= 0)) {
printf("shexdump: invalid parameters\n");
return;
}
printf("Hexdump from %p:\n", data);
for (i=0; i<data_len; i++) {
for (i = 0; i < data_len; i++) {
if ((i % HEX_PER_ROW) == 0) {
printf("\n0x%04x: ", i);
}
@ -39,8 +36,7 @@ void shexdump(unsigned char *data, int data_len)
void printbin(unsigned char *c)
{
void printbin(unsigned char *c) {
int i, j;
unsigned char x;
@ -49,9 +45,9 @@ void printbin(unsigned char *c)
return;
}
for (i=0; i<6; i++) {
for (i = 0; i < 6; i++) {
x = c[i];
for (j=0; j<8; j++) {
for (j = 0; j < 8; j++) {
printf("%d", (x & 0x80) >> 7);
x = x << 1;
}
@ -60,14 +56,13 @@ void printbin(unsigned char *c)
}
void printbin2(uint64_t val, unsigned int size)
{
void printbin2(uint64_t val, unsigned int size) {
int i;
uint64_t mask = 1;
mask = mask << (size - 1);
for (i=0; i<size; i++) {
for (i = 0; i < size; i++) {
if (val & mask) {
printf("1");
} else {
@ -78,8 +73,7 @@ void printbin2(uint64_t val, unsigned int size)
}
void printstate(Hitag_State *hstate)
{
void printstate(Hitag_State *hstate) {
printf("shiftreg =\t");
printbin2(hstate->shiftreg, 48);
printf("\n");
@ -89,8 +83,7 @@ void printstate(Hitag_State *hstate)
// convert hex char to binary
unsigned char hex2bin(unsigned char c)
{
unsigned char hex2bin(unsigned char c) {
if ((c >= '0') && (c <= '9')) {
return (c - '0');
} else if ((c >= 'a') && (c <= 'f')) {
@ -103,8 +96,7 @@ unsigned char hex2bin(unsigned char c)
}
// return a single bit from a value
int bitn(uint64_t x, int bit)
{
int bitn(uint64_t x, int bit) {
uint64_t bitmask = 1;
bitmask = bitmask << bit;
@ -118,20 +110,18 @@ int bitn(uint64_t x, int bit)
// the sub-function R that rollback depends upon
int fnR(uint64_t x)
{
int fnR(uint64_t x) {
// renumbered bits because my state is 0-47, not 1-48
return (bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^ bitn(x, 6) ^ bitn(x, 7) ^
bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^
bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47));
bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^
bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47));
}
// the rollback function that lets us go backwards in time
void rollback(Hitag_State *hstate, unsigned int steps)
{
void rollback(Hitag_State *hstate, unsigned int steps) {
int i;
for (i=0; i<steps; i++) {
for (i = 0; i < steps; i++) {
hstate->shiftreg = ((hstate->shiftreg << 1) & 0xffffffffffff) | fnR(hstate->shiftreg);
}
@ -139,24 +129,20 @@ void rollback(Hitag_State *hstate, unsigned int steps)
// the three filter sub-functions that feed fnf
int fa(unsigned int i)
{
int fa(unsigned int i) {
return bitn(0x2C79, i);
}
int fb(unsigned int i)
{
int fb(unsigned int i) {
return bitn(0x6671, i);
}
int fc(unsigned int i)
{
int fc(unsigned int i) {
return bitn(0x7907287B, i);
}
// the filter function that generates a bit of output from the prng state
int fnf(uint64_t s)
{
int fnf(uint64_t s) {
unsigned int x1, x2, x3, x4, x5, x6;
x1 = (bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3);
@ -171,16 +157,15 @@ int fnf(uint64_t s)
}
// builds the lfsr for the prng (quick calcs for hitag2_nstep())
void buildlfsr(Hitag_State *hstate)
{
void buildlfsr(Hitag_State *hstate) {
uint64_t state = hstate->shiftreg;
uint64_t temp;
temp = state ^ (state >> 1);
hstate->lfsr = state ^ (state >> 6) ^ (state >> 16)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
}

View file

@ -93,8 +93,7 @@ uint64_t uid;
int maxtablesize = 800000;
uint64_t supplied_testkey = 0;
void usage()
{
void usage() {
printf("ht2crack4 - K Sheldrake, based on the work of Garcia et al\n\n");
printf("Cracks a HiTag2 key using a small number (4 to 16) of encrypted\n");
printf("nonce and challenge response pairs, using a fast correlation\n");
@ -130,46 +129,44 @@ const uint64_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 011
* a known least-sig pattern. first index is num bits in known part, second is the
* bit pattern of the known part. */
double pfna[][8] = {
{0.50000, 0.50000, },
{0.50000, 0.50000, 0.50000, 0.50000, },
{0.50000, 0.00000, 0.50000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, },
{0.50000, 0.50000, },
{0.50000, 0.50000, 0.50000, 0.50000, },
{0.50000, 0.00000, 0.50000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, },
};
double pfnb[][8] = {
{0.62500, 0.37500, },
{0.50000, 0.75000, 0.75000, 0.00000, },
{0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 1.00000, 1.00000, 0.00000, },
{0.62500, 0.37500, },
{0.50000, 0.75000, 0.75000, 0.00000, },
{0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 1.00000, 1.00000, 0.00000, },
};
double pfnc[][16] = {
{0.50000, 0.50000, },
{0.62500, 0.62500, 0.37500, 0.37500, },
{0.75000, 0.50000, 0.25000, 0.75000, 0.50000, 0.75000, 0.50000, 0.00000, },
{1.00000, 1.00000, 0.50000, 0.50000, 0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 0.00000, 0.00000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, },
{0.50000, 0.50000, },
{0.62500, 0.62500, 0.37500, 0.37500, },
{0.75000, 0.50000, 0.25000, 0.75000, 0.50000, 0.75000, 0.50000, 0.00000, },
{1.00000, 1.00000, 0.50000, 0.50000, 0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 0.00000, 0.00000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, },
};
/* hitag2_crypt works on the post-shifted form of the lfsr; this is the ref in rfidler code */
static uint32_t hitag2_crypt(uint64_t s)
{
static uint32_t hitag2_crypt(uint64_t s) {
uint32_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08;
bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
return (ht2_function5c >> bitindex) & 1;
}
/* ht2crypt works on the pre-shifted form of the lfsr; this is the ref in the paper */
uint64_t ht2crypt(uint64_t s)
{
uint64_t ht2crypt(uint64_t s) {
uint64_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 2, 5)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 8, 12, 14)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 17, 21, 23, 26)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 28, 31, 33)) & 0x08;
bitindex = (ht2_function4a >> pickbits2_2(s, 2, 5)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 8, 12, 14)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 17, 21, 23, 26)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 28, 31, 33)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 34, 43, 46)) & 0x10;
return (ht2_function5c >> bitindex) & 1;
@ -177,11 +174,10 @@ uint64_t ht2crypt(uint64_t s)
/* fnL is the feedback function for the reference code */
uint64_t fnL(uint64_t x)
{
uint64_t fnL(uint64_t x) {
return (bitn(x, 0) ^ bitn(x, 2) ^ bitn(x, 3) ^ bitn(x, 6) ^ bitn(x, 7) ^ bitn(x, 8) ^
bitn(x, 16) ^ bitn(x, 22) ^ bitn(x, 23) ^ bitn(x, 26) ^ bitn(x, 30) ^ bitn(x, 41) ^
bitn(x, 42) ^ bitn(x, 43) ^ bitn(x, 46) ^ bitn(x, 47));
bitn(x, 16) ^ bitn(x, 22) ^ bitn(x, 23) ^ bitn(x, 26) ^ bitn(x, 30) ^ bitn(x, 41) ^
bitn(x, 42) ^ bitn(x, 43) ^ bitn(x, 46) ^ bitn(x, 47));
}
@ -189,18 +185,18 @@ uint64_t fnL(uint64_t x)
* the number of relevant bits.
* e.g. if there are 16 confirmed bits in a state, then packed_size[16] = 8 relevant bits.
* this is for pre-shifted lfsr */
unsigned int packed_size[] = { 0, 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
unsigned int packed_size[] = { 0, 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
8, 9, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 14, 14, 15,
15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 20, 20 };
15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 20, 20
};
/* f20 is the same as hitag2_crypt except it works on the packed version
* of the state where all 20 relevant bits are squashed together */
uint64_t f20(uint64_t y)
{
uint64_t f20(uint64_t y) {
uint64_t bitindex;
bitindex = (ht2_function4a >> (y & 0xf)) & 1;
bitindex = (ht2_function4a >> (y & 0xf)) & 1;
bitindex |= ((ht2_function4b << 1) >> ((y >> 4) & 0xf)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> ((y >> 8) & 0xf)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> ((y >> 12) & 0xf)) & 0x08;
@ -211,14 +207,13 @@ uint64_t f20(uint64_t y)
/* packstate packs the relevant bits from LFSR state into 20 bits for pre-shifted lfsr */
uint64_t packstate(uint64_t s)
{
uint64_t packstate(uint64_t s) {
uint64_t packed;
packed = pickbits2_2 (s, 2, 5);
packed |= (pickbits1_1_2 (s, 8, 12, 14) << 4);
packed |= (pickbits1x4 (s, 17, 21, 23, 26) << 8);
packed |= (pickbits2_1_1 (s, 28, 31, 33) << 12);
packed = pickbits2_2(s, 2, 5);
packed |= (pickbits1_1_2(s, 8, 12, 14) << 4);
packed |= (pickbits1x4(s, 17, 21, 23, 26) << 8);
packed |= (pickbits2_1_1(s, 28, 31, 33) << 12);
packed |= (pickbits1_2_1(s, 34, 43, 46) << 16);
return packed;
@ -226,8 +221,7 @@ uint64_t packstate(uint64_t s)
/* create_guess_table mallocs the tables */
void create_guess_table()
{
void create_guess_table() {
guesses = (struct guess *)malloc(sizeof(struct guess) * maxtablesize);
if (!guesses) {
printf("cannot malloc guess table\n");
@ -238,8 +232,7 @@ void create_guess_table()
/* init the guess table by reading in the encrypted nR,aR values and
* setting the first 2^16 key guesses */
void init_guess_table(char *filename, char *uidstr)
{
void init_guess_table(char *filename, char *uidstr) {
unsigned int i, j;
FILE *fp;
char *buf = NULL;
@ -289,8 +282,8 @@ void init_guess_table(char *filename, char *uidstr)
}
*buft2 = 0x00;
if (!strncmp(buf, "0x", 2)) {
nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf+2));
nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1+2)) ^ 0xffffffff;
nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf + 2));
nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1 + 2)) ^ 0xffffffff;
} else {
nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf));
nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1)) ^ 0xffffffff;
@ -303,12 +296,12 @@ void init_guess_table(char *filename, char *uidstr)
fprintf(stderr, "Loaded %d nRaR pairs\n", num_nRaR);
// set key and copy in enc_nR and ks values
// set key and copy in enc_nR and ks values
// set score to -1.0 to distinguish them from 0 scores
for (i=0; i<65536; i++) {
for (i = 0; i < 65536; i++) {
guesses[i].key = i;
guesses[i].score = -1.0;
for (j=0; j<num_nRaR; j++) {
for (j = 0; j < num_nRaR; j++) {
guesses[i].b0to31[j] = 0;
}
}
@ -320,8 +313,7 @@ void init_guess_table(char *filename, char *uidstr)
/* bit_score calculates the ratio of partial states that could generate
* the resulting bit b to all possible states
* size is the number of confirmed bits in the state */
double bit_score(uint64_t s, uint64_t size, uint64_t b)
{
double bit_score(uint64_t s, uint64_t size, uint64_t b) {
uint64_t packed;
uint64_t chopped;
unsigned int n;
@ -353,14 +345,14 @@ double bit_score(uint64_t s, uint64_t size, uint64_t b)
// incomplete first nibble
// get probability of getting a 1 from first nibble
// and by subtraction from 1, prob of getting a 0
nibprob1 = pfna[n-1][packed];
nibprob1 = pfna[n - 1][packed];
nibprob0 = 1.0 - nibprob1;
// calc fnc prob as sum of probs of nib 1 producing a 1 and 0
prob = (nibprob0 * pfnc[0][0]) + (nibprob1 * pfnc[0][1]);
} else if (n < 20) {
// calculate the fnc input first, then we'll fix it
fncinput = (ht2_function4a >> (packed & 0xf)) & 1;
fncinput = (ht2_function4a >> (packed & 0xf)) & 1;
fncinput |= ((ht2_function4b << 1) >> ((packed >> 4) & 0xf)) & 0x02;
fncinput |= ((ht2_function4b << 2) >> ((packed >> 8) & 0xf)) & 0x04;
fncinput |= ((ht2_function4b << 3) >> ((packed >> 12) & 0xf)) & 0x08;
@ -404,8 +396,7 @@ double bit_score(uint64_t s, uint64_t size, uint64_t b)
* bit_scores together until no bits remain. bit_scores are
* multiplied by the number of relevant bits in the scored state
* to give weight to more complete states. */
double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize)
{
double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize) {
double sc, sc2;
if ((size == 1) || (kssize == 1)) {
@ -436,8 +427,7 @@ double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize)
/* score_traces runs score for each encrypted nonce */
void score_traces(struct guess *g, unsigned int size)
{
void score_traces(struct guess *g, unsigned int size) {
uint64_t lfsr;
unsigned int i;
double sc;
@ -448,13 +438,13 @@ void score_traces(struct guess *g, unsigned int size)
return;
}
for (i=0; i<num_nRaR; i++) {
for (i = 0; i < num_nRaR; i++) {
// calc next b
// create lfsr - lower 32 bits is uid, upper 16 bits are lower 16 bits of key
// then shift by size - 16, insert upper key XOR enc_nonce XOR bitstream,
// and calc new bit b
lfsr = (uid >> (size - 16)) | ((g->key << (48 - size)) ^
((nonces[i].enc_nR ^ g->b0to31[i]) << (64 - size)));
((nonces[i].enc_nR ^ g->b0to31[i]) << (64 - size)));
g->b0to31[i] = g->b0to31[i] | (ht2crypt(lfsr) << (size - 16));
// create lfsr - lower 16 bits are lower 16 bits of key
@ -491,12 +481,11 @@ void score_all_traces(unsigned int size)
*/
/* score_some_traces runs score_traces for every key guess in a section of the table */
void *score_some_traces(void *data)
{
void *score_some_traces(void *data) {
unsigned int i;
struct thread_data *tdata = (struct thread_data *)data;
for (i=tdata->start; i<tdata->end; i++) {
for (i = tdata->start; i < tdata->end; i++) {
score_traces(&(guesses[i]), tdata->size);
}
@ -505,8 +494,7 @@ void *score_some_traces(void *data)
/* score_all_traces runs score_traces for every key guess in the table */
void score_all_traces(unsigned int size)
{
void score_all_traces(unsigned int size) {
pthread_t threads[NUM_THREADS];
void *status;
struct thread_data tdata[NUM_THREADS];
@ -516,9 +504,9 @@ void score_all_traces(unsigned int size)
chunk_size = num_guesses / NUM_THREADS;
// create thread data
for (i=0; i<NUM_THREADS; i++) {
for (i = 0; i < NUM_THREADS; i++) {
tdata[i].start = i * chunk_size;
tdata[i].end = (i+1) * chunk_size;
tdata[i].end = (i + 1) * chunk_size;
tdata[i].size = size;
}
@ -526,7 +514,7 @@ void score_all_traces(unsigned int size)
tdata[NUM_THREADS - 1].end = num_guesses;
// start the threads
for (i=0; i<NUM_THREADS; i++) {
for (i = 0; i < NUM_THREADS; i++) {
if (pthread_create(&(threads[i]), NULL, score_some_traces, (void *)(tdata + i))) {
printf("cannot start thread %d\n", i);
exit(1);
@ -534,7 +522,7 @@ void score_all_traces(unsigned int size)
}
// wait for threads to end
for (i=0; i<NUM_THREADS; i++) {
for (i = 0; i < NUM_THREADS; i++) {
if (pthread_join(threads[i], &status)) {
printf("cannot join thread %d\n", i);
exit(1);
@ -547,8 +535,7 @@ void score_all_traces(unsigned int size)
/* cmp_guess is the comparison function for qsorting the guess table */
int cmp_guess(const void *a, const void *b)
{
int cmp_guess(const void *a, const void *b) {
struct guess *a1 = (struct guess *)a;
struct guess *b1 = (struct guess *)b;
@ -565,15 +552,14 @@ int cmp_guess(const void *a, const void *b)
/* expand all guesses in first half of (sorted) table by
* copying them into the second half and extending the copied
* ones with an extra 1, leaving the first half with an extra 0 */
void expand_guesses(unsigned int halfsize, unsigned int size)
{
void expand_guesses(unsigned int halfsize, unsigned int size) {
unsigned int i, j;
for (i=0; i<halfsize; i++) {
guesses[i+halfsize].key = guesses[i].key | (1l << size);
guesses[i+halfsize].score = guesses[i].score;
for (j=0; j<num_nRaR; j++) {
guesses[i+halfsize].b0to31[j] = guesses[i].b0to31[j];
for (i = 0; i < halfsize; i++) {
guesses[i + halfsize].key = guesses[i].key | (1l << size);
guesses[i + halfsize].score = guesses[i].score;
for (j = 0; j < num_nRaR; j++) {
guesses[i + halfsize].b0to31[j] = guesses[i].b0to31[j];
}
}
}
@ -581,14 +567,13 @@ void expand_guesses(unsigned int halfsize, unsigned int size)
/* checks if the supplied test key is still in the table, which
* is useful when testing different scoring methods */
void check_supplied_testkey(unsigned int size)
{
void check_supplied_testkey(unsigned int size) {
uint64_t partkey;
unsigned int i;
partkey = supplied_testkey & ((1l << size) - 1);
for (i=0; i<num_guesses; i++) {
for (i = 0; i < num_guesses; i++) {
if (guesses[i].key == partkey) {
fprintf(stderr, " supplied test key score = %1.10f, position = %d\n", guesses[i].score, i);
return;
@ -601,8 +586,7 @@ void check_supplied_testkey(unsigned int size)
/* execute_round scores the guesses, sorts them and expands the good half */
void execute_round(unsigned int size)
{
void execute_round(unsigned int size) {
unsigned int halfsize;
// score all the current guesses
@ -630,14 +614,13 @@ void execute_round(unsigned int size)
/* crack is the main cracking algo; it executes the rounds */
void crack()
{
void crack() {
unsigned int i;
uint64_t revkey;
uint64_t foundkey;
for (i=16; i<=48; i++) {
fprintf(stderr, "round %2d, size=%2d\n", i-16, i);
for (i = 16; i <= 48; i++) {
fprintf(stderr, "round %2d, size=%2d\n", i - 16, i);
execute_round(i);
// print some metrics
@ -649,8 +632,7 @@ void crack()
/* test function to make sure I know how the LFSR works */
void testkey(uint64_t key)
{
void testkey(uint64_t key) {
uint64_t i;
uint64_t b0to31 = 0;
uint64_t ks = 0;
@ -663,7 +645,7 @@ void testkey(uint64_t key)
printf("after init with key, uid, nR:\n");
printstate(&hstate);
b0to31 = 0;
for (i=0; i<32; i++) {
for (i = 0; i < 32; i++) {
b0to31 = (b0to31 >> 1) | (hitag2_nstep(&hstate, 1) << 31);
}
printf("ks = 0x%08" PRIx64 ", enc_aR = 0x%08" PRIx64 ", aR = 0x%08" PRIx64 "\n", b0to31, nonces[0].ks ^ 0xffffffff, nonces[0].ks ^ 0xffffffff ^ b0to31);
@ -679,7 +661,7 @@ void testkey(uint64_t key)
// xor upper part of key with encrypted nonce
nRxorkey = nonces[0].enc_nR ^ (key >> 16);
// insert keyupper xor encrypted nonce xor ks
for (i=0; i<32; i++) {
for (i = 0; i < 32; i++) {
// store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
b0to31 = (b0to31 >> 1) | (ht2crypt(lfsr) << 31);
// insert new bit
@ -693,7 +675,7 @@ void testkey(uint64_t key)
printf("\n");
// iterate lfsr with fnL, extracting ks
for (i=0; i<32; i++) {
for (i = 0; i < 32; i++) {
// store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
ks = (ks >> 1) | (ht2crypt(lfsr) << 31);
// insert new bit
@ -710,38 +692,37 @@ void testkey(uint64_t key)
/* test function to generate test data */
void gen_bitstreams_testks(struct guess *g, uint64_t key)
{
unsigned int i, j;
uint64_t nRxorkey, lfsr, ks;
void gen_bitstreams_testks(struct guess *g, uint64_t key) {
unsigned int i, j;
uint64_t nRxorkey, lfsr, ks;
for (j=0; j<num_nRaR; j++) {
for (j = 0; j < num_nRaR; j++) {
// build initial lfsr
lfsr = uid | ((key & 0xffff) << 32);
g->b0to31[j] = 0;
// xor upper part of key with encrypted nonce
nRxorkey = nonces[j].enc_nR ^ (key >> 16);
// insert keyupper xor encrypted nonce xor ks
for (i=0; i<32; i++) {
// store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
g->b0to31[j] = (g->b0to31[j] >> 1) | (ht2crypt(lfsr) << 31);
// insert new bit
lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((g->b0to31[j] >> 31) & 0x1)) << 48);
// shift lfsr
lfsr = lfsr >> 1;
}
// build initial lfsr
lfsr = uid | ((key & 0xffff) << 32);
g->b0to31[j] = 0;
// xor upper part of key with encrypted nonce
nRxorkey = nonces[j].enc_nR ^ (key >> 16);
// insert keyupper xor encrypted nonce xor ks
for (i = 0; i < 32; i++) {
// store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
g->b0to31[j] = (g->b0to31[j] >> 1) | (ht2crypt(lfsr) << 31);
// insert new bit
lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((g->b0to31[j] >> 31) & 0x1)) << 48);
// shift lfsr
lfsr = lfsr >> 1;
}
ks = 0;
// iterate lfsr with fnL, extracting ks
for (i=0; i<32; i++) {
// store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
ks = (ks >> 1) | (ht2crypt(lfsr) << 31);
// insert new bit
lfsr = lfsr | (fnL(lfsr) << 48);
// shift lfsr
lfsr = lfsr >> 1;
}
// iterate lfsr with fnL, extracting ks
for (i = 0; i < 32; i++) {
// store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
ks = (ks >> 1) | (ht2crypt(lfsr) << 31);
// insert new bit
lfsr = lfsr | (fnL(lfsr) << 48);
// shift lfsr
lfsr = lfsr >> 1;
}
printf("orig ks = 0x%08" PRIx64 ", gen ks = 0x%08" PRIx64 ", b0to31 = 0x%08" PRIx64 "\n", nonces[j].ks, ks, g->b0to31[j]);
if (nonces[j].ks != ks) {
@ -752,15 +733,14 @@ void gen_bitstreams_testks(struct guess *g, uint64_t key)
/* test function */
void test()
{
void test() {
uint64_t lfsr;
uint64_t packed;
uint64_t i;
for (i=0; i<1000; i++) {
for (i = 0; i < 1000; i++) {
lfsr = ((uint64_t)rand() << 32) | rand();
packed = packstate(lfsr);
@ -774,15 +754,14 @@ void test()
/* check_key tests the potential key against an encrypted nonce, ks pair */
int check_key(uint64_t key, uint64_t enc_nR, uint64_t ks)
{
int check_key(uint64_t key, uint64_t enc_nR, uint64_t ks) {
Hitag_State hstate;
uint64_t bits;
int i;
hitag2_init(&hstate, key, uid, enc_nR);
bits = 0;
for (i=0; i<32; i++) {
for (i = 0; i < 32; i++) {
bits = (bits >> 1) | (hitag2_nstep(&hstate, 1) << 31);
}
if (ks == bits) {
@ -794,8 +773,7 @@ int check_key(uint64_t key, uint64_t enc_nR, uint64_t ks)
/* start up */
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
unsigned int i;
uint64_t revkey;
uint64_t foundkey;
@ -808,7 +786,7 @@ int main(int argc, char *argv[])
// exit(0);
while ((c = getopt(argc, argv, "u:n:N:t:T:h")) != -1) {
switch(c) {
switch (c) {
case 'u':
uidstr = optarg;
break;
@ -848,7 +826,7 @@ int main(int argc, char *argv[])
crack();
// test all key guesses and stop if one works
for (i=0; i<num_guesses; i++) {
for (i = 0; i < num_guesses; i++) {
if (check_key(guesses[i].key, nonces[0].enc_nR, nonces[0].ks) &&
check_key(guesses[i].key, nonces[1].enc_nR, nonces[1].ks)) {
printf("WIN!!! :)\n");

View file

@ -336,7 +336,7 @@ extern rtccDate RTC_date; // date structure
#define TAG_TYPE_AWID_26 17
#define TAG_TYPE_EM4X05 18
#define TAG_TYPE_TAMAGOTCHI 19
#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram
#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram
// various

View file

@ -142,19 +142,17 @@ rtccTime RTC_time; // time structure
rtccDate RTC_date; // date structure
// convert byte-reversed 8 digit hex to unsigned long
unsigned long hexreversetoulong(BYTE *hex)
{
unsigned long ret= 0L;
unsigned long hexreversetoulong(BYTE *hex) {
unsigned long ret = 0L;
unsigned int x;
BYTE i;
if(strlen(hex) != 8)
if (strlen(hex) != 8)
return 0L;
for(i= 0 ; i < 4 ; ++i)
{
if(sscanf(hex, "%2X", &x) != 1)
return 0L;
for (i = 0 ; i < 4 ; ++i) {
if (sscanf(hex, "%2X", &x) != 1)
return 0L;
ret += ((unsigned long) x) << i * 8;
hex += 2;
}
@ -162,18 +160,17 @@ unsigned long hexreversetoulong(BYTE *hex)
}
// convert byte-reversed 12 digit hex to unsigned long
unsigned long long hexreversetoulonglong(BYTE *hex)
{
unsigned long long ret= 0LL;
unsigned long long hexreversetoulonglong(BYTE *hex) {
unsigned long long ret = 0LL;
BYTE tmp[9];
// this may seem an odd way to do it, but weird compiler issues were
// this may seem an odd way to do it, but weird compiler issues were
// breaking direct conversion!
tmp[8]= '\0';
tmp[8] = '\0';
memset(tmp + 4, '0', 4);
memcpy(tmp, hex + 8, 4);
ret= hexreversetoulong(tmp);
ret = hexreversetoulong(tmp);
ret <<= 32;
memcpy(tmp, hex, 8);
ret += hexreversetoulong(tmp);