mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-05 20:41:34 -07:00
style
This commit is contained in:
parent
0446509d1e
commit
a776f9a0bd
10 changed files with 231 additions and 187 deletions
146
armsrc/em4x70.c
146
armsrc/em4x70.c
|
@ -108,13 +108,13 @@ static bool command_parity = true;
|
|||
//
|
||||
// Four of the commands send a predetermined bitstream, immediately synchronize
|
||||
// on the tag sending the header, and then receive a number of bits from the tag:
|
||||
//
|
||||
//
|
||||
// #define EM4X70_COMMAND_ID 0x01 // 0b0001 --> 0b001'1
|
||||
// Tag: [LIW] [Header][ID₃₁..ID₀][LIW]
|
||||
// Reader: [RM][Command]
|
||||
// Bits Sent: RM + 4 bits
|
||||
// Bits Recv: Header + 32 bits
|
||||
//
|
||||
//
|
||||
// #define EM4X70_COMMAND_UM1 0x02 // 0b0010 --> 0b010'1
|
||||
// Tag: [LIW] [Header][LB₁, LB₀, UM1₂₉..UM1₀][LIW]
|
||||
// Reader: [RM][Command]
|
||||
|
@ -171,7 +171,7 @@ static bool command_parity = true;
|
|||
// Auto-detect tag variant and command parity?
|
||||
// EM4070/V4070 does not contain UM2 or PIN, and UM1 may be OTP (one-time programmable)
|
||||
// EM4170 added Pin and UM2, and UM1
|
||||
//
|
||||
//
|
||||
// Thus, to check for overlap, need only check the first three commands with parity:
|
||||
// | CMD | P? | Bits | Safe? | Overlaps With | Notes
|
||||
// |-------|-----|----------|-------|------------------|------------
|
||||
|
@ -182,7 +182,7 @@ static bool command_parity = true;
|
|||
// | PIN | No | `0b0100` | N/A | | DO NOT USE ... just in case
|
||||
// | UM2 | No | `0b0111` | Yes | None! | Safe ... indicates no parity AND EM4170 tag type
|
||||
// | ID | Yes | `0b0011` | Yes | Auth w/o Parity | Safe to try ... indicates parity if successful
|
||||
// | UM1 | Yes | `0b0101` | Yes | Write w/o Parity |
|
||||
// | UM1 | Yes | `0b0101` | Yes | Write w/o Parity |
|
||||
// | AUTH | Yes | `0b0110` | Yes | None! | Not testable
|
||||
// | WRITE | Yes | `0b1010` | NO | None! | DO NOT USE ... just in case
|
||||
// | PIN | Yes | `0b1001` | N/A | None! | DO NOT USE ... just in case
|
||||
|
@ -359,15 +359,15 @@ typedef struct _em4x70_transmit_log_t {
|
|||
em4x70_sublog_t receive;
|
||||
} em4x70_transmitted_data_log_t;
|
||||
em4x70_transmitted_data_log_t g_not_used_directly; // change to bigbuff allocation?
|
||||
em4x70_transmitted_data_log_t* g_Log = &g_not_used_directly;
|
||||
em4x70_transmitted_data_log_t *g_Log = &g_not_used_directly;
|
||||
static void log_reset(void) {
|
||||
if (g_Log != NULL) {
|
||||
memset(g_Log, 0, sizeof(em4x70_transmitted_data_log_t));
|
||||
}
|
||||
}
|
||||
static void log_dump_helper(em4x70_sublog_t * part, bool is_transmit) {
|
||||
static void log_dump_helper(em4x70_sublog_t *part, bool is_transmit) {
|
||||
if (g_dbglevel >= DBG_INFO || FORCE_ENABLE_LOGGING) {
|
||||
char const * const direction = is_transmit ? "sent >>>" : "recv <<<";
|
||||
char const *const direction = is_transmit ? "sent >>>" : "recv <<<";
|
||||
if (part->bits_used == 0) {
|
||||
DPRINTF_EXTENDED(("%s: no data", direction));
|
||||
} else {
|
||||
|
@ -377,12 +377,12 @@ static void log_dump_helper(em4x70_sublog_t * part, bool is_transmit) {
|
|||
bitstring[i] = part->bit[i] ? '1' : '0';
|
||||
}
|
||||
DPRINTF_EXTENDED((
|
||||
"%s: [ %8d .. %8d ] ( %6d ) %2d bits: %s",
|
||||
direction,
|
||||
part->start_tick, part->end_tick,
|
||||
part->end_tick - part->start_tick,
|
||||
part->bits_used, bitstring
|
||||
));
|
||||
"%s: [ %8d .. %8d ] ( %6d ) %2d bits: %s",
|
||||
direction,
|
||||
part->start_tick, part->end_tick,
|
||||
part->end_tick - part->start_tick,
|
||||
part->bits_used, bitstring
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -390,7 +390,7 @@ static void log_dump(void) {
|
|||
if (g_dbglevel >= DBG_INFO || FORCE_ENABLE_LOGGING) {
|
||||
bool hasContent = false;
|
||||
if (g_Log != NULL) {
|
||||
uint8_t * check_for_data = (uint8_t *)g_Log;
|
||||
uint8_t *check_for_data = (uint8_t *)g_Log;
|
||||
for (size_t i = 0; i < sizeof(em4x70_transmitted_data_log_t); ++i) {
|
||||
if (check_for_data[i] != 0) {
|
||||
hasContent = true;
|
||||
|
@ -419,7 +419,7 @@ static void log_sent_bit_end(uint32_t end_tick) {
|
|||
}
|
||||
}
|
||||
static void log_received_bit_start(uint32_t start_tick) {
|
||||
if (g_Log != NULL && g_Log->receive.start_tick == 0) {
|
||||
if (g_Log != NULL && g_Log->receive.start_tick == 0) {
|
||||
g_Log->receive.start_tick = start_tick;
|
||||
}
|
||||
}
|
||||
|
@ -475,7 +475,7 @@ static bool check_ack(void) {
|
|||
// ACK 64 + 64
|
||||
// NAK 64 + 48
|
||||
if (check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD) &&
|
||||
check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD)) {
|
||||
check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD)) {
|
||||
// ACK
|
||||
return true;
|
||||
}
|
||||
|
@ -516,12 +516,12 @@ typedef struct _em4x70_command_bitstream {
|
|||
uint8_t received_data_converted_to_bytes[(EM4X70_MAX_BITSTREAM_BITS / 8) + (EM4X70_MAX_BITSTREAM_BITS % 8 ? 1 : 0)];
|
||||
} em4x70_command_bitstream_t;
|
||||
|
||||
typedef bool (*bitstream_command_generator_id_t)(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity);
|
||||
typedef bool (*bitstream_command_generator_um1_t)(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity);
|
||||
typedef bool (*bitstream_command_generator_um2_t)(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity);
|
||||
typedef bool (*bitstream_command_generator_auth_t)(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity, const uint8_t * rnd, const uint8_t * frnd);
|
||||
typedef bool (*bitstream_command_generator_pin_t)(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity, const uint8_t * tag_id, const uint32_t pin_little_endian);
|
||||
typedef bool (*bitstream_command_generator_write_t)(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity, uint16_t data_little_endian, uint8_t address);
|
||||
typedef bool (*bitstream_command_generator_id_t)(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity);
|
||||
typedef bool (*bitstream_command_generator_um1_t)(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity);
|
||||
typedef bool (*bitstream_command_generator_um2_t)(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity);
|
||||
typedef bool (*bitstream_command_generator_auth_t)(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity, const uint8_t *rnd, const uint8_t *frnd);
|
||||
typedef bool (*bitstream_command_generator_pin_t)(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity, const uint8_t *tag_id, const uint32_t pin_little_endian);
|
||||
typedef bool (*bitstream_command_generator_write_t)(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity, uint16_t data_little_endian, uint8_t address);
|
||||
|
||||
typedef struct _em4x70_command_generators_t {
|
||||
bitstream_command_generator_id_t id;
|
||||
|
@ -534,9 +534,9 @@ typedef struct _em4x70_command_generators_t {
|
|||
|
||||
#endif // #pragma endregion // Bitstream structures / enumerations
|
||||
#if 1 // #pragma region // Functions to dump bitstreams to debug output
|
||||
static void bitstream_dump_helper(const em4x70_bitstream_t * bitstream, bool is_transmit) {
|
||||
static void bitstream_dump_helper(const em4x70_bitstream_t *bitstream, bool is_transmit) {
|
||||
// mimic the log's output format to make comparisons easier
|
||||
char const * const direction = is_transmit ? "sent >>>" : "recv <<<";
|
||||
char const *const direction = is_transmit ? "sent >>>" : "recv <<<";
|
||||
if (bitstream->bitcount == 0) {
|
||||
if (g_dbglevel >= DBG_INFO || true) {
|
||||
DPRINTF_EXTENDED(("%s: no data", direction));
|
||||
|
@ -550,17 +550,17 @@ static void bitstream_dump_helper(const em4x70_bitstream_t * bitstream, bool is_
|
|||
bitstring[i] = bitstream->one_bit_per_byte[i] ? '1' : '0';
|
||||
}
|
||||
DPRINTF_EXTENDED((
|
||||
"%s: [ %8d .. %8d ] ( %6d ) %2d bits: %s%s",
|
||||
direction,
|
||||
0, 0, 0,
|
||||
bitstream->bitcount + (is_transmit ? 2u : 0u), // add the two RM bits to transmitted data
|
||||
is_transmit ? "00" : "", // add the two RM bits to transmitted data
|
||||
bitstring
|
||||
));
|
||||
"%s: [ %8d .. %8d ] ( %6d ) %2d bits: %s%s",
|
||||
direction,
|
||||
0, 0, 0,
|
||||
bitstream->bitcount + (is_transmit ? 2u : 0u), // add the two RM bits to transmitted data
|
||||
is_transmit ? "00" : "", // add the two RM bits to transmitted data
|
||||
bitstring
|
||||
));
|
||||
}
|
||||
}
|
||||
static void bitstream_dump(const em4x70_command_bitstream_t * cmd_bitstream) {
|
||||
bitstream_dump_helper(&cmd_bitstream->to_send, true );
|
||||
static void bitstream_dump(const em4x70_command_bitstream_t *cmd_bitstream) {
|
||||
bitstream_dump_helper(&cmd_bitstream->to_send, true);
|
||||
bitstream_dump_helper(&cmd_bitstream->to_receive, false);
|
||||
}
|
||||
#endif // #pragma region // Functions to dump bitstreams to debug output
|
||||
|
@ -569,14 +569,14 @@ static void bitstream_dump(const em4x70_command_bitstream_t * cmd_bitstream) {
|
|||
/// @brief Internal function to send a bitstream to the tag.
|
||||
/// @details This function presumes a validated structure, and sends the bitstream without delays, to support timing-sensitive operations.
|
||||
/// @param send The details on the bitstream to send to the tag.
|
||||
/// @return
|
||||
static bool send_bitstream_internal(const em4x70_bitstream_t * send) {
|
||||
/// @return
|
||||
static bool send_bitstream_internal(const em4x70_bitstream_t *send) {
|
||||
// similar to original send_command_and_read, but using provided bitstream
|
||||
int retries = EM4X70_COMMAND_RETRIES;
|
||||
|
||||
// TIMING SENSITIVE FUNCTION ... Minimize delays after finding the listen window
|
||||
while (retries) {
|
||||
const uint8_t * s = send->one_bit_per_byte;
|
||||
const uint8_t *s = send->one_bit_per_byte;
|
||||
uint8_t sent = 0;
|
||||
retries--;
|
||||
if (find_listen_window(true)) { // `true` will automatically send the two `RM` zero bits
|
||||
|
@ -597,9 +597,9 @@ static bool send_bitstream_internal(const em4x70_bitstream_t * send) {
|
|||
/// @param recv Buffer to store received data from the tag.
|
||||
/// `recv->expected_bitcount` must be initialized to indicate expected bits to receive from the tag.
|
||||
/// @return true only if the bitstream was sent and the expected count of bits were received from the tag.
|
||||
static bool send_bitstream_and_read(em4x70_command_bitstream_t * command_bitstream) {
|
||||
const em4x70_bitstream_t * send = &command_bitstream->to_send;
|
||||
em4x70_bitstream_t * recv = &command_bitstream->to_receive;
|
||||
static bool send_bitstream_and_read(em4x70_command_bitstream_t *command_bitstream) {
|
||||
const em4x70_bitstream_t *send = &command_bitstream->to_send;
|
||||
em4x70_bitstream_t *recv = &command_bitstream->to_receive;
|
||||
|
||||
// Validate the parameters before proceeding
|
||||
bool parameters_valid = true;
|
||||
|
@ -614,7 +614,7 @@ static bool send_bitstream_and_read(em4x70_command_bitstream_t * command_bitstre
|
|||
(command_bitstream->command == EM4X70_COMMAND_UM1) ||
|
||||
(command_bitstream->command == EM4X70_COMMAND_UM2) ||
|
||||
(command_bitstream->command == EM4X70_COMMAND_AUTH)
|
||||
) {
|
||||
) {
|
||||
// These are the four commands that are supported by this function.
|
||||
// Allow these to proceed.
|
||||
} else {
|
||||
|
@ -665,7 +665,7 @@ static bool send_bitstream_and_read(em4x70_command_bitstream_t * command_bitstre
|
|||
|
||||
// similar to original send_command_and_read, but using provided bitstream
|
||||
int bits_received = 0;
|
||||
|
||||
|
||||
// NOTE: reset of log does not track the time first bit is sent. That occurs
|
||||
// when the first sent bit is recorded in the log.
|
||||
log_reset();
|
||||
|
@ -694,9 +694,9 @@ static bool send_bitstream_and_read(em4x70_command_bitstream_t * command_bitstre
|
|||
// finally return the result of the operation
|
||||
return result;
|
||||
}
|
||||
static bool send_bitstream_wait_ack_wait_read(em4x70_command_bitstream_t * command_bitstream) {
|
||||
const em4x70_bitstream_t * send = &command_bitstream->to_send;
|
||||
em4x70_bitstream_t * recv = &command_bitstream->to_receive;
|
||||
static bool send_bitstream_wait_ack_wait_read(em4x70_command_bitstream_t *command_bitstream) {
|
||||
const em4x70_bitstream_t *send = &command_bitstream->to_send;
|
||||
em4x70_bitstream_t *recv = &command_bitstream->to_receive;
|
||||
|
||||
// Validate the parameters before proceeding
|
||||
bool parameters_valid = true;
|
||||
|
@ -769,10 +769,10 @@ static bool send_bitstream_wait_ack_wait_read(em4x70_command_bitstream_t * comma
|
|||
|
||||
return result;
|
||||
}
|
||||
static bool send_bitstream_wait_ack_wait_ack(em4x70_command_bitstream_t * command_bitstream) {
|
||||
static bool send_bitstream_wait_ack_wait_ack(em4x70_command_bitstream_t *command_bitstream) {
|
||||
|
||||
const em4x70_bitstream_t * send = &command_bitstream->to_send;
|
||||
em4x70_bitstream_t * recv = &command_bitstream->to_receive;
|
||||
const em4x70_bitstream_t *send = &command_bitstream->to_send;
|
||||
em4x70_bitstream_t *recv = &command_bitstream->to_receive;
|
||||
|
||||
// Validate the parameters before proceeding
|
||||
bool parameters_valid = true;
|
||||
|
@ -835,7 +835,7 @@ static bool send_bitstream_wait_ack_wait_ack(em4x70_command_bitstream_t * comman
|
|||
#endif // #pragma region // Functions to send bitstreams, with options to receive data
|
||||
#if 1 // #pragma region // Create bitstreams for each type of EM4x70 command
|
||||
|
||||
static bool add_bit_to_bitstream(em4x70_bitstream_t * s, bool b) {
|
||||
static bool add_bit_to_bitstream(em4x70_bitstream_t *s, bool b) {
|
||||
uint8_t i = s->bitcount;
|
||||
uint8_t bits_to_add = 1u;
|
||||
|
||||
|
@ -848,10 +848,10 @@ static bool add_bit_to_bitstream(em4x70_bitstream_t * s, bool b) {
|
|||
s->bitcount++;
|
||||
return true;
|
||||
}
|
||||
static bool add_nibble_to_bitstream(em4x70_bitstream_t * s, uint8_t nibble, bool add_fifth_parity_bit) {
|
||||
static bool add_nibble_to_bitstream(em4x70_bitstream_t *s, uint8_t nibble, bool add_fifth_parity_bit) {
|
||||
uint8_t i = s->bitcount;
|
||||
uint8_t bits_to_add = add_fifth_parity_bit ? 5u : 4u;
|
||||
|
||||
|
||||
if (i > EM4X70_MAX_BITSTREAM_BITS - bits_to_add) {
|
||||
DPRINTF_ERROR(("Too many bits to add to bitstream: %d, %d", i, bits_to_add));
|
||||
return false;
|
||||
|
@ -875,7 +875,7 @@ static bool add_nibble_to_bitstream(em4x70_bitstream_t * s, uint8_t nibble, bool
|
|||
s->bitcount += bits_to_add;
|
||||
return true;
|
||||
}
|
||||
static bool add_byte_to_bitstream(em4x70_bitstream_t * s, uint8_t b) {
|
||||
static bool add_byte_to_bitstream(em4x70_bitstream_t *s, uint8_t b) {
|
||||
uint8_t i = s->bitcount;
|
||||
uint8_t bits_to_add = 8u;
|
||||
|
||||
|
@ -897,7 +897,7 @@ static bool add_byte_to_bitstream(em4x70_bitstream_t * s, uint8_t b) {
|
|||
}
|
||||
|
||||
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_id(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity) {
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_id(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity) {
|
||||
const uint8_t expected_bits_to_send = 4u;
|
||||
bool result = true;
|
||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||
|
@ -911,7 +911,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_id(em4x70_command_bitstream_t
|
|||
}
|
||||
return result;
|
||||
}
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_um1(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity) {
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_um1(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity) {
|
||||
const uint8_t expected_bits_to_send = 4u;
|
||||
bool result = true;
|
||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||
|
@ -925,7 +925,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_um1(em4x70_command_bitstream_
|
|||
}
|
||||
return result;
|
||||
}
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_um2(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity) {
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_um2(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity) {
|
||||
const uint8_t expected_bits_to_send = 4u;
|
||||
bool result = true;
|
||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||
|
@ -939,14 +939,14 @@ static bool create_legacy_em4x70_bitstream_for_cmd_um2(em4x70_command_bitstream_
|
|||
}
|
||||
return true;
|
||||
}
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_auth(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity, const uint8_t *rnd, const uint8_t *frnd) {
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_auth(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity, const uint8_t *rnd, const uint8_t *frnd) {
|
||||
const uint8_t expected_bits_to_send = 96u;
|
||||
bool result = true;
|
||||
|
||||
|
||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||
out_cmd_bitstream->command = EM4X70_COMMAND_AUTH;
|
||||
|
||||
em4x70_bitstream_t * s = &out_cmd_bitstream->to_send;
|
||||
em4x70_bitstream_t *s = &out_cmd_bitstream->to_send;
|
||||
|
||||
// *********************************************************************************
|
||||
// HACK -- Insert an extra zero bit to match legacy behavior
|
||||
|
@ -994,12 +994,12 @@ static bool create_legacy_em4x70_bitstream_for_cmd_auth(em4x70_command_bitstream
|
|||
|
||||
return result;
|
||||
}
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_pin(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity, const uint8_t *tag_id, const uint32_t pin) {
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_pin(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity, const uint8_t *tag_id, const uint32_t pin) {
|
||||
const uint8_t expected_bits_to_send = 69; // normally 68 bits, but legacy hack inserts an extra RM bit, and always adds a command parity bit
|
||||
bool result = true;
|
||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||
|
||||
em4x70_bitstream_t * s = &out_cmd_bitstream->to_send;
|
||||
em4x70_bitstream_t *s = &out_cmd_bitstream->to_send;
|
||||
|
||||
out_cmd_bitstream->command = EM4X70_COMMAND_PIN;
|
||||
|
||||
|
@ -1015,7 +1015,7 @@ static bool create_legacy_em4x70_bitstream_for_cmd_pin(em4x70_command_bitstream_
|
|||
// Send tag's ID ... indexes 4 .. 35
|
||||
// e.g., tag_id points to &tag.data[4] ... &tag.data[7]
|
||||
for (uint_fast8_t i = 0; i < 4; i++) {
|
||||
uint8_t b = tag_id[3-i];
|
||||
uint8_t b = tag_id[3 - i];
|
||||
result = result && add_byte_to_bitstream(s, b);
|
||||
}
|
||||
|
||||
|
@ -1033,13 +1033,13 @@ static bool create_legacy_em4x70_bitstream_for_cmd_pin(em4x70_command_bitstream_
|
|||
}
|
||||
return result;
|
||||
}
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_write(em4x70_command_bitstream_t * out_cmd_bitstream, bool with_command_parity, uint16_t new_data, uint8_t address) {
|
||||
static bool create_legacy_em4x70_bitstream_for_cmd_write(em4x70_command_bitstream_t *out_cmd_bitstream, bool with_command_parity, uint16_t new_data, uint8_t address) {
|
||||
const uint8_t expected_bits_to_send = 35u; // normally 34 bits, but legacy hack inserts an extra RM bit, and always adds a command parity bit
|
||||
bool result = true;
|
||||
memset(out_cmd_bitstream, 0, sizeof(em4x70_command_bitstream_t));
|
||||
out_cmd_bitstream->command = EM4X70_COMMAND_WRITE;
|
||||
|
||||
em4x70_bitstream_t * s = &out_cmd_bitstream->to_send;
|
||||
em4x70_bitstream_t *s = &out_cmd_bitstream->to_send;
|
||||
|
||||
// *********************************************************************************
|
||||
// HACK -- Insert an extra zero bit to match legacy behavior
|
||||
|
@ -1105,7 +1105,7 @@ const em4x70_command_generators_t legacy_em4x70_command_generators = {
|
|||
static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *response) {
|
||||
em4x70_command_bitstream_t auth_cmd;
|
||||
|
||||
const em4x70_command_generators_t * generator = &legacy_em4x70_command_generators;
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->auth(&auth_cmd, command_parity, rnd, frnd);
|
||||
|
||||
bool result = send_bitstream_and_read(&auth_cmd);
|
||||
|
@ -1193,7 +1193,7 @@ static int bruteforce(const uint8_t address, const uint8_t *rnd, const uint8_t *
|
|||
// log entry/exit point
|
||||
static int send_pin(const uint32_t pin) {
|
||||
em4x70_command_bitstream_t send_pin_cmd;
|
||||
const em4x70_command_generators_t * generator = &legacy_em4x70_command_generators;
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->pin(&send_pin_cmd, command_parity, &tag.data[4], pin);
|
||||
|
||||
bool result = send_bitstream_wait_ack_wait_read(&send_pin_cmd);
|
||||
|
@ -1204,7 +1204,7 @@ static int send_pin(const uint32_t pin) {
|
|||
static int write(const uint16_t word, const uint8_t address) {
|
||||
em4x70_command_bitstream_t write_cmd;
|
||||
|
||||
const em4x70_command_generators_t * generator = &legacy_em4x70_command_generators;
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->write(&write_cmd, command_parity, word, address);
|
||||
|
||||
bool result = send_bitstream_wait_ack_wait_ack(&write_cmd);
|
||||
|
@ -1226,10 +1226,10 @@ static bool find_listen_window(bool command) {
|
|||
96 ( 64 + 32 )
|
||||
64 ( 32 + 16 +16 )*/
|
||||
|
||||
if (check_pulse_length(get_pulse_length(RISING_EDGE), (2 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_HALF_PERIOD) &&
|
||||
check_pulse_length(get_pulse_length(RISING_EDGE), (2 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_HALF_PERIOD) &&
|
||||
check_pulse_length(get_pulse_length(FALLING_EDGE), (2 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_FULL_PERIOD) &&
|
||||
check_pulse_length(get_pulse_length(FALLING_EDGE), (1 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_FULL_PERIOD)) {
|
||||
if (check_pulse_length(get_pulse_length(RISING_EDGE), (2 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_HALF_PERIOD) &&
|
||||
check_pulse_length(get_pulse_length(RISING_EDGE), (2 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_HALF_PERIOD) &&
|
||||
check_pulse_length(get_pulse_length(FALLING_EDGE), (2 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_FULL_PERIOD) &&
|
||||
check_pulse_length(get_pulse_length(FALLING_EDGE), (1 * EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_FULL_PERIOD)) {
|
||||
|
||||
if (command) {
|
||||
/* Here we are after the 64 duration edge.
|
||||
|
@ -1238,7 +1238,7 @@ static bool find_listen_window(bool command) {
|
|||
*
|
||||
* I've found 32-40 field cycles works best
|
||||
* Allow user adjustment in range: 24-48 field cycles?
|
||||
* On PM3Easy I've seen success at 24..40 field
|
||||
* On PM3Easy I've seen success at 24..40 field
|
||||
*/
|
||||
WaitTicks(40 * TICKS_PER_FC);
|
||||
// Send RM Command
|
||||
|
@ -1291,7 +1291,7 @@ static uint8_t encoded_bit_array_to_byte(const uint8_t *bits, int count_of_bits)
|
|||
*/
|
||||
static bool em4x70_read_id(void) {
|
||||
em4x70_command_bitstream_t read_id_cmd;
|
||||
const em4x70_command_generators_t * generator = &legacy_em4x70_command_generators;
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->id(&read_id_cmd, command_parity);
|
||||
|
||||
bool result = send_bitstream_and_read(&read_id_cmd);
|
||||
|
@ -1308,7 +1308,7 @@ static bool em4x70_read_id(void) {
|
|||
*/
|
||||
static bool em4x70_read_um1(void) {
|
||||
em4x70_command_bitstream_t read_um1_cmd;
|
||||
const em4x70_command_generators_t * generator = &legacy_em4x70_command_generators;
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->um1(&read_um1_cmd, command_parity);
|
||||
|
||||
bool result = send_bitstream_and_read(&read_um1_cmd);
|
||||
|
@ -1327,7 +1327,7 @@ static bool em4x70_read_um1(void) {
|
|||
*/
|
||||
static bool em4x70_read_um2(void) {
|
||||
em4x70_command_bitstream_t read_um2_cmd;
|
||||
const em4x70_command_generators_t * generator = &legacy_em4x70_command_generators;
|
||||
const em4x70_command_generators_t *generator = &legacy_em4x70_command_generators;
|
||||
generator->um2(&read_um2_cmd, command_parity);
|
||||
|
||||
bool result = send_bitstream_and_read(&read_um2_cmd);
|
||||
|
|
130
armsrc/pcf7931.c
130
armsrc/pcf7931.c
|
@ -43,7 +43,7 @@
|
|||
#define _64T0 (CLOCK)
|
||||
|
||||
// calculating the two possible pmc lengths, based on the clock. -4 at the end is to make sure not to increment too far
|
||||
#define PMC_16T0_LEN ((128 + 127 + 16 + 32 + 33 + 16) * CLOCK/64);
|
||||
#define PMC_16T0_LEN ((128 + 127 + 16 + 32 + 33 + 16) * CLOCK/64);
|
||||
#define PMC_32T0_LEN ((128 + 127 + 16 + 32 + 33 ) * CLOCK/64);
|
||||
|
||||
// theshold for recognition of positive/negative slope
|
||||
|
@ -54,13 +54,13 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
|
|||
uint8_t blocks[8][16];
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
uint16_t g_GraphTraceLen = BigBuf_max_traceLen();
|
||||
// limit g_GraphTraceLen to a little more than 2 data frames.
|
||||
// limit g_GraphTraceLen to a little more than 2 data frames.
|
||||
// To make sure a complete dataframe is in the dataset.
|
||||
// 1 Frame is 16 Byte -> 128byte. at a T0 of 64 -> 8129 Samples per frame.
|
||||
// + PMC -> 384T0 --> 8576 samples required for one block
|
||||
// to make sure that one complete block is definitely being sampled, we need 2 times that
|
||||
// which is ~17.xxx samples. round up. and clamp to this value.
|
||||
|
||||
|
||||
// TODO: Doublecheck why this is being limited? - seems not to be needed.
|
||||
// g_GraphTraceLen = (g_GraphTraceLen > 18000) ? 18000 : g_GraphTraceLen;
|
||||
|
||||
|
@ -87,15 +87,15 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
|
|||
samplePosLastEdge = 0;
|
||||
block_done = 0;
|
||||
bitPos = 0;
|
||||
lastClockDuration=0;
|
||||
|
||||
for (sample = 1 ; sample < g_GraphTraceLen-4; sample++) {
|
||||
// condition is searching for the next edge, in the expected diretion.
|
||||
//todo: without flouz
|
||||
dest[sample] = (uint8_t)(dest[sample-1] * IIR_CONST1 + dest[sample] * IIR_CONST2); // apply IIR filter
|
||||
lastClockDuration = 0;
|
||||
|
||||
if ( ((dest[sample] + THRESHOLD) < dest[sample-1] && expectedNextEdge == FALLING ) ||
|
||||
((dest[sample] - THRESHOLD) > dest[sample-1] && expectedNextEdge == RISING )) {
|
||||
for (sample = 1 ; sample < g_GraphTraceLen - 4; sample++) {
|
||||
// condition is searching for the next edge, in the expected diretion.
|
||||
//todo: without flouz
|
||||
dest[sample] = (uint8_t)(dest[sample - 1] * IIR_CONST1 + dest[sample] * IIR_CONST2); // apply IIR filter
|
||||
|
||||
if (((dest[sample] + THRESHOLD) < dest[sample - 1] && expectedNextEdge == FALLING) ||
|
||||
((dest[sample] - THRESHOLD) > dest[sample - 1] && expectedNextEdge == RISING)) {
|
||||
//okay, next falling/rising edge found
|
||||
|
||||
expectedNextEdge = (expectedNextEdge == FALLING) ? RISING : FALLING; //toggle the next expected edge
|
||||
|
@ -104,14 +104,14 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
|
|||
lastClockDuration = samplePosCurrentEdge - samplePosLastEdge;
|
||||
samplePosLastEdge = sample;
|
||||
|
||||
// Dbprintf("%d, %d, edge found, len: %d, nextEdge: %d", sample, dest[sample], lastClockDuration*DECIMATION, expectedNextEdge);
|
||||
|
||||
// Dbprintf("%d, %d, edge found, len: %d, nextEdge: %d", sample, dest[sample], lastClockDuration*DECIMATION, expectedNextEdge);
|
||||
|
||||
// Switch depending on lastClockDuration length:
|
||||
// 16T0
|
||||
// 16T0
|
||||
if (ABS(lastClockDuration - _16T0) < TOLERANCE) {
|
||||
|
||||
// if the clock before also was 16T0, it is a PMC!
|
||||
if (ABS(beforeLastClockDuration - _16T0) < TOLERANCE) {
|
||||
if (ABS(beforeLastClockDuration - _16T0) < TOLERANCE) {
|
||||
// It's a PMC
|
||||
Dbprintf(_GREEN_("PMC 16T0 FOUND:") " bitPos: %d, sample: %d", bitPos, sample);
|
||||
sample += PMC_16T0_LEN; // move to the sample after PMC
|
||||
|
@ -120,44 +120,44 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
|
|||
samplePosLastEdge = sample;
|
||||
block_done = 1;
|
||||
}
|
||||
|
||||
// 32TO
|
||||
|
||||
// 32TO
|
||||
} else if (ABS(lastClockDuration - _32T0) < TOLERANCE) {
|
||||
// if the clock before also was 16T0, it is a PMC!
|
||||
if (ABS(beforeLastClockDuration - _16T0) < TOLERANCE) {
|
||||
// It's a PMC !
|
||||
Dbprintf(_GREEN_("PMC 32T0 FOUND:") " bitPos: %d, sample: %d", bitPos, sample);
|
||||
|
||||
|
||||
sample += PMC_32T0_LEN; // move to the sample after PMC
|
||||
|
||||
expectedNextEdge = FALLING;
|
||||
samplePosLastEdge = sample;
|
||||
block_done = 1;
|
||||
|
||||
// if no pmc, then its a normal bit.
|
||||
// Check if its the second time, the edge changed if yes, then the bit is 0
|
||||
// if no pmc, then its a normal bit.
|
||||
// Check if its the second time, the edge changed if yes, then the bit is 0
|
||||
} else if (half_switch == 1) {
|
||||
bits[bitPos] = 0;
|
||||
// reset the edge counter to 0
|
||||
half_switch = 0;
|
||||
bitPos++;
|
||||
|
||||
// if it is the first time the edge changed. No bit value will be set here, bit if the
|
||||
// edge changes again, it will be. see case above.
|
||||
// if it is the first time the edge changed. No bit value will be set here, bit if the
|
||||
// edge changes again, it will be. see case above.
|
||||
} else
|
||||
half_switch++;
|
||||
|
||||
// 64T0
|
||||
// 64T0
|
||||
} else if (ABS(lastClockDuration - _64T0) < TOLERANCE) {
|
||||
// this means, bit here is 1
|
||||
bits[bitPos] = 1;
|
||||
bitPos++;
|
||||
|
||||
// Error
|
||||
|
||||
// Error
|
||||
} else {
|
||||
// some Error. maybe check tolerances.
|
||||
// some Error. maybe check tolerances.
|
||||
// likeley to happen in the first block.
|
||||
|
||||
|
||||
// In an Ideal world, this can be enabled. However, if only bad antenna field, this print will flood the output
|
||||
// and one might miss some "good" frames.
|
||||
//Dbprintf(_RED_("ERROR in demodulation") " Length last clock: %d - check threshold/tolerance/signal. Toss block", lastClockDuration*DECIMATION);
|
||||
|
@ -168,7 +168,7 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
|
|||
|
||||
if (block_done == 1) {
|
||||
// Dbprintf(_YELLOW_("Block Done") " bitPos: %d, sample: %d", bitPos, sample);
|
||||
|
||||
|
||||
// check if it is a complete block. If bitpos <128, it means that we did not receive
|
||||
// a complete block. E.g. at the first start of a transmission.
|
||||
// only save if a complete block is being received.
|
||||
|
@ -187,14 +187,14 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
|
|||
}
|
||||
num_blocks++;
|
||||
}
|
||||
// now start over for the next block / first complete block.
|
||||
// now start over for the next block / first complete block.
|
||||
bitPos = 0;
|
||||
block_done = 0;
|
||||
half_switch = 0;
|
||||
}
|
||||
|
||||
}else {
|
||||
// Dbprintf("%d, %d", sample, dest[sample]);
|
||||
} else {
|
||||
// Dbprintf("%d, %d", sample, dest[sample]);
|
||||
}
|
||||
|
||||
// one block only holds 16byte (=128 bit) and then comes the PMC. so if more bit are found than 129, there must be an issue and PMC has not been identfied...
|
||||
|
@ -204,8 +204,8 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
|
|||
bitPos = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
memcpy(outBlocks, blocks, 16 * num_blocks);
|
||||
return num_blocks;
|
||||
}
|
||||
|
@ -251,10 +251,10 @@ bool IsBlock1PCF7931(const uint8_t *block) {
|
|||
}
|
||||
|
||||
void ReadPCF7931(bool ledcontrol) {
|
||||
|
||||
|
||||
uint8_t maxBlocks = 8; // readable blocks
|
||||
int found_blocks = 0; // successfully read blocks
|
||||
|
||||
|
||||
// TODO: Why 17 byte len? 16 should be good.
|
||||
uint8_t memory_blocks[maxBlocks][17]; // PCF content
|
||||
uint8_t single_blocks[maxBlocks][17]; // PFC blocks with unknown position
|
||||
|
@ -263,7 +263,7 @@ void ReadPCF7931(bool ledcontrol) {
|
|||
int single_blocks_cnt = 0;
|
||||
|
||||
size_t n; // transmitted blocks
|
||||
|
||||
|
||||
//uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found
|
||||
int errors = 0; // error counter
|
||||
int tries = 0; // tries counter
|
||||
|
@ -300,7 +300,7 @@ void ReadPCF7931(bool ledcontrol) {
|
|||
goto end;
|
||||
}
|
||||
|
||||
// This part was not working properly.
|
||||
// This part was not working properly.
|
||||
// So currently the blocks are not being sorted, but at least printed.
|
||||
|
||||
// // our logic breaks if we don't get at least two blocks
|
||||
|
@ -403,28 +403,28 @@ void ReadPCF7931(bool ledcontrol) {
|
|||
|
||||
|
||||
end:
|
||||
/*
|
||||
Dbprintf("-----------------------------------------");
|
||||
Dbprintf("Memory content:");
|
||||
Dbprintf("-----------------------------------------");
|
||||
for (i = 0; i < maxBlocks; ++i) {
|
||||
if (memory_blocks[i][ALLOC])
|
||||
print_result("Block", memory_blocks[i], 16);
|
||||
else
|
||||
Dbprintf("<missing block %d>", i);
|
||||
}
|
||||
Dbprintf("-----------------------------------------");
|
||||
/*
|
||||
Dbprintf("-----------------------------------------");
|
||||
Dbprintf("Memory content:");
|
||||
Dbprintf("-----------------------------------------");
|
||||
for (i = 0; i < maxBlocks; ++i) {
|
||||
if (memory_blocks[i][ALLOC])
|
||||
print_result("Block", memory_blocks[i], 16);
|
||||
else
|
||||
Dbprintf("<missing block %d>", i);
|
||||
}
|
||||
Dbprintf("-----------------------------------------");
|
||||
|
||||
if (found_blocks < maxBlocks) {
|
||||
Dbprintf("-----------------------------------------");
|
||||
Dbprintf("Blocks with unknown position:");
|
||||
Dbprintf("-----------------------------------------");
|
||||
for (i = 0; i < single_blocks_cnt; ++i)
|
||||
print_result("Block", single_blocks[i], 16);
|
||||
if (found_blocks < maxBlocks) {
|
||||
Dbprintf("-----------------------------------------");
|
||||
Dbprintf("Blocks with unknown position:");
|
||||
Dbprintf("-----------------------------------------");
|
||||
for (i = 0; i < single_blocks_cnt; ++i)
|
||||
print_result("Block", single_blocks[i], 16);
|
||||
|
||||
Dbprintf("-----------------------------------------");
|
||||
}
|
||||
*/
|
||||
Dbprintf("-----------------------------------------");
|
||||
}
|
||||
*/
|
||||
|
||||
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
@ -434,7 +434,7 @@ static void RealWritePCF7931(
|
|||
uint16_t init_delay,
|
||||
int8_t offsetPulseWidth, int8_t offsetPulsePosition,
|
||||
uint8_t address, uint8_t byte, uint8_t data,
|
||||
bool ledcontrol){
|
||||
bool ledcontrol) {
|
||||
|
||||
uint32_t tab[1024] = {0}; // data times frame
|
||||
uint32_t u = 0;
|
||||
|
@ -512,10 +512,10 @@ static void RealWritePCF7931(
|
|||
* @param data : data to write
|
||||
*/
|
||||
void WritePCF7931(
|
||||
uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7,
|
||||
uint16_t init_delay,
|
||||
int8_t offsetPulseWidth, int8_t offsetPulsePosition,
|
||||
uint8_t address, uint8_t byte, uint8_t data,
|
||||
uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7,
|
||||
uint16_t init_delay,
|
||||
int8_t offsetPulseWidth, int8_t offsetPulsePosition,
|
||||
uint8_t address, uint8_t byte, uint8_t data,
|
||||
bool ledcontrol) {
|
||||
|
||||
if (g_dbglevel >= DBG_INFO) {
|
||||
|
@ -550,7 +550,7 @@ void SendCmdPCF7931(uint32_t *tab, bool ledcontrol) {
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
|
||||
|
||||
if (ledcontrol) LED_A_ON();
|
||||
|
||||
|
||||
// rescale the values to match the time of the timer below.
|
||||
for (u = 0; u < 500; ++u) {
|
||||
tab[u] = (tab[u] * 3) / 2;
|
||||
|
@ -651,7 +651,7 @@ bool AddBitPCF7931(bool b, uint32_t *tab, int8_t offsetPulseWidth, int8_t offset
|
|||
|
||||
tab[u + 1] = 6 * T0_PCF + tab[u] + offsetPulseWidth;
|
||||
tab[u + 2] = 88 * T0_PCF + tab[u + 1] - offsetPulseWidth - offsetPulsePosition;
|
||||
|
||||
|
||||
} else { //add a bit 0
|
||||
if (u == 0)
|
||||
tab[u] = 98 * T0_PCF + offsetPulsePosition;
|
||||
|
@ -660,7 +660,7 @@ bool AddBitPCF7931(bool b, uint32_t *tab, int8_t offsetPulseWidth, int8_t offset
|
|||
|
||||
tab[u + 1] = 6 * T0_PCF + tab[u] + offsetPulseWidth;
|
||||
tab[u + 2] = 24 * T0_PCF + tab[u + 1] - offsetPulseWidth - offsetPulsePosition;
|
||||
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
#include "common.h"
|
||||
|
||||
|
||||
typedef enum{
|
||||
typedef enum {
|
||||
FALLING,
|
||||
RISING
|
||||
RISING
|
||||
} EdgeType;
|
||||
|
||||
size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol);
|
||||
|
|
|
@ -102,7 +102,7 @@ local function reanimate_t5577(password)
|
|||
p:console('lf t55 write -b 0 -d 000880E0 --pg1 --r0 -p 00000000')
|
||||
p:console('lf t55 write -b 0 -d 000880E0 --pg1 --r1 -p 00000000')
|
||||
p:console('lf t55 write -b 0 -d 000880E0 --pg1 --r2 -p 00000000')
|
||||
p:console('lf t55 write -b 0 -d 000880E0 --pg1 --r3 -p 00000000')
|
||||
p:console('lf t55 write -b 0 -d 000880E0 --pg1 --r3 -p 00000000')
|
||||
reset_log_file()
|
||||
end
|
||||
|
||||
|
@ -118,7 +118,7 @@ local function main(args)
|
|||
print(dash)
|
||||
print("::: "..ac.cyan.."Hold on, I'm searching for a password in the dictionary"..ac.reset.." :::")
|
||||
print(dash)
|
||||
p:console('lf t55 chk')
|
||||
p:console('lf t55 chk')
|
||||
local log_content = read_log_file(logfile)
|
||||
local password = log_content and extract_password(log_content) or nil
|
||||
reanimate_t5577(password)
|
||||
|
@ -141,4 +141,4 @@ local function main(args)
|
|||
print(dash)
|
||||
end
|
||||
|
||||
main(args)
|
||||
main(args)
|
||||
|
|
|
@ -9,14 +9,14 @@ local command = core.console
|
|||
command('clear')
|
||||
author = ' Author: jareckib - 12.03.2025'
|
||||
version = ' version v1.03'
|
||||
desc = [[
|
||||
desc = [[
|
||||
This simple script stores 1, 2 or 3 different EM4102 on a single T5577.
|
||||
There is an option to enter the number engraved on the fob in decimal form.
|
||||
The script can therefore be useful if the original EM4102 doesn't work but
|
||||
has an engraved ID number. By entering such an ID as a single EM4102, we
|
||||
The script can therefore be useful if the original EM4102 doesn't work but
|
||||
has an engraved ID number. By entering such an ID as a single EM4102, we
|
||||
can create a working copy of our damaged fob.
|
||||
A tag T5577 created in this way works with the following USB readers:
|
||||
|
||||
|
||||
- ACM08Y
|
||||
- ACM26C
|
||||
- Sycreader R60D
|
||||
|
@ -121,7 +121,7 @@ local function get_uid_from_user()
|
|||
while true do
|
||||
print(dash)
|
||||
io.write(ac.cyan .. '(1)' .. ac.reset .. ' Manual entry UID |' .. ac.cyan .. ' (2)' .. ac.reset .. ' Read via Proxmark3 ')
|
||||
|
||||
|
||||
local choice
|
||||
repeat
|
||||
choice = io.read()
|
||||
|
@ -159,7 +159,7 @@ local function get_uid_from_user()
|
|||
io.read()
|
||||
|
||||
while true do
|
||||
reset_log_file()
|
||||
reset_log_file()
|
||||
command('lf em 410x read')
|
||||
local log_content = read_log_file(logfile)
|
||||
local uid = extract_uid(log_content)
|
||||
|
@ -178,7 +178,7 @@ end
|
|||
local function main(args)
|
||||
for o, a in getopt.getopt(args, 'h') do
|
||||
if o == 'h' then return help() end
|
||||
end
|
||||
end
|
||||
local blocks = {}
|
||||
local uid_count = 0
|
||||
|
||||
|
@ -224,4 +224,4 @@ local function main(args)
|
|||
print(ac.green .. "Successfully written " .. uid_count .. " EM4102 UID(s) to T5577" .. ac.reset)
|
||||
end
|
||||
|
||||
main(args)
|
||||
main(args)
|
||||
|
|
|
@ -459,4 +459,4 @@ local function main(args)
|
|||
end
|
||||
end
|
||||
|
||||
main(args)
|
||||
main(args)
|
||||
|
|
|
@ -77,14 +77,14 @@ def parse_config(config: str):
|
|||
cfg_auth_type = config[8:10]
|
||||
cfg_cuid = config[12:14]
|
||||
cfg_memory_config = config[14:16]
|
||||
|
||||
|
||||
log_magic_wup = "Magic wakeup " + ("en" if cfg_magic_wup != "8500" else "dis") + "abled" + (" with config access" if cfg_magic_wup == "7AFF" else "")
|
||||
log_wup_style = "Magic wakeup style " + ("Gen1a 40(7)/43" if cfg_wup_style == "00" else ("GDM 20(7)/23" if cfg_wup_style == "85" else "unknown"))
|
||||
log_regular_available = "Config " + ("" if cfg_regular_available == "A0" else "un") + "available in regular mode"
|
||||
log_auth_type = "Auth type " + ("1B - PWD" if cfg_auth_type == "00" else "1A - 3DES")
|
||||
log_cuid = "CUID " + ("dis" if cfg_cuid == "A0" else "en") + "abled"
|
||||
log_memory_config = "Maximum memory configuration: " + (MEMORY_CONFIG[cfg_memory_config] if cfg_memory_config in MEMORY_CONFIG.keys() else "unknown")
|
||||
|
||||
|
||||
print(SUCCESS + "^^^^............................ " + log_magic_wup)
|
||||
print(SUCCESS + "....^^.......................... " + log_wup_style)
|
||||
print(SUCCESS + "......^^........................ " + log_regular_available)
|
||||
|
@ -93,7 +93,7 @@ def parse_config(config: str):
|
|||
print(SUCCESS + "............^^.................. " + log_cuid)
|
||||
print(SUCCESS + "..............^^................ " + log_memory_config)
|
||||
print(SUCCESS + "................^^^^^^^^^^^^^^^^ version info")
|
||||
|
||||
|
||||
def try_auth_magic(enforced = False):
|
||||
if enforced and not (gen1a | alt):
|
||||
print(ERROR + "Magic wakeup required. Please select one.")
|
||||
|
@ -158,7 +158,7 @@ elif write_backdoor != None:
|
|||
if len(data) % 8 != 0:
|
||||
print(ERROR + "Data must be a multiple of 4 bytes.")
|
||||
exit()
|
||||
|
||||
|
||||
try_auth_magic(True)
|
||||
for i in range(len(data) // 8):
|
||||
p.console("hf 14a raw -" + ("k" if i != (len(data) // 8 - 1) else "") + f"c A2{(write_backdoor_num + i):02x}{data[8*i:8*i+8]}", False, False)
|
||||
|
@ -171,13 +171,13 @@ elif uid != None:
|
|||
p.console(f"hf 14a raw -kc" + ("s" if not (gen1a or alt) else "") + " 3002")
|
||||
block_2 = p.grabbed_output.split("\n")[-2][4:-9].replace(" ", "")[:8]
|
||||
uid_bytes = [int(uid[2*x:2*x+2], 16) for x in range(7)]
|
||||
|
||||
|
||||
bcc_0 = 0x88 ^ uid_bytes[0] ^ uid_bytes[1] ^ uid_bytes[2]
|
||||
new_block_0 = ""
|
||||
for i in range(3):
|
||||
new_block_0 += f"{uid_bytes[i]:02x}"
|
||||
new_block_0 += f"{bcc_0:02x}"
|
||||
|
||||
|
||||
bcc_1 = uid_bytes[3] ^ uid_bytes[4] ^ uid_bytes[5] ^ uid_bytes[6]
|
||||
new_block_1 = uid[6:]
|
||||
new_block_2 = f"{bcc_1:02x}" + block_2[2:]
|
||||
|
|
|
@ -42,7 +42,7 @@ typedef struct _em4x70_tag_info_t {
|
|||
/// * UM2 does not exist on the tag
|
||||
/// * Pin does not exist on the tag
|
||||
/// * UM1 (including the lock bits) might be one-time programmable (OTP)
|
||||
///
|
||||
///
|
||||
/// [31] == Block 15 MSB == UM2₆₃..UM2₅₆
|
||||
/// [30] == Block 15 LSB == UM2₅₅..UM2₄₈
|
||||
/// [29] == Block 14 MSB == UM2₄₇..UM2₄₀
|
||||
|
|
|
@ -186,6 +186,7 @@ static void fill_grabber(const char *string) {
|
|||
g_grabbed_output.ptr = tmp;
|
||||
g_grabbed_output.size += MAX_PRINT_BUFFER;
|
||||
}
|
||||
|
||||
int len = snprintf(g_grabbed_output.ptr + g_grabbed_output.idx, MAX_PRINT_BUFFER, "%s", string);
|
||||
if (len < 0 || len > MAX_PRINT_BUFFER) {
|
||||
// We leave current g_grabbed_output_len untouched
|
||||
|
@ -196,24 +197,34 @@ static void fill_grabber(const char *string) {
|
|||
}
|
||||
|
||||
void PrintAndLogOptions(const char *str[][2], size_t size, size_t space) {
|
||||
|
||||
char buff[2000] = "Options:\n";
|
||||
char format[2000] = "";
|
||||
size_t counts[2] = {0, 0};
|
||||
for (size_t i = 0; i < size; i++)
|
||||
for (size_t j = 0 ; j < 2 ; j++)
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
for (size_t j = 0 ; j < 2 ; j++) {
|
||||
if (counts[j] < strlen(str[i][j])) {
|
||||
counts[j] = strlen(str[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
|
||||
for (size_t j = 0; j < 2; j++) {
|
||||
if (j == 0)
|
||||
if (j == 0) {
|
||||
snprintf(format, sizeof(format), "%%%zus%%%zus", space, counts[j]);
|
||||
else
|
||||
} else {
|
||||
snprintf(format, sizeof(format), "%%%zus%%-%zus", space, counts[j]);
|
||||
}
|
||||
|
||||
snprintf(buff + strlen(buff), sizeof(buff) - strlen(buff), format, " ", str[i][j]);
|
||||
}
|
||||
if (i < size - 1)
|
||||
|
||||
if (i < size - 1) {
|
||||
strncat(buff, "\n", sizeof(buff) - strlen(buff) - 1);
|
||||
}
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "%s", buff);
|
||||
}
|
||||
|
@ -223,12 +234,14 @@ static uint8_t PrintAndLogEx_spinidx = 0;
|
|||
void PrintAndLogEx(logLevel_t level, const char *fmt, ...) {
|
||||
|
||||
// skip debug messages if client debugging is turned off i.e. 'DATA SETDEBUG -0'
|
||||
if (g_debugMode == 0 && level == DEBUG)
|
||||
if (g_debugMode == 0 && level == DEBUG) {
|
||||
return;
|
||||
}
|
||||
|
||||
// skip HINT messages if client has hints turned off i.e. 'HINT 0'
|
||||
if (g_session.show_hints == false && level == HINT)
|
||||
if (g_session.show_hints == false && level == HINT) {
|
||||
return;
|
||||
}
|
||||
|
||||
char prefix[40] = {0};
|
||||
char buffer[MAX_PRINT_BUFFER] = {0};
|
||||
|
@ -242,17 +255,19 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) {
|
|||
};
|
||||
switch (level) {
|
||||
case ERR:
|
||||
if (g_session.emoji_mode == EMO_EMOJI)
|
||||
if (g_session.emoji_mode == EMO_EMOJI) {
|
||||
strncpy(prefix, "[" _RED_("!!") "] :rotating_light: ", sizeof(prefix) - 1);
|
||||
else
|
||||
} else {
|
||||
strncpy(prefix, "[" _RED_("!!") "] ", sizeof(prefix) - 1);
|
||||
}
|
||||
stream = stderr;
|
||||
break;
|
||||
case FAILED:
|
||||
if (g_session.emoji_mode == EMO_EMOJI)
|
||||
if (g_session.emoji_mode == EMO_EMOJI) {
|
||||
strncpy(prefix, "[" _RED_("-") "] :no_entry: ", sizeof(prefix) - 1);
|
||||
else
|
||||
} else {
|
||||
strncpy(prefix, "[" _RED_("-") "] ", sizeof(prefix) - 1);
|
||||
}
|
||||
break;
|
||||
case DEBUG:
|
||||
strncpy(prefix, "[" _BLUE_("#") "] ", sizeof(prefix) - 1);
|
||||
|
@ -264,10 +279,11 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) {
|
|||
strncpy(prefix, "[" _GREEN_("+") "] ", sizeof(prefix) - 1);
|
||||
break;
|
||||
case WARNING:
|
||||
if (g_session.emoji_mode == EMO_EMOJI)
|
||||
if (g_session.emoji_mode == EMO_EMOJI) {
|
||||
strncpy(prefix, "[" _CYAN_("!") "] :warning: ", sizeof(prefix) - 1);
|
||||
else
|
||||
} else {
|
||||
strncpy(prefix, "[" _CYAN_("!") "] ", sizeof(prefix) - 1);
|
||||
}
|
||||
break;
|
||||
case INFO:
|
||||
strncpy(prefix, "[" _YELLOW_("=") "] ", sizeof(prefix) - 1);
|
||||
|
@ -276,13 +292,15 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) {
|
|||
if (g_session.emoji_mode == EMO_EMOJI) {
|
||||
strncpy(prefix, spinner_emoji[PrintAndLogEx_spinidx], sizeof(prefix) - 1);
|
||||
PrintAndLogEx_spinidx++;
|
||||
if (PrintAndLogEx_spinidx >= ARRAYLEN(spinner_emoji))
|
||||
if (PrintAndLogEx_spinidx >= ARRAYLEN(spinner_emoji)) {
|
||||
PrintAndLogEx_spinidx = 0;
|
||||
}
|
||||
} else {
|
||||
strncpy(prefix, spinner[PrintAndLogEx_spinidx], sizeof(prefix) - 1);
|
||||
PrintAndLogEx_spinidx++;
|
||||
if (PrintAndLogEx_spinidx >= ARRAYLEN(spinner))
|
||||
if (PrintAndLogEx_spinidx >= ARRAYLEN(spinner)) {
|
||||
PrintAndLogEx_spinidx = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NORMAL:
|
||||
|
@ -306,8 +324,9 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) {
|
|||
const char delim[2] = "\n";
|
||||
|
||||
// line starts with newline
|
||||
if (buffer[0] == '\n')
|
||||
if (buffer[0] == '\n') {
|
||||
fPrintAndLog(stream, "");
|
||||
}
|
||||
|
||||
token = strtok_r(buffer, delim, &tmp_ptr);
|
||||
|
||||
|
@ -315,16 +334,21 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) {
|
|||
|
||||
size_t size = strlen(buffer2);
|
||||
|
||||
if (strlen(token))
|
||||
if (strlen(token)) {
|
||||
snprintf(buffer2 + size, sizeof(buffer2) - size, "%s%s\n", prefix, token);
|
||||
else
|
||||
} else {
|
||||
snprintf(buffer2 + size, sizeof(buffer2) - size, "\n");
|
||||
}
|
||||
|
||||
token = strtok_r(NULL, delim, &tmp_ptr);
|
||||
}
|
||||
|
||||
fPrintAndLog(stream, "%s", buffer2);
|
||||
|
||||
} else {
|
||||
|
||||
snprintf(buffer2, sizeof(buffer2), "%s%s", prefix, buffer);
|
||||
|
||||
if (level == INPLACE) {
|
||||
// ignore INPLACE if rest of output is grabbed
|
||||
if (!(g_printAndLog & PRINTANDLOG_GRAB)) {
|
||||
|
@ -354,6 +378,7 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
|
|||
if (logging && g_session.incognito) {
|
||||
logging = 0;
|
||||
}
|
||||
|
||||
if ((g_printAndLog & PRINTANDLOG_LOG) && logging && !logfile) {
|
||||
char *my_logfile_path = NULL;
|
||||
char filename[40];
|
||||
|
@ -361,11 +386,15 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
|
|||
time_t now = time(NULL);
|
||||
timenow = gmtime(&now);
|
||||
strftime(filename, sizeof(filename), PROXLOG, timenow);
|
||||
|
||||
if (searchHomeFilePath(&my_logfile_path, LOGS_SUBDIR, filename, true) != PM3_SUCCESS) {
|
||||
|
||||
printf(_YELLOW_("[-]") " Logging disabled!\n");
|
||||
my_logfile_path = NULL;
|
||||
logging = 0;
|
||||
|
||||
} else {
|
||||
|
||||
logfile = fopen(my_logfile_path, "a");
|
||||
if (logfile == NULL) {
|
||||
printf(_YELLOW_("[-]") " Can't open logfile %s, logging disabled!\n", my_logfile_path);
|
||||
|
@ -411,13 +440,16 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
|
|||
linefeed = false;
|
||||
buffer[strlen(buffer) - 1] = 0;
|
||||
}
|
||||
|
||||
bool filter_ansi = !g_session.supports_colors;
|
||||
memcpy_filter_ansi(buffer2, buffer, sizeof(buffer), filter_ansi);
|
||||
if (g_printAndLog & PRINTANDLOG_PRINT) {
|
||||
|
||||
if ((g_printAndLog & PRINTANDLOG_PRINT) == PRINTANDLOG_PRINT) {
|
||||
memcpy_filter_emoji(buffer3, buffer2, sizeof(buffer2), g_session.emoji_mode);
|
||||
fprintf(stream, "%s", buffer3);
|
||||
if (linefeed)
|
||||
if (linefeed) {
|
||||
fprintf(stream, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RL_STATE_READCMD
|
||||
|
@ -433,33 +465,44 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
|
|||
|
||||
if (((g_printAndLog & PRINTANDLOG_LOG) && logging && logfile) ||
|
||||
(g_printAndLog & PRINTANDLOG_GRAB)) {
|
||||
|
||||
memcpy_filter_emoji(buffer3, buffer2, sizeof(buffer2), EMO_ALTTEXT);
|
||||
|
||||
if (filter_ansi == false) {
|
||||
memcpy_filter_ansi(buffer, buffer3, sizeof(buffer3), true);
|
||||
}
|
||||
}
|
||||
|
||||
if ((g_printAndLog & PRINTANDLOG_LOG) && logging && logfile) {
|
||||
|
||||
if (filter_ansi) {
|
||||
fprintf(logfile, "%s", buffer3);
|
||||
} else {
|
||||
fprintf(logfile, "%s", buffer);
|
||||
}
|
||||
if (linefeed)
|
||||
|
||||
if (linefeed) {
|
||||
fprintf(logfile, "\n");
|
||||
}
|
||||
fflush(logfile);
|
||||
}
|
||||
|
||||
if (g_printAndLog & PRINTANDLOG_GRAB) {
|
||||
|
||||
if (filter_ansi) {
|
||||
fill_grabber(buffer3);
|
||||
} else {
|
||||
fill_grabber(buffer);
|
||||
}
|
||||
if (linefeed)
|
||||
|
||||
if (linefeed) {
|
||||
fill_grabber("\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (flushAfterWrite)
|
||||
if (flushAfterWrite) {
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
//release lock
|
||||
pthread_mutex_unlock(&g_print_lock);
|
||||
|
@ -478,9 +521,10 @@ void memcpy_filter_rlmarkers(void *dest, const void *src, size_t n) {
|
|||
uint8_t *rsrc = (uint8_t *)src;
|
||||
uint16_t si = 0;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if ((rsrc[i] == '\001') || (rsrc[i] == '\002'))
|
||||
if ((rsrc[i] == '\001') || (rsrc[i] == '\002')) {
|
||||
// skip readline special markers
|
||||
continue;
|
||||
}
|
||||
rdest[si++] = rsrc[i];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5047,7 +5047,7 @@
|
|||
"-v, --verbose verbose output",
|
||||
"-f, --file <fn> Specify a filename for dump file",
|
||||
"--emu from emulator memory",
|
||||
"--start <dec> index of block to start writing (default 0)",
|
||||
"--start <dec> index of block to start writing (def 0)",
|
||||
"--end <dec> index of block to end writing (default last block)"
|
||||
],
|
||||
"usage": "hf mf gload [-hv] [--mini] [--1k] [--1k+] [--2k] [--4k] [-p <hex>] [-f <fn>] [--emu] [--start <dec>] [--end <dec>]"
|
||||
|
@ -10992,8 +10992,8 @@
|
|||
"-r, --reset Reset configuration to default values",
|
||||
"-p, --pwd <hex> Password, 7bytes, LSB-order",
|
||||
"-d, --delay <dec> Tag initialization delay (in us)",
|
||||
"--lw <dec> offset, low pulses width (in us)",
|
||||
"--lp <dec> offset, low pulses position (in us)"
|
||||
"--lw <dec> offset, low pulses width (in us), optional!",
|
||||
"--lp <dec> offset, low pulses position (in us), optional!"
|
||||
],
|
||||
"usage": "lf pcf7931 config [-hr] [-p <hex>] [-d <dec>] [--lw <dec>] [--lp <dec>]"
|
||||
},
|
||||
|
@ -13232,6 +13232,6 @@
|
|||
"metadata": {
|
||||
"commands_extracted": 760,
|
||||
"extracted_by": "PM3Help2JSON v1.00",
|
||||
"extracted_on": "2025-03-12T15:46:33"
|
||||
"extracted_on": "2025-03-18T06:54:58"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue