Merge branch 'master' into master

Signed-off-by: Angel <jeremy_1996@hotmail.com>
This commit is contained in:
Angel
2023-06-04 11:39:45 -04:00
committed by GitHub
36 changed files with 724 additions and 269 deletions
+8 -3
View File
@@ -3,6 +3,10 @@ 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]
- Fixed truncated FPGA upload due to incorrect integer size variable (@d18c7db)
- Changed `usart btfactory` - handles the new BT board with version "BT SPP V3.0" (@iceman1001)
- Changed `hf mf eview --sk` - now can extract keys and save to file (@iceman1001)
- Changed `hf mf view --sk` - now can extract keys and save to file (@iceman1001)
- Changed `hf mf sim` - reduce 6ms threshold to 4ms for reset to idle #1974 (@net147)
- Rebuilt the Spartan-2 `fpga_*.bit` files to include the `hi_iso14443a.v` update (@d18c7db)
- Added minor orphaned change from `hi_iso14443a.v` in `fpga-xc3s100e` to `hi_iso14443a.v` in `fpga-xc2s30` (@d18c7db)
@@ -22,7 +26,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Changed `hf mf supercard` - Support editing UID and recovery of keys from second generation card (@AloneLiberty)
- Added iClass credit key to default iClass key table and reorganized key order (@GuruSteve)
- Changed `hf mf value` - ability to use transfer on different block (@AloneLiberty)
- Change `hf mf dump --ns` - dump command now supports `no save` of MFC card memory (@iceman1001)
- Changed `hf mf dump --ns` - dump command now supports `no save` of MFC card memory (@iceman1001)
- Added `hf mf gdmsetcfg` - Supprt Gen4 GDM write configuration block (@iceman1001)
- Added `hf mf gdmcfg` - Support Gen4 GDM read configuration block (@iceman1001)
- Changed magic note to include a section about GDM tags (@iceman1001)
@@ -62,13 +66,14 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added `hf legic info` command for other sources (@0xdeb)
- Added `hf legic einfo` - views emulator menory (@0xdeb)
- Changed `hf legic view` - now also print the decoded info of the dump file (@0xdeb)
- Now `script run hf_mf_ultimatecard.lua -u` supports 10bytes UID (@alejandro12120)
- Update documentation for installation on macOS with MacPorts (@linuxgemini)
- Changed `script run hf_mf_ultimatecard.lua -u` to support 10bytes UID (@alejandro12120)
- Updated documentation for installation on macOS with MacPorts (@linuxgemini)
- Added possible Paxton id to hitag2 tag info output
- Changed `hf mf sim` - reduce 50ms threshold to 6ms for reset to idle #1974 (@net147)
- Update `amiibo_tools.lua` with new identifiers and create a python script `update_amiibo_tools_lua.py` to automate the process in the future. (@CorySolovewicz)
- Added `lf paradox sim --fc --cn` - Simulates Paradox fob from facility code and card number (jerji)
## [Nitride.4.16191][2023-01-29]
- Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox)
- Fixed some coverity fixes (@iceman1001)
+1 -1
View File
@@ -77,7 +77,7 @@ else
endif
ifneq (,$(findstring WITH_EM4x50,$(APP_CFLAGS)))
SRC_EM4x50 = em4x50.c
SRC_EM4x50 = em4x50.c bruteforce.c
else
SRC_EM4x50 =
endif
+19 -3
View File
@@ -2014,11 +2014,16 @@ static void PacketReceived(PacketCommandNG *packet) {
uint32_t waittime;
} PACKED;
struct p *payload = (struct p *) &packet->data.asBytes;
uint16_t available;
uint16_t pre_available = 0;
uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
uint32_t wait = payload->waittime;
StartTicks();
uint32_t ti = GetTickCount();
while (true) {
WaitMS(50);
available = usart_rxdata_available();
@@ -2039,6 +2044,8 @@ static void PacketReceived(PacketCommandNG *packet) {
} else {
reply_ng(CMD_USART_RX, PM3_ENODATA, NULL, 0);
}
StopTicks();
BigBuf_free();
LED_B_OFF();
break;
@@ -2051,11 +2058,16 @@ static void PacketReceived(PacketCommandNG *packet) {
} PACKED;
struct p *payload = (struct p *) &packet->data.asBytes;
usart_writebuffer_sync(payload->data, packet->length - sizeof(payload));
uint16_t available;
uint16_t pre_available = 0;
uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
uint32_t wait = payload->waittime;
StartTicks();
uint32_t ti = GetTickCount();
while (true) {
WaitMS(50);
available = usart_rxdata_available();
@@ -2070,12 +2082,15 @@ static void PacketReceived(PacketCommandNG *packet) {
if (GetTickCountDelta(ti) > wait)
break;
}
if (available > 0) {
uint16_t len = usart_read_ng(dest, available);
reply_ng(CMD_USART_TXRX, PM3_SUCCESS, dest, len);
} else {
reply_ng(CMD_USART_TXRX, PM3_ENODATA, NULL, 0);
}
StopTicks();
BigBuf_free();
LED_B_OFF();
break;
@@ -2718,9 +2733,6 @@ void __attribute__((noreturn)) AppMain(void) {
}
#endif
#ifdef WITH_FPC_USART
usart_init(USART_BAUD_RATE, USART_PARITY);
#endif
#ifdef WITH_FLASH
// If flash is not present, BUSY_TIMEOUT kicks in, let's do it after USB
@@ -2733,6 +2745,10 @@ void __attribute__((noreturn)) AppMain(void) {
rdv40_spiffs_check();
#endif
#ifdef WITH_FPC_USART
usart_init(USART_BAUD_RATE, USART_PARITY);
#endif
// This is made as late as possible to ensure enumeration without timeout
// against device such as http://www.hobbytronics.co.uk/usb-host-board-v2
// In other words, keep the interval between usb_enable() and the main loop as short as possible.
+15 -5
View File
@@ -27,6 +27,7 @@
#include "BigBuf.h"
#include "spiffs.h"
#include "appmain.h" // tear
#include "bruteforce.h"
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
@@ -632,12 +633,21 @@ static int login(uint32_t password) {
return PM3_EFAILED;
}
// searching for password in given range
static bool brute(uint32_t start, uint32_t stop, uint32_t *pwd) {
// searching for password using chosen bruteforce algorithm
static bool brute(em4x50_data_t *etd, uint32_t *pwd) {
generator_context_t ctx;
bool pwd_found = false;
int generator_ret = 0;
int cnt = 0;
for (*pwd = start; *pwd <= stop; (*pwd)++) {
bf_generator_init(&ctx, etd->bruteforce_mode);
if (etd->bruteforce_mode == BRUTEFORCE_MODE_CHARSET)
bf_generator_set_charset(&ctx, etd->bruteforce_charset);
while ((generator_ret = bf_generate32(&ctx)) == GENERATOR_NEXT) {
*pwd = ctx.current_key32;
WDT_HIT();
@@ -702,7 +712,7 @@ void em4x50_login(uint32_t *password, bool ledcontrol) {
reply_ng(CMD_LF_EM4X50_LOGIN, status, NULL, 0);
}
// envoke password search
// invoke password search
void em4x50_brute(em4x50_data_t *etd, bool ledcontrol) {
em4x50_setup_read();
@@ -714,7 +724,7 @@ void em4x50_brute(em4x50_data_t *etd, bool ledcontrol) {
LED_C_OFF();
LED_D_ON();
}
bsuccess = brute(etd->password1, etd->password2, &pwd);
bsuccess = brute(etd, &pwd);
}
if (ledcontrol) LEDsoff();
+2 -2
View File
@@ -393,7 +393,7 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
while (numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) {
char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
numbytes++;
uint16_t current_length = 0;
uint32_t current_length = 0;
if (current_name < 'a' || current_name > 'e') {
/* Strange section name, abort */
break;
@@ -423,7 +423,7 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
break;
}
for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) {
for (uint32_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) {
get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
numbytes++;
}
+32 -20
View File
@@ -46,8 +46,8 @@ void usart_close(void) {
}
*/
static uint8_t us_inbuf1[USART_BUFFLEN];
static uint8_t us_inbuf2[USART_BUFFLEN];
static uint8_t us_in_a[USART_BUFFLEN];
static uint8_t us_in_b[USART_BUFFLEN];
static uint8_t *usart_cur_inbuf = NULL;
static uint16_t usart_cur_inbuf_off = 0;
static uint8_t us_rxfifo[USART_FIFOLEN];
@@ -56,7 +56,9 @@ static size_t us_rxfifo_high = 0;
static void usart_fill_rxfifo(void) {
uint16_t rxfifo_free ;
uint16_t rxfifo_free = 0;
if (pUS1->US_RNCR == 0) { // One buffer got filled, backup buffer being used
if (us_rxfifo_low > us_rxfifo_high)
@@ -79,19 +81,22 @@ static void usart_fill_rxfifo(void) {
pUS1->US_RNCR = USART_BUFFLEN;
// Swap current buff
if (usart_cur_inbuf == us_inbuf1)
usart_cur_inbuf = us_inbuf2;
if (usart_cur_inbuf == us_in_a)
usart_cur_inbuf = us_in_b;
else
usart_cur_inbuf = us_inbuf1;
usart_cur_inbuf = us_in_a;
usart_cur_inbuf_off = 0;
} else {
// Take only what we have room for
available = rxfifo_free;
for (uint16_t i = 0; i < available; i++) {
us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i];
if (us_rxfifo_high == sizeof(us_rxfifo))
if (us_rxfifo_high == sizeof(us_rxfifo)) {
us_rxfifo_high = 0;
}
}
usart_cur_inbuf_off += available;
return;
@@ -101,18 +106,20 @@ static void usart_fill_rxfifo(void) {
if (pUS1->US_RCR < USART_BUFFLEN - usart_cur_inbuf_off) { // Current buffer partially filled
if (us_rxfifo_low > us_rxfifo_high)
rxfifo_free = us_rxfifo_low - us_rxfifo_high;
rxfifo_free = (us_rxfifo_low - us_rxfifo_high);
else
rxfifo_free = sizeof(us_rxfifo) - us_rxfifo_high + us_rxfifo_low;
rxfifo_free = (sizeof(us_rxfifo) - us_rxfifo_high + us_rxfifo_low);
uint16_t available = USART_BUFFLEN - pUS1->US_RCR - usart_cur_inbuf_off;
uint16_t available = (USART_BUFFLEN - pUS1->US_RCR - usart_cur_inbuf_off);
if (available > rxfifo_free)
available = rxfifo_free;
for (uint16_t i = 0; i < available; i++) {
us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i];
if (us_rxfifo_high == sizeof(us_rxfifo))
if (us_rxfifo_high == sizeof(us_rxfifo)) {
us_rxfifo_high = 0;
}
}
usart_cur_inbuf_off += available;
}
@@ -121,9 +128,9 @@ static void usart_fill_rxfifo(void) {
uint16_t usart_rxdata_available(void) {
usart_fill_rxfifo();
if (us_rxfifo_low <= us_rxfifo_high)
return us_rxfifo_high - us_rxfifo_low;
return (us_rxfifo_high - us_rxfifo_low);
else
return sizeof(us_rxfifo) - us_rxfifo_low + us_rxfifo_high;
return (sizeof(us_rxfifo) - us_rxfifo_low + us_rxfifo_high);
}
uint32_t usart_read_ng(uint8_t *data, size_t len) {
@@ -143,9 +150,10 @@ uint32_t usart_read_ng(uint8_t *data, size_t len) {
uint32_t maxtry = 10 * (3000000 / USART_BAUD_RATE) + tryconstant;
while (len) {
uint32_t available = usart_rxdata_available();
uint32_t available = usart_rxdata_available();
uint32_t packetSize = MIN(available, len);
if (available > 0) {
// Dbprintf_usb("Dbg USART ask %d bytes, available %d bytes, packetsize %d bytes", len, available, packetSize);
// highest_observed_try = MAX(highest_observed_try, try);
@@ -153,8 +161,9 @@ uint32_t usart_read_ng(uint8_t *data, size_t len) {
}
len -= packetSize;
while (packetSize--) {
if (us_rxfifo_low == sizeof(us_rxfifo))
if (us_rxfifo_low == sizeof(us_rxfifo)) {
us_rxfifo_low = 0;
}
data[bytes_rcv++] = us_rxfifo[us_rxfifo_low++];
}
if (try++ == maxtry) {
@@ -183,10 +192,13 @@ int usart_writebuffer_sync(uint8_t *data, size_t len) {
void usart_init(uint32_t baudrate, uint8_t parity) {
if (baudrate != 0)
if (baudrate != 0) {
g_usart_baudrate = baudrate;
if ((parity == 'N') || (parity == 'O') || (parity == 'E'))
}
if ((parity == 'N') || (parity == 'O') || (parity == 'E')) {
g_usart_parity = parity;
}
// For a nice detailed sample, interrupt driven but still relevant.
// See https://www.sparkfun.com/datasheets/DevTools/SAM7/at91sam7%20serial%20communications.pdf
@@ -262,11 +274,11 @@ void usart_init(uint32_t baudrate, uint8_t parity) {
pUS1->US_TCR = 0;
pUS1->US_TNPR = (uint32_t)0;
pUS1->US_TNCR = 0;
pUS1->US_RPR = (uint32_t)us_inbuf1;
pUS1->US_RPR = (uint32_t)us_in_a;
pUS1->US_RCR = USART_BUFFLEN;
usart_cur_inbuf = us_inbuf1;
usart_cur_inbuf = us_in_a;
usart_cur_inbuf_off = 0;
pUS1->US_RNPR = (uint32_t)us_inbuf2;
pUS1->US_RNPR = (uint32_t)us_in_b;
pUS1->US_RNCR = USART_BUFFLEN;
// Initialize our fifo
+11
View File
@@ -586,6 +586,17 @@ if (MINGW)
set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}")
# GCC 10 has issues with false positives on stringop-overflow,
# let's disable them for now (cf https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92955, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94335)
# beware these flags didn't exist for GCC < 7
if(CMAKE_COMPILER_IS_GNUCXX)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
if (GCC_VERSION VERSION_GREATER 10.0 OR GCC_VERSION VERSION_EQUAL 10.0)
set(CMAKE_C_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_CXX_FLAGS}")
endif()
endif(CMAKE_COMPILER_IS_GNUCXX)
# link Winsock2
set(ADDITIONAL_LNK ws2_32 ${ADDITIONAL_LNK})
endif (MINGW)
@@ -182,7 +182,7 @@ crack_states_thread(void *x) {
} else {
if (!thread_arg->silent) {
char progress_text[80];
snprintf(progress_text, sizeof(progress_text), "Brute force phase: %6.02f%%\t", 100.0 * (float)num_keys_tested / (float)(thread_arg->maximum_states));
snprintf(progress_text, sizeof(progress_text), "Brute force phase: %6.02f%% ", 100.0 * (float)num_keys_tested / (float)(thread_arg->maximum_states));
float remaining_bruteforce = thread_arg->nonces[thread_arg->best_first_bytes[0]].expected_num_brute_force - (float)num_keys_tested / 2;
hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, remaining_bruteforce, 5000);
}
+28 -15
View File
@@ -18,6 +18,19 @@ A5A4A3A2A1A0
# MAD access key B
89ECA97F8C2A
#
# Mifare 1k EV1 (S50) hidden blocks, Signature data
# 16 A
5C8FF9990DA2
#
# 17 A
75CCB59C9BED
#
# 16 B
D01AFEEB890A
#
# 17 B
4B791BEA7BCC
#
#
B0B1B2B3B4B5
C0C1C2C3C4C5
@@ -111,7 +124,7 @@ F1D83F964314
# Access control system
605F5E5D5C5B
#
#NSP Global keys A and B (uk housing access control)
# NSP Global keys A and B (uk housing access control)
199404281970
199404281998
#
@@ -263,16 +276,25 @@ E3429281EFC1
460722122510
#
# 3dprinter
# EPI Envisionte# 3dprinter
# EPI Envisionte
AAFB06045877
#
# gym
#
# Fysiken A
3E65E4FB65B3
#
# Fysiken B
25094DF6F148
#
#
# https://mattionline.de/fitnessstudio-armband-reverse-engineering/
# https://mattionline.de/milazycracker/
# gym wistband A, same as Fysiken A
# gym wistband B
81CC25EBBB6A
195DC63DB3A3
#
# CleverFit
A05DBD98E0FC
#
@@ -280,6 +302,10 @@ A05DBD98E0FC
AA4DDA458EBB
EAB8066C7479
#
# Nordic Wellness A, same as Fysiken A
# Nordic Wellness B
E5519E1CC92B
#
# Hotel KeyCard
D3B595E9DD63
AFBECD121004
@@ -626,19 +652,6 @@ A8844B0BCA06
564C505F4D41
BA5B895DA162
#
# Vigik mystery Keys Mifare 1k EV1 (S50)
# 16 A
5C8FF9990DA2
#
# 17 A
75CCB59C9BED
#
# 16 B
D01AFEEB890A
#
# 17 B
4B791BEA7BCC
#
# BTCINO UNDETERMINED SPREAKD 0x01->0x13 key
021209197591
#
+12
View File
@@ -585,6 +585,18 @@ if (MINGW)
set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}")
# GCC 10 has issues with false positives on stringop-overflow,
# let's disable them for now (cf https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92955, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94335)
# beware these flags didn't exist for GCC < 7
if(CMAKE_COMPILER_IS_GNUCXX)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
if (GCC_VERSION VERSION_GREATER 10.0 OR GCC_VERSION VERSION_EQUAL 10.0)
set(CMAKE_C_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-Wno-stringop-overflow -Wno-error=stringop-overflow ${CMAKE_CXX_FLAGS}")
endif()
endif(CMAKE_COMPILER_IS_GNUCXX)
endif (MINGW)
target_include_directories(pm3rrg_rdv4 PRIVATE
+16
View File
@@ -367,5 +367,21 @@
"Name": "University of Ljubljana Student ID",
"Description": "",
"Type": "student"
},
{
"AID": "27E178",
"Vendor": "Disney",
"Country": "US",
"Name": "Disney MagicBand",
"Description": "",
"Type": "payment system"
},
{
"AID": "44434C",
"Vendor": "Disney",
"Country": "US",
"Name": "Disney MagicBand",
"Description": "AID found on MagicBand desfire cards",
"Type": "payment system"
}
]
+2 -2
View File
@@ -531,7 +531,7 @@ static int CmdFlashMemSpiFFSView(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_str1("f", "file", "<fn>", "SPIFFS file to view"),
arg_int0("c", "cols", "<dec>", "column breaks (def 32)"),
arg_int0("c", "cols", "<dec>", "column breaks (def 16)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@@ -540,7 +540,7 @@ static int CmdFlashMemSpiFFSView(const char *Cmd) {
char fn[32] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)fn, 32, &fnlen);
int breaks = arg_get_int_def(ctx, 2, 32);
int breaks = arg_get_int_def(ctx, 2, 16);
CLIParserFree(ctx);
uint8_t *dump = NULL;
+186 -150
View File
File diff suppressed because it is too large Load Diff
+27 -8
View File
@@ -34,7 +34,6 @@
#include "commonutil.h" // ARRAYLEN
#include "comms.h"
#include "proxmark3.h"
#include "ui.h"
#include "util_posix.h"
@@ -48,7 +47,8 @@
#define NUM_CHECK_BITFLIPS_THREADS (num_CPUs())
#define NUM_REDUCTION_WORKING_THREADS (num_CPUs())
#define IGNORE_BITFLIP_THRESHOLD 0.99 // ignore bitflip arrays which have nearly only valid states
// ignore bitflip arrays which have nearly only valid states
#define IGNORE_BITFLIP_THRESHOLD 0.9901
#define STATE_FILES_DIRECTORY "hardnested_tables/"
#define STATE_FILE_TEMPLATE "bitflip_%d_%03" PRIx16 "_states.bin.bz2"
@@ -57,7 +57,11 @@
// #define DEBUG_REDUCTION
// possible sum property values
static uint16_t sums[NUM_SUMS] = {0, 32, 56, 64, 80, 96, 104, 112, 120, 128, 136, 144, 152, 160, 176, 192, 200, 224, 256};
static uint16_t sums[NUM_SUMS] = {
0, 32, 56, 64, 80, 96, 104, 112,
120, 128, 136, 144, 152, 160, 176, 192,
200, 224, 256
};
// number of possible partial sum property values
#define NUM_PART_SUMS 9
@@ -505,8 +509,11 @@ static void free_sum_bitarrays(void) {
static char failstr[250] = "";
#endif
static const float p_K0[NUM_SUMS] = { // the probability that a random nonce has a Sum Property K
0.0290, 0.0083, 0.0006, 0.0339, 0.0048, 0.0934, 0.0119, 0.0489, 0.0602, 0.4180, 0.0602, 0.0489, 0.0119, 0.0934, 0.0048, 0.0339, 0.0006, 0.0083, 0.0290
// the probability that a random nonce has a Sum Property K
static const float p_K0[NUM_SUMS] = {
0.0290, 0.0083, 0.0006, 0.0339, 0.0048, 0.0934, 0.0119, 0.0489,
0.0602, 0.4180, 0.0602, 0.0489, 0.0119, 0.0934, 0.0048, 0.0339,
0.0006, 0.0083, 0.0290
};
static float my_p_K[NUM_SUMS];
static const float *p_K;
@@ -1275,6 +1282,7 @@ static void apply_sum_a0(void) {
}
static void simulate_MFplus_RNG(uint32_t test_cuid, uint64_t test_key, uint32_t *nt_enc, uint8_t *par_enc) {
struct Crypto1State sim_cs = {0, 0};
// init cryptostate with key:
@@ -1285,12 +1293,20 @@ static void simulate_MFplus_RNG(uint32_t test_cuid, uint64_t test_key, uint32_t
*par_enc = 0;
uint32_t nt = (rand() & 0xff) << 24 | (rand() & 0xff) << 16 | (rand() & 0xff) << 8 | (rand() & 0xff);
for (int8_t byte_pos = 3; byte_pos >= 0; byte_pos--) {
uint8_t nt_byte_dec = (nt >> (8 * byte_pos)) & 0xff;
uint8_t nt_byte_enc = crypto1_byte(&sim_cs, nt_byte_dec ^ (test_cuid >> (8 * byte_pos)), false) ^ nt_byte_dec; // encode the nonce byte
// encode the nonce byte
uint8_t nt_byte_enc = crypto1_byte(&sim_cs, nt_byte_dec ^ (test_cuid >> (8 * byte_pos)), false) ^ nt_byte_dec;
*nt_enc = (*nt_enc << 8) | nt_byte_enc;
uint8_t ks_par = filter(sim_cs.odd); // the keystream bit to encode/decode the parity bit
uint8_t nt_byte_par_enc = ks_par ^ oddparity8(nt_byte_dec); // determine the nt byte's parity and encode it
// the keystream bit to encode/decode the parity bit
uint8_t ks_par = filter(sim_cs.odd);
// determine the nt byte's parity and encode it
uint8_t nt_byte_par_enc = ks_par ^ oddparity8(nt_byte_dec);
*par_enc = (*par_enc << 1) | nt_byte_par_enc;
}
}
@@ -2460,6 +2476,9 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
free_bitarray(all_bitflips_bitarray[EVEN_STATE]);
free_sum_bitarrays();
free_part_sum_bitarrays();
return (key_found) ? PM3_SUCCESS : PM3_EFAILED;
}
return PM3_SUCCESS;
}
+94 -29
View File
@@ -19,6 +19,7 @@
#include "cliparser.h"
#include "cmdlfem4x50.h"
#include <ctype.h>
#include <math.h>
#include "cmdparser.h" // command_t
#include "util_posix.h" // msclock
#include "fileutils.h"
@@ -349,54 +350,118 @@ int CmdEM4x50Brute(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 4x50 brute",
"Tries to bruteforce the password of a EM4x50 card.\n"
"Function can be stopped by pressing pm3 button.",
"lf em 4x50 brute --first 12330000 --last 12340000 -> tries pwds from 0x12330000 to 0x1234000000\n"
"Function can be stopped by pressing pm3 button.\n",
"lf em 4x50 brute --mode range --begin 12330000 --end 12340000 -> tries pwds from 0x12330000 to 0x12340000\n"
"lf em 4x50 brute --mode charset --digits --uppercase -> tries all combinations of ASCII codes for digits and uppercase letters\n"
);
void *argtable[] = {
arg_param_begin,
arg_str1(NULL, "first", "<hex>", "first password (start), 4 bytes, lsb"),
arg_str1(NULL, "last", "<hex>", "last password (stop), 4 bytes, lsb"),
arg_str1(NULL, "mode", "<str>", "Bruteforce mode (range|charset)"),
arg_str0(NULL, "begin", "<hex>", "Range mode - start of the key range"),
arg_str0(NULL, "end", "<hex>", "Range mode - end of the key range"),
arg_lit0(NULL, "digits", "Charset mode - include ASCII codes for digits"),
arg_lit0(NULL, "uppercase", "Charset mode - include ASCII codes for uppercase letters"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int first_len = 0;
uint8_t first[4] = {0, 0, 0, 0};
CLIGetHexWithReturn(ctx, 1, first, &first_len);
int last_len = 0;
uint8_t last[4] = {0, 0, 0, 0};
CLIGetHexWithReturn(ctx, 2, last, &last_len);
CLIParserFree(ctx);
if (first_len != 4) {
PrintAndLogEx(FAILED, "password length must be 4 bytes");
return PM3_EINVARG;
}
if (last_len != 4) {
PrintAndLogEx(FAILED, "password length must be 4 bytes");
return PM3_EINVARG;
}
em4x50_data_t etd;
etd.password1 = BYTES2UINT32_BE(first);
etd.password2 = BYTES2UINT32_BE(last);
memset(&etd, 0, sizeof(etd));
int mode_len = 64;
char mode[64];
CLIGetStrWithReturn(ctx, 1, (uint8_t *) mode, &mode_len);
PrintAndLogEx(INFO, "Chosen mode: %s", mode);
if (strcmp(mode, "range") == 0) {
etd.bruteforce_mode = BRUTEFORCE_MODE_RANGE;
} else if (strcmp(mode, "charset") == 0) {
etd.bruteforce_mode = BRUTEFORCE_MODE_CHARSET;
} else {
PrintAndLogEx(FAILED, "Unknown bruteforce mode: %s", mode);
CLIParserFree(ctx);
return PM3_EINVARG;
}
if (etd.bruteforce_mode == BRUTEFORCE_MODE_RANGE) {
int begin_len = 0;
uint8_t begin[4] = {0x0};
CLIGetHexWithReturn(ctx, 2, begin, &begin_len);
int end_len = 0;
uint8_t end[4] = {0x0};
CLIGetHexWithReturn(ctx, 3, end, &end_len);
if (begin_len != 4) {
PrintAndLogEx(FAILED, "'begin' parameter must be 4 bytes");
CLIParserFree(ctx);
return PM3_EINVARG;
}
if (end_len != 4) {
PrintAndLogEx(FAILED, "'end' parameter must be 4 bytes");
CLIParserFree(ctx);
return PM3_EINVARG;
}
etd.password1 = BYTES2UINT32_BE(begin);
etd.password2 = BYTES2UINT32_BE(end);
} else if (etd.bruteforce_mode == BRUTEFORCE_MODE_CHARSET) {
bool enable_digits = arg_get_lit(ctx, 4);
bool enable_uppercase = arg_get_lit(ctx, 5);
if (enable_digits)
etd.bruteforce_charset |= CHARSET_DIGITS;
if (enable_uppercase)
etd.bruteforce_charset |= CHARSET_UPPERCASE;
if (etd.bruteforce_charset == 0) {
PrintAndLogEx(FAILED, "Please enable at least one charset when using charset bruteforce mode.");
CLIParserFree(ctx);
return PM3_EINVARG;
}
PrintAndLogEx(INFO, "Enabled charsets: %s%s",
enable_digits ? "digits " : "",
enable_uppercase ? "uppercase " : "");
}
CLIParserFree(ctx);
// 27 passwords/second (empirical value)
const int speed = 27;
int no_iter = 0;
if (etd.bruteforce_mode == BRUTEFORCE_MODE_RANGE) {
no_iter = etd.password2 - etd.password1 + 1;
PrintAndLogEx(INFO, "Trying " _YELLOW_("%i") " passwords in range [0x%08x, 0x%08x]"
, no_iter
, etd.password1
, etd.password2
);
} else if (etd.bruteforce_mode == BRUTEFORCE_MODE_CHARSET) {
unsigned int digits = 0;
if (etd.bruteforce_charset & CHARSET_DIGITS)
digits += CHARSET_DIGITS_SIZE;
if (etd.bruteforce_charset & CHARSET_UPPERCASE)
digits += CHARSET_UPPERCASE_SIZE;
no_iter = pow(digits, 4);
}
// print some information
int no_iter = etd.password2 - etd.password1 + 1;
int dur_s = no_iter / speed;
int dur_h = dur_s / 3600;
int dur_m = (dur_s - dur_h * 3600) / 60;
dur_s -= dur_h * 3600 + dur_m * 60;
PrintAndLogEx(INFO, "Trying " _YELLOW_("%i") " passwords in range [0x%08x, 0x%08x]"
, no_iter
, etd.password1
, etd.password2
);
PrintAndLogEx(INFO, "Estimated duration: %ih %im %is", dur_h, dur_m, dur_s);
// start
@@ -1190,7 +1255,7 @@ int CmdEM4x50Sim(const char *Cmd) {
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"},
{"brute", CmdEM4x50Brute, IfPm3EM4x50, "Simple bruteforce attack to find password"},
{"brute", CmdEM4x50Brute, IfPm3EM4x50, "Bruteforce attack to find password"},
{"chk", CmdEM4x50Chk, IfPm3EM4x50, "Check passwords from dictionary"},
{"dump", CmdEM4x50Dump, IfPm3EM4x50, "Dump EM4x50 tag"},
{"info", CmdEM4x50Info, IfPm3EM4x50, "Tag information"},
+10 -4
View File
@@ -68,15 +68,20 @@ static int usart_txrx(uint8_t *srcdata, size_t srclen, uint8_t *dstdata, size_t
struct payload_header header;
uint8_t data[PM3_CMD_DATA_SIZE - sizeof(uint32_t)];
} PACKED payload;
payload.header.waittime = waittime;
if (srclen >= sizeof(payload.data))
if (srclen >= sizeof(payload.data)) {
return PM3_EOVFLOW;
}
memcpy(payload.data, srcdata, srclen);
SendCommandNG(CMD_USART_TXRX, (uint8_t *)&payload, srclen + sizeof(payload.header));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_USART_TXRX, &resp, waittime + 500)) {
if (WaitForResponseTimeout(CMD_USART_TXRX, &resp, waittime + 500) == false) {
return PM3_ETIMEOUT;
}
if (resp.status == PM3_SUCCESS) {
*dstlen = resp.length;
memcpy(dstdata, resp.data.asBytes, resp.length);
@@ -154,10 +159,11 @@ static int usart_bt_testcomm(uint32_t baudrate, uint8_t parity) {
PrintAndLogEx(SUCCESS, "TX (%3zu):%.*s at %u 8%c1", strlen(string), (int)strlen(string), string, baudrate, parity);
ret = usart_txrx((uint8_t *)string, strlen(string), data, &len, 1000); // such large timeout needed
// 1000, such large timeout needed
ret = usart_txrx((uint8_t *)string, strlen(string), data, &len, 1000);
if (ret == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "RX (%3zu):%.*s", len, (int)len, data);
if (strcmp((char *)data, "hc01.comV2.0") == 0) {
if (str_startswith((char *)data, "hc01.comV2.0") || str_startswith((char *)data, "BT SPP V3.0")) {
PrintAndLogEx(SUCCESS, "Add-on " _GREEN_("found!"));
return PM3_SUCCESS;
}
+6 -3
View File
@@ -30,8 +30,8 @@
#include "util_posix.h" // msclock
#include "util_darwin.h" // en/dis-ableNapp();
//#define COMMS_DEBUG
//#define COMMS_DEBUG_RAW
// #define COMMS_DEBUG
// #define COMMS_DEBUG_RAW
// Serial port that we are communicating with the PM3 on.
static serial_port sp = NULL;
@@ -369,6 +369,7 @@ __attribute__((force_align_arg_pointer))
}
res = uart_receive(sp, (uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), &rxlen);
if ((res == PM3_SUCCESS) && (rxlen == sizeof(PacketResponseNGPreamble))) {
rx.magic = rx_raw.pre.magic;
uint16_t length = rx_raw.pre.length;
@@ -380,6 +381,7 @@ __attribute__((force_align_arg_pointer))
PrintAndLogEx(WARNING, "Received packet frame with incompatible length: 0x%04x", length);
error = true;
}
if ((!error) && (length > 0)) { // Get the variable length payload
res = uart_receive(sp, (uint8_t *)&rx_raw.data, length, &rxlen);
@@ -418,10 +420,10 @@ __attribute__((force_align_arg_pointer))
rx.length = 0; // set received length to 0
else { // old frames can't be empty
PrintAndLogEx(WARNING, "Received empty MIX packet frame (length: 0x00)");
error = true;
}
}
if (!error) { // Get the postamble
res = uart_receive(sp, (uint8_t *)&rx_raw.foopost, sizeof(PacketResponseNGPostamble), &rxlen);
if ((res != PM3_SUCCESS) || (rxlen != sizeof(PacketResponseNGPostamble))) {
@@ -429,6 +431,7 @@ __attribute__((force_align_arg_pointer))
error = true;
}
}
if (!error) { // Check CRC, accept MAGIC as placeholder
rx.crc = rx_raw.foopost.crc;
if (rx.crc != RESPONSENG_POSTAMBLE_MAGIC) {
+1 -1
View File
@@ -805,7 +805,7 @@ int createMfcKeyDump(const char *preferredName, uint8_t sectorsCnt, sector_t *e_
fflush(f);
fclose(f);
PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_("%s"), fileName);
PrintAndLogEx(INFO, "FYI! --> " _YELLOW_("0xFFFFFFFFFFFF") " <-- has been inserted for unknown keys where " _YELLOW_("res") " is " _YELLOW_("0"));
PrintAndLogEx(INFO, "FYI! --> " _YELLOW_("0xFFFFFFFFFFFF") " <-- has been inserted for unknown keys where " _YELLOW_("res") " is " _RED_("0"));
free(fileName);
return PM3_SUCCESS;
}
+5 -5
View File
@@ -530,7 +530,7 @@ uint8_t mfSectorTrailerOfSector(uint8_t sectorNo) {
}
// assumes blockno is 0-255..
uint8_t mfSectorTrailer(uint8_t blockNo) {
uint8_t mfSectorTrailer(uint16_t blockNo) {
if (blockNo < 32 * 4) {
return (blockNo | 0x03);
} else {
@@ -539,15 +539,15 @@ uint8_t mfSectorTrailer(uint8_t blockNo) {
}
// assumes blockno is 0-255..
bool mfIsSectorTrailer(uint8_t blockNo) {
bool mfIsSectorTrailer(uint16_t blockNo) {
return (blockNo == mfSectorTrailer(blockNo));
}
// assumes blockno is 0-255..
uint8_t mfSectorNum(uint8_t blockNo) {
uint8_t mfSectorNum(uint16_t blockNo) {
if (blockNo < 32 * 4)
return blockNo / 4;
return (blockNo / 4);
else
return 32 + (blockNo - 32 * 4) / 16;
return (32 + (blockNo - 32 * 4) / 16);
}
+3 -3
View File
@@ -77,9 +77,9 @@ const char *mfGetAccessConditionsDesc(uint8_t blockn, const uint8_t *data);
uint8_t mfNumBlocksPerSector(uint8_t sectorNo);
uint8_t mfFirstBlockOfSector(uint8_t sectorNo);
uint8_t mfSectorTrailerOfSector(uint8_t sectorNo);
uint8_t mfSectorTrailer(uint8_t blockNo);
bool mfIsSectorTrailer(uint8_t blockNo);
uint8_t mfSectorNum(uint8_t blockNo);
uint8_t mfSectorTrailer(uint16_t blockNo);
bool mfIsSectorTrailer(uint16_t blockNo);
uint8_t mfSectorNum(uint16_t blockNo);
#endif // mifare4.h

Some files were not shown because too many files have changed in this diff Show More