mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
Merge branch 'master' of github.com:merlokk/proxmark3i into emv_vsdc
This commit is contained in:
commit
bebfcab7b9
84 changed files with 3694 additions and 923 deletions
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -1,6 +1,9 @@
|
||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help us improve
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: "[idea]"
|
||||||
|
labels: Request, enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
|
@ -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...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
- Change 'hf 14a antifuzz' - original implementation (@asfabw), reworked a bit
|
||||||
|
- Fix 'hf mf fchk' (@iceman)
|
||||||
|
- Fix 'usb slow on posix based systems' (@fl0-0)
|
||||||
- Change 'lf pcf7931' - improved read code (@sguerrini97)
|
- Change 'lf pcf7931' - improved read code (@sguerrini97)
|
||||||
- Change 'hf felica list' - started with some FeliCa annotations (@iceman)
|
- Change 'hf felica list' - started with some FeliCa annotations (@iceman)
|
||||||
- Fix 'hf tune' - now works as expected (@iceman)
|
- Fix 'hf tune' - now works as expected (@iceman)
|
||||||
|
|
88
README.md
88
README.md
|
@ -5,6 +5,33 @@ Proxmark3 RDV40 dedicated repo, based on iceman fork
|
||||||
## Notice
|
## Notice
|
||||||
This repo is based on iceman fork for proxmark3. It is dedicated to bring the most out of the new features for proxmark3 RDV40 device.
|
This repo is based on iceman fork for proxmark3. It is dedicated to bring the most out of the new features for proxmark3 RDV40 device.
|
||||||
|
|
||||||
|
# Donations
|
||||||
|
Nothing says thank you as much as a donation, https://www.patreon.com/iceman1001
|
||||||
|
|
||||||
|
## ToC
|
||||||
|
|
||||||
|
- Coverity Scan Config & Run
|
||||||
|
- Whats changed?
|
||||||
|
- Why didn't you based it on offical PM3 Master?
|
||||||
|
- Why don't you add this or that functionality?
|
||||||
|
- PM3 GUI
|
||||||
|
- Development
|
||||||
|
- KALI and ARCHLINUX users
|
||||||
|
- Setup and build for UBUNTU
|
||||||
|
- Setup and build for ArchLinux
|
||||||
|
- Homebrew (Mac OS X)
|
||||||
|
- Upgrading HomeBrew tap formula
|
||||||
|
- Building on Windows
|
||||||
|
- Gator96100 distro
|
||||||
|
- Build and run
|
||||||
|
- Validating proxmark client functionality
|
||||||
|
- Run the following commands
|
||||||
|
- Quit client
|
||||||
|
- First things on your RDV40
|
||||||
|
- Verify sim module firmware version
|
||||||
|
|
||||||
|
- The end
|
||||||
|
|
||||||
## Coverity Scan Config & Run
|
## Coverity Scan Config & Run
|
||||||
Download the Coverity Scan Self-buld and install it.
|
Download the Coverity Scan Self-buld and install it.
|
||||||
You will need to configure ARM-NON-EABI- Compiler for it to use:
|
You will need to configure ARM-NON-EABI- Compiler for it to use:
|
||||||
|
@ -37,19 +64,28 @@ The separation from offical pm3 repo gives us very much freedom to create a firm
|
||||||
Give us a hint, and we'll see if we can't merge in the stuff you have.
|
Give us a hint, and we'll see if we can't merge in the stuff you have.
|
||||||
|
|
||||||
## PM3 GUI
|
## PM3 GUI
|
||||||
The official PM3-GUI from Gaucho will not work.
|
The official PM3-GUI from Gaucho will not work.
|
||||||
The new universial GUI will work.
|
The new universial GUI will work. [Proxmark3 Univerisal GUI](https://github.com/burma69/PM3UniversalGUI)
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
This fork now compiles just fine on
|
This fork now compiles just fine on
|
||||||
- Windows/mingw environment with Qt5.6.1 & GCC 4.8
|
- Windows/mingw environment with Qt5.6.1 & GCC 4.8
|
||||||
- Ubuntu 1404, 1510, 1604, 1804
|
- Ubuntu 1404, 1510, 1604, 1804
|
||||||
- Mac OS X / Homebrew
|
- Mac OS X / Homebrew
|
||||||
|
- ParrotOS
|
||||||
|
- WSL (Windows subsystem linux) on Windows 10
|
||||||
- Docker container
|
- Docker container
|
||||||
|
|
||||||
## KALI and ARCHLINUX users
|
## KALI and ARCHLINUX users
|
||||||
Kali and ArchLinux users usually must kill their modem manager in order for the proxmark3 to enumerate properly.
|
Kali and ArchLinux users usually must kill their modem manager in order for the proxmark3 to enumerate properly.
|
||||||
`sudo apt remove modemmanager`
|
```sh
|
||||||
|
sudo apt remove modemmanager
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```sh
|
||||||
|
systemctl stop ModemManager
|
||||||
|
systemctl disable ModemManager
|
||||||
|
```
|
||||||
|
|
||||||
## Setup and build for UBUNTU
|
## Setup and build for UBUNTU
|
||||||
GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04
|
GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04
|
||||||
|
@ -61,7 +97,7 @@ I have also added this script to the fork.
|
||||||
https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh
|
https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh
|
||||||
|
|
||||||
- Run
|
- Run
|
||||||
`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libjansson-dev`
|
`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi`
|
||||||
|
|
||||||
- Clone fork
|
- Clone fork
|
||||||
`git clone https://github.com/RfidResearchGroup/proxmark3.git`
|
`git clone https://github.com/RfidResearchGroup/proxmark3.git`
|
||||||
|
@ -86,7 +122,7 @@ https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh
|
||||||
|
|
||||||
## Setup and build for ArchLinux
|
## Setup and build for ArchLinux
|
||||||
- Run
|
- Run
|
||||||
`sudo pacman -Sy base-devel p7zip libusb readline ncurses libjansson-dev arm-none-eabi-newlib --needed`
|
`sudo pacman -Sy base-devel p7zip libusb readline ncurses arm-none-eabi-newlib --needed`
|
||||||
`yaourt -S termcap`
|
`yaourt -S termcap`
|
||||||
|
|
||||||
- Remove modemmanager
|
- Remove modemmanager
|
||||||
|
@ -224,7 +260,7 @@ If all went well you should get some information about the firmware and memory u
|
||||||
>
|
>
|
||||||
> pm3 -->
|
> pm3 -->
|
||||||
|
|
||||||
### run the following commands
|
### Run the following commands
|
||||||
pm3 --> hw status
|
pm3 --> hw status
|
||||||
pm3 --> hw version
|
pm3 --> hw version
|
||||||
pm3 --> hw tune
|
pm3 --> hw tune
|
||||||
|
@ -240,6 +276,46 @@ You are now ready to use your newly upgraded proxmark3 device. Many commands us
|
||||||
pm3 --> quit
|
pm3 --> quit
|
||||||
|
|
||||||
|
|
||||||
|
### First things on your RDV40
|
||||||
|
You will need to run these commands to make sure your rdv4 is prepared
|
||||||
|
|
||||||
|
pm3 --> mem load f default_keys m
|
||||||
|
pm3 --> mem load f default_pwd t
|
||||||
|
pm3 --> mem load f default_iclass_keys i
|
||||||
|
pm3 --> lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 p
|
||||||
|
|
||||||
|
### Verify sim module firmware version
|
||||||
|
To make sure you got the latest sim module firmware.
|
||||||
|
_Lastest version is v3.10_
|
||||||
|
|
||||||
|
pm3 --> hw status
|
||||||
|
|
||||||
|
Find version in the long output, look for these two lines
|
||||||
|
|
||||||
|
#db# Smart card module (ISO 7816)
|
||||||
|
#db# version.................v2.06
|
||||||
|
|
||||||
|
This version is obselete. The following command upgrades your device sim module firmware.
|
||||||
|
Don't not turn of your device during the execution of this command.
|
||||||
|
|
||||||
|
pm3 --> sc upgrade f ../tools/simmodule/SIM010.BIN
|
||||||
|
|
||||||
|
You get the following output, this is a successful execution.
|
||||||
|
|
||||||
|
[!] WARNING - Smartcard socket firmware upgrade.
|
||||||
|
[!] A dangerous command, do wrong and you will brick the smart card socket
|
||||||
|
[+] Smartcard socket firmware uploading to PM3
|
||||||
|
..
|
||||||
|
[+] Smartcard socket firmware updating, don't turn off your PM3!
|
||||||
|
#db# FW 0000
|
||||||
|
#db# FW 0080
|
||||||
|
#db# FW 0100
|
||||||
|
#db# FW 0180
|
||||||
|
#db# FW 0200
|
||||||
|
#db# FW 0280
|
||||||
|
[+] Smartcard socket firmware upgraded successful
|
||||||
|
|
||||||
|
|
||||||
## the end
|
## the end
|
||||||
|
|
||||||
`iceman at host iuse.se`
|
`iceman at host iuse.se`
|
||||||
|
|
|
@ -21,7 +21,7 @@ APP_CFLAGS = -DWITH_CRC \
|
||||||
-DWITH_ISO14443a \
|
-DWITH_ISO14443a \
|
||||||
-DWITH_ICLASS \
|
-DWITH_ICLASS \
|
||||||
-DWITH_FELICA \
|
-DWITH_FELICA \
|
||||||
-DWITH_FLASH \
|
-DWITH_FLASH \
|
||||||
-DWITH_SMARTCARD \
|
-DWITH_SMARTCARD \
|
||||||
-DWITH_FPC \
|
-DWITH_FPC \
|
||||||
-DWITH_HFSNOOP \
|
-DWITH_HFSNOOP \
|
||||||
|
@ -191,7 +191,7 @@ $(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
||||||
$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@
|
$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@
|
||||||
|
|
||||||
$(FPGA_COMPRESSOR):
|
$(FPGA_COMPRESSOR):
|
||||||
make -C ../client $(notdir $(FPGA_COMPRESSOR))
|
$(MAKE) -C ../client $(notdir $(FPGA_COMPRESSOR))
|
||||||
|
|
||||||
$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
|
$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
|
||||||
$(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS)
|
$(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS)
|
||||||
|
|
|
@ -271,6 +271,11 @@ void RAMFUNC SniffAndStore(uint8_t param) {
|
||||||
uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts);
|
uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts);
|
||||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen);
|
if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen);
|
||||||
|
|
||||||
|
// If pwd saved successfully, blink led A three times
|
||||||
|
if (writelen > 0) {
|
||||||
|
SpinErr(0, 200, 5); // blink led A
|
||||||
|
}
|
||||||
|
|
||||||
SpinDelay(100);
|
SpinDelay(100);
|
||||||
|
|
||||||
// Reset the SPI Baudrate to the default value (24MHz)
|
// Reset the SPI Baudrate to the default value (24MHz)
|
||||||
|
|
|
@ -724,6 +724,9 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
||||||
case CMD_T55XX_RESET_READ:
|
case CMD_T55XX_RESET_READ:
|
||||||
T55xxResetRead();
|
T55xxResetRead();
|
||||||
break;
|
break;
|
||||||
|
case CMD_T55XX_CHKPWDS:
|
||||||
|
T55xx_ChkPwds();
|
||||||
|
break;
|
||||||
case CMD_PCF7931_READ:
|
case CMD_PCF7931_READ:
|
||||||
ReadPCF7931();
|
ReadPCF7931();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -103,6 +103,8 @@ void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t PwdMode
|
||||||
void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t PwdMode);
|
void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t PwdMode);
|
||||||
void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd);
|
void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd);
|
||||||
void T55xxWakeUp(uint32_t Pwd);
|
void T55xxWakeUp(uint32_t Pwd);
|
||||||
|
void T55xx_ChkPwds(void);
|
||||||
|
|
||||||
void TurnReadLFOn(uint32_t delay);
|
void TurnReadLFOn(uint32_t delay);
|
||||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
|
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
|
||||||
void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd);
|
void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd);
|
||||||
|
|
|
@ -108,7 +108,7 @@ int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response)
|
||||||
switch(iso_type)
|
switch(iso_type)
|
||||||
{
|
{
|
||||||
case 'a':
|
case 'a':
|
||||||
return iso14_apdu(apdu, (uint16_t) length, response, NULL);
|
return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
return iso14443b_apdu(apdu, length, response);
|
return iso14443b_apdu(apdu, length, response);
|
||||||
|
|
|
@ -2219,13 +2219,16 @@ b8 b7 b6 b5 b4 b3 b2 b1
|
||||||
b5,b6 = 00 - DESELECT
|
b5,b6 = 00 - DESELECT
|
||||||
11 - WTX
|
11 - WTX
|
||||||
*/
|
*/
|
||||||
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data, uint8_t *res) {
|
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res) {
|
||||||
uint8_t parity[MAX_PARITY_SIZE] = {0x00};
|
uint8_t parity[MAX_PARITY_SIZE] = {0x00};
|
||||||
uint8_t real_cmd[cmd_len + 4];
|
uint8_t real_cmd[cmd_len + 4];
|
||||||
|
|
||||||
if (cmd_len) {
|
if (cmd_len) {
|
||||||
// ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02
|
// ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02
|
||||||
real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00)
|
real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00)
|
||||||
|
if (send_chaining) {
|
||||||
|
real_cmd[0] |= 0x10;
|
||||||
|
}
|
||||||
// put block number into the PCB
|
// put block number into the PCB
|
||||||
real_cmd[0] |= iso14_pcb_blocknum;
|
real_cmd[0] |= iso14_pcb_blocknum;
|
||||||
memcpy(real_cmd + 1, cmd, cmd_len);
|
memcpy(real_cmd + 1, cmd, cmd_len);
|
||||||
|
@ -2245,7 +2248,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data, uint8_t *res) {
|
||||||
return 0; //DATA LINK ERROR
|
return 0; //DATA LINK ERROR
|
||||||
} else{
|
} else{
|
||||||
// S-Block WTX
|
// S-Block WTX
|
||||||
while((data_bytes[0] & 0xF2) == 0xF2) {
|
while(len && ((data_bytes[0] & 0xF2) == 0xF2)) {
|
||||||
uint32_t save_iso14a_timeout = iso14a_get_timeout();
|
uint32_t save_iso14a_timeout = iso14a_get_timeout();
|
||||||
// temporarily increase timeout
|
// temporarily increase timeout
|
||||||
iso14a_set_timeout( MAX((data_bytes[1] & 0x3f) * save_iso14a_timeout, MAX_ISO14A_TIMEOUT) );
|
iso14a_set_timeout( MAX((data_bytes[1] & 0x3f) * save_iso14a_timeout, MAX_ISO14A_TIMEOUT) );
|
||||||
|
@ -2263,32 +2266,34 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data, uint8_t *res) {
|
||||||
iso14a_set_timeout(save_iso14a_timeout);
|
iso14a_set_timeout(save_iso14a_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we received an I- or R(ACK)-Block with a block number equal to the
|
// if we received an I- or R(ACK)-Block with a block number equal to the
|
||||||
// current block number, toggle the current block number
|
// current block number, toggle the current block number
|
||||||
if (len >= 3 // PCB+CRC = 3 bytes
|
if (len >= 3 // PCB+CRC = 3 bytes
|
||||||
&& ((data_bytes[0] & 0xC0) == 0 // I-Block
|
&& ((data_bytes[0] & 0xC0) == 0 // I-Block
|
||||||
|| (data_bytes[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
|
|| (data_bytes[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
|
||||||
&& (data_bytes[0] & 0x01) == iso14_pcb_blocknum) // equal block numbers
|
&& (data_bytes[0] & 0x01) == iso14_pcb_blocknum) // equal block numbers
|
||||||
{
|
{
|
||||||
iso14_pcb_blocknum ^= 1;
|
iso14_pcb_blocknum ^= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we received I-block with chaining we need to send ACK and receive another block of data
|
// if we received I-block with chaining we need to send ACK and receive another block of data
|
||||||
if (res)
|
if (res)
|
||||||
*res = data_bytes[0];
|
*res = data_bytes[0];
|
||||||
|
|
||||||
// crc check
|
// crc check
|
||||||
if (len >=3 && !check_crc(CRC_14443_A, data_bytes, len)) {
|
if (len >= 3 && !check_crc(CRC_14443_A, data_bytes, len)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cut frame byte
|
if (len) {
|
||||||
len -= 1;
|
// cut frame byte
|
||||||
// memmove(data_bytes, data_bytes + 1, len);
|
len -= 1;
|
||||||
for (int i = 0; i < len; i++)
|
// memmove(data_bytes, data_bytes + 1, len);
|
||||||
data_bytes[i] = data_bytes[i + 1];
|
for (int i = 0; i < len; i++)
|
||||||
|
data_bytes[i] = data_bytes[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -2338,7 +2343,7 @@ void ReaderIso14443a(UsbCommand *c) {
|
||||||
|
|
||||||
if ((param & ISO14A_APDU)) {
|
if ((param & ISO14A_APDU)) {
|
||||||
uint8_t res;
|
uint8_t res;
|
||||||
arg0 = iso14_apdu(cmd, len, buf, &res);
|
arg0 = iso14_apdu(cmd, len, (param & ISO14A_SEND_CHAINING), buf, &res);
|
||||||
cmd_send(CMD_ACK, arg0, res, 0, buf, sizeof(buf));
|
cmd_send(CMD_ACK, arg0, res, 0, buf, sizeof(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ extern void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32
|
||||||
extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par);
|
extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par);
|
||||||
|
|
||||||
extern void iso14443a_setup(uint8_t fpga_minor_mode);
|
extern void iso14443a_setup(uint8_t fpga_minor_mode);
|
||||||
extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data, uint8_t *res);
|
extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res);
|
||||||
extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
|
extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
|
||||||
extern int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
extern int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
||||||
extern void iso14a_set_trigger(bool enable);
|
extern void iso14a_set_trigger(bool enable);
|
||||||
|
|
|
@ -61,7 +61,7 @@ static inline uint8_t rx_byte_from_fpga() {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
// wait for byte be become available in rx holding register
|
// wait for byte be become available in rx holding register
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
return AT91C_BASE_SSC->SSC_RHR;
|
return AT91C_BASE_SSC->SSC_RHR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ static inline uint8_t rx_byte_from_fpga() {
|
||||||
// To reduce CPU time the amplitude is approximated by using linear functions:
|
// To reduce CPU time the amplitude is approximated by using linear functions:
|
||||||
// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
|
// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
|
||||||
//
|
//
|
||||||
// Note: The SSC receiver is never synchronized the calculation my be performed
|
// Note: The SSC receiver is never synchronized the calculation may be performed
|
||||||
// on a i/q pair from two subsequent correlations, but does not matter.
|
// on a i/q pair from two subsequent correlations, but does not matter.
|
||||||
static inline int32_t sample_power() {
|
static inline int32_t sample_power() {
|
||||||
int32_t q = (int8_t)rx_byte_from_fpga(); q = ABS(q);
|
int32_t q = (int8_t)rx_byte_from_fpga(); q = ABS(q);
|
||||||
|
@ -100,7 +100,7 @@ static inline int32_t sample_power() {
|
||||||
static inline bool rx_bit() {
|
static inline bool rx_bit() {
|
||||||
int32_t power;
|
int32_t power;
|
||||||
|
|
||||||
for(size_t i = 0; i<5; ++i) {
|
for (size_t i = 0; i<5; ++i) {
|
||||||
power = sample_power();
|
power = sample_power();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,12 +120,12 @@ static inline void tx_bit(bool bit) {
|
||||||
// insert pause
|
// insert pause
|
||||||
LOW(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
last_frame_end += RWD_TIME_PAUSE;
|
last_frame_end += RWD_TIME_PAUSE;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
HIGH(GPIO_SSC_DOUT);
|
HIGH(GPIO_SSC_DOUT);
|
||||||
|
|
||||||
// return to high, wait for bit periode to end
|
// return to high, wait for bit periode to end
|
||||||
last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
|
last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -143,13 +143,13 @@ static void tx_frame(uint32_t frame, uint8_t len) {
|
||||||
|
|
||||||
// wait for next tx timeslot
|
// wait for next tx timeslot
|
||||||
last_frame_end += RWD_FRAME_WAIT;
|
last_frame_end += RWD_FRAME_WAIT;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
|
|
||||||
// backup ts for trace log
|
// backup ts for trace log
|
||||||
uint32_t last_frame_start = last_frame_end;
|
uint32_t last_frame_start = last_frame_end;
|
||||||
|
|
||||||
// transmit frame, MSB first
|
// transmit frame, MSB first
|
||||||
for(uint8_t i = 0; i < len; ++i) {
|
for (uint8_t i = 0; i < len; ++i) {
|
||||||
bool bit = (frame >> i) & 0x01;
|
bool bit = (frame >> i) & 0x01;
|
||||||
tx_bit(bit ^ legic_prng_get_bit());
|
tx_bit(bit ^ legic_prng_get_bit());
|
||||||
legic_prng_forward(1);
|
legic_prng_forward(1);
|
||||||
|
@ -158,7 +158,7 @@ static void tx_frame(uint32_t frame, uint8_t len) {
|
||||||
// add pause to mark end of the frame
|
// add pause to mark end of the frame
|
||||||
LOW(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
last_frame_end += RWD_TIME_PAUSE;
|
last_frame_end += RWD_TIME_PAUSE;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
HIGH(GPIO_SSC_DOUT);
|
HIGH(GPIO_SSC_DOUT);
|
||||||
|
|
||||||
// log
|
// log
|
||||||
|
@ -173,19 +173,19 @@ static uint32_t rx_frame(uint8_t len) {
|
||||||
|
|
||||||
// hold sampling until card is expected to respond
|
// hold sampling until card is expected to respond
|
||||||
last_frame_end += TAG_FRAME_WAIT;
|
last_frame_end += TAG_FRAME_WAIT;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
|
|
||||||
// backup ts for trace log
|
// backup ts for trace log
|
||||||
uint32_t last_frame_start = last_frame_end;
|
uint32_t last_frame_start = last_frame_end;
|
||||||
|
|
||||||
uint32_t frame = 0;
|
uint32_t frame = 0;
|
||||||
for(uint8_t i = 0; i < len; ++i) {
|
for (uint8_t i = 0; i < len; ++i) {
|
||||||
frame |= (rx_bit() ^ legic_prng_get_bit()) << i;
|
frame |= (rx_bit() ^ legic_prng_get_bit()) << i;
|
||||||
legic_prng_forward(1);
|
legic_prng_forward(1);
|
||||||
|
|
||||||
// rx_bit runs only 95us, resync to TAG_BIT_PERIOD
|
// rx_bit runs only 95us, resync to TAG_BIT_PERIOD
|
||||||
last_frame_end += TAG_BIT_PERIOD;
|
last_frame_end += TAG_BIT_PERIOD;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
}
|
}
|
||||||
|
|
||||||
// log
|
// log
|
||||||
|
@ -203,23 +203,23 @@ static bool rx_ack() {
|
||||||
|
|
||||||
// hold sampling until card is expected to respond
|
// hold sampling until card is expected to respond
|
||||||
last_frame_end += TAG_FRAME_WAIT;
|
last_frame_end += TAG_FRAME_WAIT;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
|
|
||||||
// backup ts for trace log
|
// backup ts for trace log
|
||||||
uint32_t last_frame_start = last_frame_end;
|
uint32_t last_frame_start = last_frame_end;
|
||||||
|
|
||||||
uint32_t ack = 0;
|
uint32_t ack = 0;
|
||||||
for(uint8_t i = 0; i < TAG_WRITE_TIMEOUT; ++i) {
|
for (uint8_t i = 0; i < TAG_WRITE_TIMEOUT; ++i) {
|
||||||
// sample bit
|
// sample bit
|
||||||
ack = rx_bit();
|
ack = rx_bit();
|
||||||
legic_prng_forward(1);
|
legic_prng_forward(1);
|
||||||
|
|
||||||
// rx_bit runs only 95us, resync to TAG_BIT_PERIOD
|
// rx_bit runs only 95us, resync to TAG_BIT_PERIOD
|
||||||
last_frame_end += TAG_BIT_PERIOD;
|
last_frame_end += TAG_BIT_PERIOD;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
|
|
||||||
// check if it was an ACK
|
// check if it was an ACK
|
||||||
if(ack) {
|
if (ack) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,7 @@ static void init_reader(bool clear_mem) {
|
||||||
|
|
||||||
// reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
|
// reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
|
||||||
legic_mem = BigBuf_get_EM_addr();
|
legic_mem = BigBuf_get_EM_addr();
|
||||||
if(legic_mem) {
|
if (legic_mem) {
|
||||||
memset(legic_mem, 0x00, LEGIC_CARD_MEMSIZE);
|
memset(legic_mem, 0x00, LEGIC_CARD_MEMSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +309,7 @@ static uint32_t setup_phase(uint8_t iv) {
|
||||||
|
|
||||||
// Switch on carrier and let the card charge for 5ms.
|
// Switch on carrier and let the card charge for 5ms.
|
||||||
last_frame_end += 7500;
|
last_frame_end += 7500;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while (GET_TICKS < last_frame_end) { };
|
||||||
|
|
||||||
legic_prng_init(0);
|
legic_prng_init(0);
|
||||||
tx_frame(iv, 7);
|
tx_frame(iv, 7);
|
||||||
|
@ -359,7 +359,7 @@ static int16_t read_byte(uint16_t index, uint8_t cmd_sz) {
|
||||||
|
|
||||||
// check received against calculated crc
|
// check received against calculated crc
|
||||||
uint8_t calc_crc = calc_crc4(cmd, cmd_sz, byte);
|
uint8_t calc_crc = calc_crc4(cmd, cmd_sz, byte);
|
||||||
if(calc_crc != crc) {
|
if (calc_crc != crc) {
|
||||||
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
|
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -399,15 +399,15 @@ void LegicRfInfo(void) {
|
||||||
|
|
||||||
// establish shared secret and detect card type
|
// establish shared secret and detect card type
|
||||||
uint8_t card_type = setup_phase(0x01);
|
uint8_t card_type = setup_phase(0x01);
|
||||||
if(init_card(card_type, &card) != 0) {
|
if (init_card(card_type, &card) != 0) {
|
||||||
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read UID
|
// read UID
|
||||||
for(uint8_t i = 0; i < sizeof(card.uid); ++i) {
|
for (uint8_t i = 0; i < sizeof(card.uid); ++i) {
|
||||||
int16_t byte = read_byte(i, card.cmdsize);
|
int16_t byte = read_byte(i, card.cmdsize);
|
||||||
if(byte == -1) {
|
if (byte == -1) {
|
||||||
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,7 @@ void LegicRfInfo(void) {
|
||||||
// read MCC and check against UID
|
// read MCC and check against UID
|
||||||
int16_t mcc = read_byte(4, card.cmdsize);
|
int16_t mcc = read_byte(4, card.cmdsize);
|
||||||
int16_t calc_mcc = CRC8Legic(card.uid, 4);;
|
int16_t calc_mcc = CRC8Legic(card.uid, 4);;
|
||||||
if(mcc != calc_mcc) {
|
if (mcc != calc_mcc) {
|
||||||
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
@ -436,19 +436,19 @@ void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
|
||||||
|
|
||||||
// establish shared secret and detect card type
|
// establish shared secret and detect card type
|
||||||
uint8_t card_type = setup_phase(iv);
|
uint8_t card_type = setup_phase(iv);
|
||||||
if(init_card(card_type, &card) != 0) {
|
if (init_card(card_type, &card) != 0) {
|
||||||
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// do not read beyond card memory
|
// do not read beyond card memory
|
||||||
if(len + offset > card.cardsize) {
|
if (len + offset > card.cardsize) {
|
||||||
len = card.cardsize - offset;
|
len = card.cardsize - offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint16_t i = 0; i < len; ++i) {
|
for (uint16_t i = 0; i < len; ++i) {
|
||||||
int16_t byte = read_byte(offset + i, card.cmdsize);
|
int16_t byte = read_byte(offset + i, card.cmdsize);
|
||||||
if(byte == -1) {
|
if (byte == -1) {
|
||||||
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
@ -468,26 +468,26 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
|
||||||
init_reader(false);
|
init_reader(false);
|
||||||
|
|
||||||
// uid is not writeable
|
// uid is not writeable
|
||||||
if(offset <= WRITE_LOWERLIMIT) {
|
if (offset <= WRITE_LOWERLIMIT) {
|
||||||
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// establish shared secret and detect card type
|
// establish shared secret and detect card type
|
||||||
uint8_t card_type = setup_phase(iv);
|
uint8_t card_type = setup_phase(iv);
|
||||||
if(init_card(card_type, &card) != 0) {
|
if (init_card(card_type, &card) != 0) {
|
||||||
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// do not write beyond card memory
|
// do not write beyond card memory
|
||||||
if(len + offset > card.cardsize) {
|
if (len + offset > card.cardsize) {
|
||||||
len = card.cardsize - offset;
|
len = card.cardsize - offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write in reverse order, only then is DCF (decremental field) writable
|
// write in reverse order, only then is DCF (decremental field) writable
|
||||||
while(len-- > 0 && !BUTTON_PRESS()) {
|
while (len-- > 0 && !BUTTON_PRESS()) {
|
||||||
if(!write_byte(len + offset, data[len], card.addrsize)) {
|
if (!write_byte(len + offset, data[len], card.addrsize)) {
|
||||||
Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
|
Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
|
||||||
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
cmd_send(CMD_ACK, 0, 0, 0, 0, 0);
|
||||||
goto OUT;
|
goto OUT;
|
||||||
|
|
|
@ -46,7 +46,7 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
|
||||||
#define RWD_TIME_PAUSE 4 /* 18.9us */
|
#define RWD_TIME_PAUSE 4 /* 18.9us */
|
||||||
#define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */
|
#define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */
|
||||||
#define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */
|
#define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */
|
||||||
#define RWD_CMD_TIMEOUT 40 /* 40 * 99.1us (arbitrary value) */
|
#define RWD_CMD_TIMEOUT 120 /* 120 * 99.1us (arbitrary value) */
|
||||||
#define RWD_MIN_FRAME_LEN 6 /* Shortest frame is 6 bits */
|
#define RWD_MIN_FRAME_LEN 6 /* Shortest frame is 6 bits */
|
||||||
#define RWD_MAX_FRAME_LEN 23 /* Longest frame is 23 bits */
|
#define RWD_MAX_FRAME_LEN 23 /* Longest frame is 23 bits */
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
|
||||||
|
|
||||||
// Returns true if a pulse/pause is received within timeout
|
// Returns true if a pulse/pause is received within timeout
|
||||||
static inline bool wait_for(bool value, const uint32_t timeout) {
|
static inline bool wait_for(bool value, const uint32_t timeout) {
|
||||||
while((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) {
|
while ((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) {
|
||||||
if(GetCountSspClk() > timeout) {
|
if (GetCountSspClk() > timeout) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,12 +81,12 @@ static inline int8_t rx_bit() {
|
||||||
uint32_t bit_start = last_frame_end;
|
uint32_t bit_start = last_frame_end;
|
||||||
|
|
||||||
// wait for pause to end
|
// wait for pause to end
|
||||||
if(!wait_for(RWD_PULSE, bit_start + RWD_TIME_1*3/2)) {
|
if (!wait_for(RWD_PULSE, bit_start + RWD_TIME_1*3/2)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for next pause
|
// wait for next pause
|
||||||
if(!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1*3/2)) {
|
if (!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1*3/2)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ static inline int8_t rx_bit() {
|
||||||
last_frame_end = GetCountSspClk();
|
last_frame_end = GetCountSspClk();
|
||||||
|
|
||||||
// check for code violation (bit to short)
|
// check for code violation (bit to short)
|
||||||
if(last_frame_end - bit_start < RWD_TIME_PAUSE) {
|
if (last_frame_end - bit_start < RWD_TIME_PAUSE) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ static inline int8_t rx_bit() {
|
||||||
static inline void tx_bit(bool bit) {
|
static inline void tx_bit(bool bit) {
|
||||||
LED_C_ON();
|
LED_C_ON();
|
||||||
|
|
||||||
if(bit) {
|
if (bit) {
|
||||||
// modulate subcarrier
|
// modulate subcarrier
|
||||||
HIGH(GPIO_SSC_DOUT);
|
HIGH(GPIO_SSC_DOUT);
|
||||||
} else {
|
} else {
|
||||||
|
@ -132,7 +132,7 @@ static inline void tx_bit(bool bit) {
|
||||||
|
|
||||||
// wait for tx timeslot to end
|
// wait for tx timeslot to end
|
||||||
last_frame_end += TAG_BIT_PERIOD;
|
last_frame_end += TAG_BIT_PERIOD;
|
||||||
while(GetCountSspClk() < last_frame_end) { };
|
while (GetCountSspClk() < last_frame_end) { };
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,13 +150,13 @@ static void tx_frame(uint32_t frame, uint8_t len) {
|
||||||
// wait for next tx timeslot
|
// wait for next tx timeslot
|
||||||
last_frame_end += TAG_FRAME_WAIT;
|
last_frame_end += TAG_FRAME_WAIT;
|
||||||
legic_prng_forward(TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1);
|
legic_prng_forward(TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1);
|
||||||
while(GetCountSspClk() < last_frame_end) { };
|
while (GetCountSspClk() < last_frame_end) { };
|
||||||
|
|
||||||
// backup ts for trace log
|
// backup ts for trace log
|
||||||
uint32_t last_frame_start = last_frame_end;
|
uint32_t last_frame_start = last_frame_end;
|
||||||
|
|
||||||
// transmit frame, MSB first
|
// transmit frame, MSB first
|
||||||
for(uint8_t i = 0; i < len; ++i) {
|
for (uint8_t i = 0; i < len; ++i) {
|
||||||
bool bit = (frame >> i) & 0x01;
|
bool bit = (frame >> i) & 0x01;
|
||||||
tx_bit(bit ^ legic_prng_get_bit());
|
tx_bit(bit ^ legic_prng_get_bit());
|
||||||
legic_prng_forward(1);
|
legic_prng_forward(1);
|
||||||
|
@ -174,7 +174,7 @@ static void tx_ack() {
|
||||||
// wait for ack timeslot
|
// wait for ack timeslot
|
||||||
last_frame_end += TAG_ACK_WAIT;
|
last_frame_end += TAG_ACK_WAIT;
|
||||||
legic_prng_forward(TAG_ACK_WAIT/TAG_BIT_PERIOD - 1);
|
legic_prng_forward(TAG_ACK_WAIT/TAG_BIT_PERIOD - 1);
|
||||||
while(GetCountSspClk() < last_frame_end) { };
|
while (GetCountSspClk() < last_frame_end) { };
|
||||||
|
|
||||||
// backup ts for trace log
|
// backup ts for trace log
|
||||||
uint32_t last_frame_start = last_frame_end;
|
uint32_t last_frame_start = last_frame_end;
|
||||||
|
@ -206,19 +206,19 @@ static int32_t rx_frame(uint8_t *len) {
|
||||||
last_frame_end -= 2;
|
last_frame_end -= 2;
|
||||||
|
|
||||||
// wait for first pause (start of frame)
|
// wait for first pause (start of frame)
|
||||||
for(uint8_t i = 0; true; ++i) {
|
for (uint8_t i = 0; true; ++i) {
|
||||||
// increment prng every TAG_BIT_PERIOD
|
// increment prng every TAG_BIT_PERIOD
|
||||||
last_frame_end += TAG_BIT_PERIOD;
|
last_frame_end += TAG_BIT_PERIOD;
|
||||||
legic_prng_forward(1);
|
legic_prng_forward(1);
|
||||||
|
|
||||||
// if start of frame was received exit delay loop
|
// if start of frame was received exit delay loop
|
||||||
if(wait_for(RWD_PAUSE, last_frame_end)) {
|
if (wait_for(RWD_PAUSE, last_frame_end)) {
|
||||||
last_frame_end = GetCountSspClk();
|
last_frame_end = GetCountSspClk();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for code violation
|
// check for code violation
|
||||||
if(i > RWD_CMD_TIMEOUT) {
|
if (i > RWD_CMD_TIMEOUT) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,19 +227,19 @@ static int32_t rx_frame(uint8_t *len) {
|
||||||
uint32_t last_frame_start = last_frame_end;
|
uint32_t last_frame_start = last_frame_end;
|
||||||
|
|
||||||
// receive frame
|
// receive frame
|
||||||
for(*len = 0; true; ++(*len)) {
|
for (*len = 0; true; ++(*len)) {
|
||||||
// receive next bit
|
// receive next bit
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
int8_t bit = rx_bit();
|
int8_t bit = rx_bit();
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
// check for code violation and to short / long frame
|
// check for code violation and to short / long frame
|
||||||
if((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) {
|
if ((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for code violation caused by end of frame
|
// check for code violation caused by end of frame
|
||||||
if(bit < 0) {
|
if (bit < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +256,6 @@ static int32_t rx_frame(uint8_t *len) {
|
||||||
// log
|
// log
|
||||||
uint8_t cmdbytes[] = {*len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
|
uint8_t cmdbytes[] = {*len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
|
||||||
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
|
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +266,7 @@ static int32_t rx_frame(uint8_t *len) {
|
||||||
static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) {
|
static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) {
|
||||||
p_card->tagtype = cardtype;
|
p_card->tagtype = cardtype;
|
||||||
|
|
||||||
switch(p_card->tagtype) {
|
switch (p_card->tagtype) {
|
||||||
case 0:
|
case 0:
|
||||||
p_card->cmdsize = 6;
|
p_card->cmdsize = 6;
|
||||||
p_card->addrsize = 5;
|
p_card->addrsize = 5;
|
||||||
|
@ -338,7 +337,7 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
|
||||||
|
|
||||||
// wait for iv
|
// wait for iv
|
||||||
int32_t iv = rx_frame(&len);
|
int32_t iv = rx_frame(&len);
|
||||||
if((len != 7) || (iv < 0)) {
|
if ((len != 7) || (iv < 0)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +345,7 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
|
||||||
legic_prng_init(iv);
|
legic_prng_init(iv);
|
||||||
|
|
||||||
// reply with card type
|
// reply with card type
|
||||||
switch(p_card->tagtype) {
|
switch (p_card->tagtype) {
|
||||||
case 0:
|
case 0:
|
||||||
tx_frame(0x0D, 6);
|
tx_frame(0x0D, 6);
|
||||||
break;
|
break;
|
||||||
|
@ -360,12 +359,12 @@ static int32_t setup_phase(legic_card_select_t *p_card) {
|
||||||
|
|
||||||
// wait for ack
|
// wait for ack
|
||||||
int32_t ack = rx_frame(&len);
|
int32_t ack = rx_frame(&len);
|
||||||
if((len != 6) || (ack < 0)) {
|
if ((len != 6) || (ack < 0)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate data
|
// validate data
|
||||||
switch(p_card->tagtype) {
|
switch (p_card->tagtype) {
|
||||||
case 0:
|
case 0:
|
||||||
if(ack != 0x19) return -1;
|
if(ack != 0x19) return -1;
|
||||||
break;
|
break;
|
||||||
|
@ -399,12 +398,12 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
|
||||||
|
|
||||||
// wait for command
|
// wait for command
|
||||||
int32_t cmd = rx_frame(&len);
|
int32_t cmd = rx_frame(&len);
|
||||||
if(cmd < 0) {
|
if (cmd < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if command is LEGIC_READ
|
// check if command is LEGIC_READ
|
||||||
if(len == p_card->cmdsize) {
|
if (len == p_card->cmdsize) {
|
||||||
// prepare data
|
// prepare data
|
||||||
uint8_t byte = legic_mem[cmd >> 1];
|
uint8_t byte = legic_mem[cmd >> 1];
|
||||||
uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte);
|
uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte);
|
||||||
|
@ -416,7 +415,7 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if command is LEGIC_WRITE
|
// check if command is LEGIC_WRITE
|
||||||
if(len == p_card->cmdsize + 8 + 4) {
|
if (len == p_card->cmdsize + 8 + 4) {
|
||||||
// decode data
|
// decode data
|
||||||
uint16_t mask = (1 << p_card->addrsize) - 1;
|
uint16_t mask = (1 << p_card->addrsize) - 1;
|
||||||
uint16_t addr = (cmd >> 1) & mask;
|
uint16_t addr = (cmd >> 1) & mask;
|
||||||
|
@ -425,7 +424,7 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
|
||||||
|
|
||||||
// check received against calculated crc
|
// check received against calculated crc
|
||||||
uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte);
|
uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte);
|
||||||
if(calc_crc != crc) {
|
if (calc_crc != crc) {
|
||||||
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
|
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -453,7 +452,7 @@ void LegicRfSimulate(uint8_t cardtype) {
|
||||||
init_tag();
|
init_tag();
|
||||||
|
|
||||||
// verify command line input
|
// verify command line input
|
||||||
if(init_card(cardtype, &card) != 0) {
|
if (init_card(cardtype, &card) != 0) {
|
||||||
DbpString("Unknown tagtype.");
|
DbpString("Unknown tagtype.");
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
@ -464,17 +463,17 @@ void LegicRfSimulate(uint8_t cardtype) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
// wait for carrier, restart after timeout
|
// wait for carrier, restart after timeout
|
||||||
if(!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) {
|
if (!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for connection, restart on error
|
// wait for connection, restart on error
|
||||||
if(setup_phase(&card)) {
|
if (setup_phase(&card)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// conection is established, process commands until one fails
|
// conection is established, process commands until one fails
|
||||||
while(!connected_phase(&card)) {
|
while (!connected_phase(&card)) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
186
armsrc/lfops.c
186
armsrc/lfops.c
|
@ -80,7 +80,7 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) {
|
||||||
|
|
||||||
printT55xxConfig();
|
printT55xxConfig();
|
||||||
|
|
||||||
#if WITH_FLASH
|
#ifdef WITH_FLASH
|
||||||
// shall persist to flashmem
|
// shall persist to flashmem
|
||||||
if (arg0 == 0) {
|
if (arg0 == 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -119,7 +119,7 @@ t55xx_config* getT55xxConfig(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadT55xxConfig(void) {
|
void loadT55xxConfig(void) {
|
||||||
#if WITH_FLASH
|
#ifdef WITH_FLASH
|
||||||
if (!FlashInit()) {
|
if (!FlashInit()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -598,9 +598,11 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle
|
||||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
|
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
|
||||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||||
AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
|
AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
|
||||||
|
|
||||||
|
uint8_t check = 1;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
|
||||||
if ( numcycles > -1 ) {
|
if ( numcycles > -1 ) {
|
||||||
if ( x != numcycles ) {
|
if ( x != numcycles ) {
|
||||||
++x;
|
++x;
|
||||||
|
@ -616,9 +618,11 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle
|
||||||
// used as a simple detection of a reader field?
|
// used as a simple detection of a reader field?
|
||||||
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
|
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if ( usb_poll_validate_length() || BUTTON_PRESS() )
|
if ( !check ) {
|
||||||
goto OUT;
|
if ( usb_poll_validate_length() || BUTTON_PRESS() )
|
||||||
}
|
goto OUT;
|
||||||
|
}
|
||||||
|
++check; }
|
||||||
|
|
||||||
if (buf[i])
|
if (buf[i])
|
||||||
OPEN_COIL();
|
OPEN_COIL();
|
||||||
|
@ -628,9 +632,11 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle
|
||||||
//wait until SSC_CLK goes LOW
|
//wait until SSC_CLK goes LOW
|
||||||
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
|
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
//if ( usb_poll_validate_length() || BUTTON_PRESS() )
|
if ( !check ) {
|
||||||
if ( BUTTON_PRESS() )
|
if ( usb_poll_validate_length() || BUTTON_PRESS() )
|
||||||
goto OUT;
|
goto OUT;
|
||||||
|
}
|
||||||
|
++check;
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
@ -1489,11 +1495,22 @@ void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) {
|
||||||
// Read one card block in page [page]
|
// Read one card block in page [page]
|
||||||
void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) {
|
void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) {
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
bool PwdMode = arg0 & 0x1;
|
bool PwdMode = arg0 & 0x1;
|
||||||
uint8_t Page = (arg0 & 0x2) >> 1;
|
uint8_t Page = ( arg0 & 0x2 ) >> 1;
|
||||||
uint32_t i = 0;
|
bool brute_mem = arg0 & 0x4;
|
||||||
bool RegReadMode = (Block == 0xFF);//regular read mode
|
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
// regular read mode
|
||||||
|
bool RegReadMode = (Block == 0xFF);
|
||||||
|
|
||||||
|
uint8_t start_wait = 4;
|
||||||
|
size_t samples = 12000;
|
||||||
|
if ( brute_mem ) {
|
||||||
|
start_wait = 0;
|
||||||
|
samples = 1024;
|
||||||
|
}
|
||||||
|
|
||||||
//clear buffer now so it does not interfere with timing later
|
//clear buffer now so it does not interfere with timing later
|
||||||
BigBuf_Clear_keep_EM();
|
BigBuf_Clear_keep_EM();
|
||||||
|
|
||||||
|
@ -1505,7 +1522,8 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) {
|
||||||
// Set up FPGA, 125kHz to power up the tag
|
// Set up FPGA, 125kHz to power up the tag
|
||||||
LFSetupFPGAForADC(95, true);
|
LFSetupFPGAForADC(95, true);
|
||||||
// make sure tag is fully powered up...
|
// make sure tag is fully powered up...
|
||||||
WaitMS(4);
|
WaitMS(start_wait);
|
||||||
|
|
||||||
// Trigger T55x7 Direct Access Mode with start gap
|
// Trigger T55x7 Direct Access Mode with start gap
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
WaitUS(t_config.start_gap);
|
WaitUS(t_config.start_gap);
|
||||||
|
@ -1529,17 +1547,118 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) {
|
||||||
|
|
||||||
// Turn field on to read the response
|
// Turn field on to read the response
|
||||||
// 137*8 seems to get to the start of data pretty well...
|
// 137*8 seems to get to the start of data pretty well...
|
||||||
// but we want to go past the start and let the repeating data settle in...
|
// but we want to go past the start and let the repeating data settle in...
|
||||||
TurnReadLFOn(210*8);
|
TurnReadLFOn(200*8);
|
||||||
|
|
||||||
// Acquisition
|
// Acquisition
|
||||||
// Now do the acquisition
|
// Now do the acquisition
|
||||||
DoPartialAcquisition(0, true, 12000, 0);
|
DoPartialAcquisition(0, true, samples, 0);
|
||||||
|
|
||||||
// Turn the field off
|
// Turn the field off
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
if ( !brute_mem ) {
|
||||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_A_OFF();
|
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||||
|
LED_A_OFF();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void T55xx_ChkPwds() {
|
||||||
|
|
||||||
|
DbpString("[+] T55XX Check pwds using flashmemory starting");
|
||||||
|
|
||||||
|
uint8_t ret = 0;
|
||||||
|
// First get baseline and setup LF mode.
|
||||||
|
// tends to mess up BigBuf
|
||||||
|
uint8_t *buf = BigBuf_get_addr();
|
||||||
|
|
||||||
|
uint32_t b1, baseline = 0;
|
||||||
|
|
||||||
|
// collect baseline for failed attempt
|
||||||
|
uint8_t x = 32;
|
||||||
|
while (x--) {
|
||||||
|
b1 = 0;
|
||||||
|
T55xxReadBlock(4, 1, 0);
|
||||||
|
for (uint16_t j=0; j < 1024; ++j)
|
||||||
|
b1 += buf[j];
|
||||||
|
|
||||||
|
b1 *= b1;
|
||||||
|
b1 >>= 8;
|
||||||
|
baseline += b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
baseline >>= 5;
|
||||||
|
Dbprintf("[=] Baseline determined [%u]", baseline);
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t *pwds = BigBuf_get_EM_addr();
|
||||||
|
uint16_t pwdCount = 0;
|
||||||
|
uint32_t candidate = 0;
|
||||||
|
|
||||||
|
#ifdef WITH_FLASH
|
||||||
|
bool use_flashmem = true;
|
||||||
|
if ( use_flashmem ) {
|
||||||
|
BigBuf_Clear_EM();
|
||||||
|
uint16_t isok = 0;
|
||||||
|
uint8_t counter[2] = {0x00, 0x00};
|
||||||
|
isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter) );
|
||||||
|
if ( isok != sizeof(counter) )
|
||||||
|
goto OUT;
|
||||||
|
|
||||||
|
pwdCount = counter[1] << 8 | counter[0];
|
||||||
|
|
||||||
|
if ( pwdCount == 0 && pwdCount == 0xFFFF)
|
||||||
|
goto OUT;
|
||||||
|
|
||||||
|
isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET+2, pwds, pwdCount * 4);
|
||||||
|
if ( isok != pwdCount * 4 )
|
||||||
|
goto OUT;
|
||||||
|
|
||||||
|
Dbprintf("[=] Password dictionary count %d ", pwdCount);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t pwd = 0, curr = 0, prev = 0;
|
||||||
|
for (uint16_t i =0; i< pwdCount; ++i) {
|
||||||
|
|
||||||
|
if (BUTTON_PRESS() && !usb_poll_validate_length()) {
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd = bytes_to_num(pwds + i * 4, 4);
|
||||||
|
|
||||||
|
|
||||||
|
T55xxReadBlock(5, 0, pwd);
|
||||||
|
|
||||||
|
// calc mean of BigBuf 1024 samples.
|
||||||
|
uint32_t sum = 0;
|
||||||
|
for (uint16_t j=0; j<1024; ++j) {
|
||||||
|
sum += buf[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
sum *= sum;
|
||||||
|
sum >>= 8;
|
||||||
|
|
||||||
|
int32_t tmp = (sum - baseline);
|
||||||
|
curr = ABS(tmp);
|
||||||
|
|
||||||
|
Dbprintf("[=] Pwd %08X | ABS %u", pwd, curr );
|
||||||
|
|
||||||
|
if ( curr > prev ) {
|
||||||
|
|
||||||
|
|
||||||
|
Dbprintf("[=] --> ABS %u Candidate %08X <--", curr, pwd );
|
||||||
|
candidate = pwd;
|
||||||
|
prev = curr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( candidate )
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
OUT:
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
cmd_send(CMD_ACK,ret,candidate,0,0,0);
|
||||||
|
LEDsoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void T55xxWakeUp(uint32_t Pwd){
|
void T55xxWakeUp(uint32_t Pwd){
|
||||||
|
@ -1970,7 +2089,6 @@ void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd) {
|
||||||
//Wait 20ms for write to complete?
|
//Wait 20ms for write to complete?
|
||||||
WaitMS(7);
|
WaitMS(7);
|
||||||
|
|
||||||
//Capture response if one exists
|
|
||||||
DoPartialAcquisition(20, true, 6000, 1000);
|
DoPartialAcquisition(20, true, 6000, 1000);
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
@ -1994,7 +2112,7 @@ This triggers a COTAG tag to response
|
||||||
*/
|
*/
|
||||||
void Cotag(uint32_t arg0) {
|
void Cotag(uint32_t arg0) {
|
||||||
#ifndef OFF
|
#ifndef OFF
|
||||||
# define OFF { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2035); }
|
# define OFF(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS((x)); }
|
||||||
#endif
|
#endif
|
||||||
#ifndef ON
|
#ifndef ON
|
||||||
# define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); }
|
# define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); }
|
||||||
|
@ -2003,29 +2121,15 @@ void Cotag(uint32_t arg0) {
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
|
||||||
// Switching to LF image on FPGA. This might empty BigBuff
|
LFSetupFPGAForADC(89, true);
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
|
||||||
|
|
||||||
//clear buffer now so it does not interfere with timing later
|
//clear buffer now so it does not interfere with timing later
|
||||||
BigBuf_Clear_ext(false);
|
BigBuf_Clear_ext(false);
|
||||||
|
|
||||||
// Set up FPGA, 132kHz to power up the tag
|
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 89);
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
|
||||||
|
|
||||||
// Connect the A/D to the peak-detected low-frequency path.
|
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
|
||||||
|
|
||||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
|
||||||
FpgaSetupSsc();
|
|
||||||
|
|
||||||
// start clock - 1.5ticks is 1us
|
|
||||||
StartTicks();
|
|
||||||
|
|
||||||
//send COTAG start pulse
|
//send COTAG start pulse
|
||||||
ON(740) OFF
|
ON(740) OFF(2035)
|
||||||
ON(3330) OFF
|
ON(3330) OFF(2035)
|
||||||
ON(740) OFF
|
ON(740) OFF(2035)
|
||||||
ON(1000)
|
ON(1000)
|
||||||
|
|
||||||
switch(rawsignal) {
|
switch(rawsignal) {
|
||||||
|
|
|
@ -117,21 +117,21 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) {
|
||||||
* @return the number of bits occupied by the samples.
|
* @return the number of bits occupied by the samples.
|
||||||
*/
|
*/
|
||||||
uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after) {
|
uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after) {
|
||||||
//bigbuf, to hold the aquired raw data signal
|
|
||||||
uint8_t *dest = BigBuf_get_addr();
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen();
|
bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen();
|
||||||
|
|
||||||
|
|
||||||
if (bits_per_sample < 1) bits_per_sample = 1;
|
if (bits_per_sample < 1) bits_per_sample = 1;
|
||||||
if (bits_per_sample > 8) bits_per_sample = 8;
|
if (bits_per_sample > 8) bits_per_sample = 8;
|
||||||
|
|
||||||
if (decimation < 1) decimation = 1;
|
if (decimation < 1) decimation = 1;
|
||||||
|
|
||||||
// Use a bit stream to handle the output
|
// use a bit stream to handle the output
|
||||||
BitstreamOut data = { dest , 0, 0};
|
BitstreamOut data = { dest , 0, 0};
|
||||||
int sample_counter = 0;
|
int sample_counter = 0;
|
||||||
uint8_t sample = 0;
|
uint8_t sample = 0;
|
||||||
//If we want to do averaging
|
|
||||||
|
// if we want to do averaging
|
||||||
uint32_t sample_sum =0 ;
|
uint32_t sample_sum =0 ;
|
||||||
uint32_t sample_total_numbers = 0;
|
uint32_t sample_total_numbers = 0;
|
||||||
uint32_t sample_total_saved = 0;
|
uint32_t sample_total_saved = 0;
|
||||||
|
@ -139,13 +139,13 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
|
||||||
|
|
||||||
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) {
|
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
|
||||||
LED_D_ON();
|
|
||||||
}
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
|
||||||
|
// Testpoint 8 (TP8) can be used to trigger oscilliscope
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
||||||
// threshold either high or low values 128 = center 0. if trigger = 178
|
// threshold either high or low values 128 = center 0. if trigger = 178
|
||||||
if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
|
if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
|
||||||
if (cancel_after > 0) {
|
if (cancel_after > 0) {
|
||||||
|
@ -162,24 +162,26 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
|
||||||
if (averaging)
|
if (averaging)
|
||||||
sample_sum += sample;
|
sample_sum += sample;
|
||||||
|
|
||||||
//Check decimation
|
// check decimation
|
||||||
if (decimation > 1) {
|
if (decimation > 1) {
|
||||||
sample_counter++;
|
sample_counter++;
|
||||||
if (sample_counter < decimation) continue;
|
if (sample_counter < decimation) continue;
|
||||||
sample_counter = 0;
|
sample_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Averaging
|
// averaging
|
||||||
if (averaging && decimation > 1) {
|
if (averaging && decimation > 1) {
|
||||||
sample = sample_sum / decimation;
|
sample = sample_sum / decimation;
|
||||||
sample_sum =0;
|
sample_sum =0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Store the sample
|
// store the sample
|
||||||
sample_total_saved ++;
|
sample_total_saved ++;
|
||||||
if (bits_per_sample == 8){
|
if (bits_per_sample == 8) {
|
||||||
dest[sample_total_saved-1] = sample;
|
dest[sample_total_saved-1] = sample;
|
||||||
data.numbits = sample_total_saved << 3;//Get the return value correct
|
|
||||||
|
// Get the return value correct
|
||||||
|
data.numbits = sample_total_saved << 3;
|
||||||
if (sample_total_saved >= bufsize) break;
|
if (sample_total_saved >= bufsize) break;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -190,9 +192,8 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
|
||||||
if (bits_per_sample > 4) pushBit(&data, sample & 0x08);
|
if (bits_per_sample > 4) pushBit(&data, sample & 0x08);
|
||||||
if (bits_per_sample > 5) pushBit(&data, sample & 0x04);
|
if (bits_per_sample > 5) pushBit(&data, sample & 0x04);
|
||||||
if (bits_per_sample > 6) pushBit(&data, sample & 0x02);
|
if (bits_per_sample > 6) pushBit(&data, sample & 0x02);
|
||||||
//Not needed, 8bps is covered above
|
|
||||||
//if (bits_per_sample > 7) pushBit(&data, sample & 0x01);
|
if ((data.numbits >> 3) + 1 >= bufsize) break;
|
||||||
if ((data.numbits >> 3) +1 >= bufsize) break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,10 +286,8 @@ void doT55x7Acquisition(size_t sample_size) {
|
||||||
|
|
||||||
while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) {
|
while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x43; //43
|
|
||||||
LED_D_ON();
|
|
||||||
}
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||||
curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
@ -352,11 +351,7 @@ void doCotagAcquisition(size_t sample_size) {
|
||||||
|
|
||||||
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) {
|
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
|
||||||
LED_D_ON();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
@ -406,12 +401,8 @@ uint32_t doCotagAcquisitionManchester() {
|
||||||
uint16_t noise_counter = 0;
|
uint16_t noise_counter = 0;
|
||||||
|
|
||||||
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) {
|
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
|
||||||
LED_D_ON();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
|
@ -1259,7 +1259,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
|
||||||
if ( firstchunk ) {
|
if ( firstchunk ) {
|
||||||
|
|
||||||
clear_trace();
|
clear_trace();
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
|
|
||||||
|
@ -1458,26 +1457,31 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
|
||||||
} // end loop sectors
|
} // end loop sectors
|
||||||
} // end loop keys
|
} // end loop keys
|
||||||
} // end loop strategy 2
|
} // end loop strategy 2
|
||||||
OUT:
|
OUT:
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
|
|
||||||
crypto1_destroy(pcs);
|
crypto1_destroy(pcs);
|
||||||
|
|
||||||
// All keys found, send to client, or last keychunk from client
|
// All keys found, send to client, or last keychunk from client
|
||||||
if (foundkeys == allkeys || lastchunk ) {
|
if (foundkeys == allkeys || lastchunk ) {
|
||||||
|
|
||||||
uint64_t foo = 0;
|
uint64_t foo = 0;
|
||||||
|
for (uint8_t m = 0; m < 64; m++) {
|
||||||
|
foo |= ((uint64_t)(found[m] & 1) << m);
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t bar = 0;
|
uint16_t bar = 0;
|
||||||
for (uint8_t m = 0; m < 64; ++m)
|
uint8_t j = 0;
|
||||||
foo |= (found[m] << m);
|
for (uint8_t m=64; m < sizeof(found); m++) {
|
||||||
for (uint8_t m=64; m < sizeof(found); ++m)
|
bar |= ((uint16_t)(found[m] & 1) << j++);
|
||||||
bar |= (found[m] << (m-64));
|
}
|
||||||
|
|
||||||
uint8_t *tmp = BigBuf_malloc(480+10);
|
uint8_t *tmp = BigBuf_malloc(480+10);
|
||||||
memcpy(tmp, k_sector, sectorcnt * sizeof(sector_t) );
|
memcpy(tmp, k_sector, sectorcnt * sizeof(sector_t) );
|
||||||
num_to_bytes(foo, 8, tmp+480);
|
num_to_bytes(foo, 8, tmp+480);
|
||||||
tmp[488] = bar & 0xFF;
|
tmp[488] = bar & 0xFF;
|
||||||
tmp[489] = bar >> 8 & 0xFF;
|
tmp[489] = bar >> 8 & 0xFF;
|
||||||
|
|
||||||
cmd_send(CMD_ACK, foundkeys, 0, 0, tmp, 480+10);
|
cmd_send(CMD_ACK, foundkeys, 0, 0, tmp, 480+10);
|
||||||
|
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
*
|
*
|
||||||
* This is free software: you can redistribute it and/or modify
|
* This is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as published
|
* it under the terms of the GNU General Public License version 2 as published
|
||||||
* by the Free Software Foundation.
|
* by the Free Software Foundation, or, at your option, any later version.
|
||||||
*
|
*
|
||||||
* This file is distributed in the hope that it will be useful,
|
* This file is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|
|
@ -299,29 +299,29 @@ lualibs/mf_default_keys.lua : default_keys.dic
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) $(CLEAN)
|
$(RM) $(CLEAN)
|
||||||
cd ../liblua && make clean
|
cd ../liblua && $(MAKE) clean
|
||||||
cd $(JANSSONLIBPATH) && make clean
|
cd $(JANSSONLIBPATH) && $(MAKE) clean
|
||||||
cd $(MBEDTLSLIBPATH) && make clean
|
cd $(MBEDTLSLIBPATH) && $(MAKE) clean
|
||||||
cd $(CBORLIBPATH) && make clean
|
cd $(CBORLIBPATH) && $(MAKE) clean
|
||||||
|
|
||||||
tarbin: $(BINS)
|
tarbin: $(BINS)
|
||||||
$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%)
|
$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%)
|
||||||
|
|
||||||
lua_build:
|
lua_build:
|
||||||
@echo Compiling liblua, using platform $(LUAPLATFORM)
|
@echo Compiling liblua, using platform $(LUAPLATFORM)
|
||||||
cd ../liblua && make $(LUAPLATFORM)
|
cd ../liblua && $(MAKE) $(LUAPLATFORM)
|
||||||
|
|
||||||
jansson_build:
|
jansson_build:
|
||||||
@echo Compiling jansson
|
@echo Compiling jansson
|
||||||
cd $(JANSSONLIBPATH) && make all
|
cd $(JANSSONLIBPATH) && $(MAKE) all
|
||||||
|
|
||||||
mbedtls_build:
|
mbedtls_build:
|
||||||
@echo Compiling mbedtls
|
@echo Compiling mbedtls
|
||||||
cd $(MBEDTLSLIBPATH) && make all
|
cd $(MBEDTLSLIBPATH) && $(MAKE) all
|
||||||
|
|
||||||
cbor_build:
|
cbor_build:
|
||||||
@echo Compiling tinycbor
|
@echo Compiling tinycbor
|
||||||
cd $(CBORLIBPATH) && make all
|
cd $(CBORLIBPATH) && $(MAKE) all
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
|
|
|
@ -1786,7 +1786,7 @@ int Cmdbin2hex(const char *Cmd) {
|
||||||
//Number of digits supplied as argument
|
//Number of digits supplied as argument
|
||||||
size_t length = en - bg + 1;
|
size_t length = en - bg + 1;
|
||||||
size_t bytelen = (length+7) / 8;
|
size_t bytelen = (length+7) / 8;
|
||||||
uint8_t* arr = (uint8_t *) malloc(bytelen);
|
uint8_t* arr = (uint8_t *) calloc(bytelen, sizeof(uint8_t));
|
||||||
memset(arr, 0, bytelen);
|
memset(arr, 0, bytelen);
|
||||||
BitstreamOut bout = { arr, 0, 0 };
|
BitstreamOut bout = { arr, 0, 0 };
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Proxmark3 RDV40 Flash memory commands
|
// Proxmark3 RDV40 Flash memory commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifdef WITH_FLASH
|
||||||
|
|
||||||
#include "cmdflashmem.h"
|
#include "cmdflashmem.h"
|
||||||
|
|
||||||
#include "mbedtls/rsa.h"
|
#include "mbedtls/rsa.h"
|
||||||
|
@ -604,3 +606,5 @@ int CmdHelp(const char *Cmd) {
|
||||||
CmdsHelp(CommandTable);
|
CmdsHelp(CommandTable);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -8,6 +8,8 @@
|
||||||
// Proxmark3 RDV40 Flash memory commands
|
// Proxmark3 RDV40 Flash memory commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef WITH_FLASH
|
||||||
|
|
||||||
#ifndef CMDFLASHMEM_H__
|
#ifndef CMDFLASHMEM_H__
|
||||||
#define CMDFLASHMEM_H__
|
#define CMDFLASHMEM_H__
|
||||||
|
|
||||||
|
@ -38,4 +40,6 @@ extern int CmdFlashMemLoad(const char* cmd);
|
||||||
extern int CmdFlashMemSave(const char* cmd);
|
extern int CmdFlashMemSave(const char* cmd);
|
||||||
extern int CmdFlashMemWipe(const char *Cmd);
|
extern int CmdFlashMemWipe(const char *Cmd);
|
||||||
extern int CmdFlashMemInfo(const char *Cmd);
|
extern int CmdFlashMemInfo(const char *Cmd);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,6 +1,6 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
|
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
|
||||||
// 2011, 2017 Merlok
|
// 2011, 2017 - 2019 Merlok
|
||||||
// 2014, Peter Fillmore
|
// 2014, Peter Fillmore
|
||||||
// 2015, 2016, 2017 Iceman
|
// 2015, 2016, 2017 Iceman
|
||||||
//
|
//
|
||||||
|
@ -12,6 +12,8 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "cmdhf14a.h"
|
#include "cmdhf14a.h"
|
||||||
|
|
||||||
|
bool APDUInFramingEnable = true;
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
static int waitCmd(uint8_t iLen);
|
static int waitCmd(uint8_t iLen);
|
||||||
|
|
||||||
|
@ -147,6 +149,10 @@ char* getTagInfo(uint8_t uid) {
|
||||||
return manufactureMapping[len-1].desc;
|
return manufactureMapping[len-1].desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// iso14a apdu input frame length
|
||||||
|
static uint16_t frameLength = 0;
|
||||||
|
uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
|
||||||
|
|
||||||
int usage_hf_14a_sim(void) {
|
int usage_hf_14a_sim(void) {
|
||||||
// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n");
|
// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n");
|
||||||
PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n");
|
PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n");
|
||||||
|
@ -486,10 +492,7 @@ int CmdHF14AInfo(const char *Cmd) {
|
||||||
(tb1 ? "" : " NOT"),
|
(tb1 ? "" : " NOT"),
|
||||||
(tc1 ? "" : " NOT"),
|
(tc1 ? "" : " NOT"),
|
||||||
fsci,
|
fsci,
|
||||||
fsci < 5 ? (fsci - 2) * 8 :
|
fsci < sizeof(atsFSC) ? atsFSC[fsci] : -1
|
||||||
fsci < 8 ? (fsci - 3) * 32 :
|
|
||||||
fsci == 8 ? 256 :
|
|
||||||
-1
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
pos = 2;
|
pos = 2;
|
||||||
|
@ -836,15 +839,90 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chaining) {
|
int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) {
|
||||||
uint16_t cmdc = 0;
|
UsbCommand resp;
|
||||||
|
|
||||||
*chaining = false;
|
frameLength = 0;
|
||||||
|
|
||||||
|
if (card)
|
||||||
|
memset(card, 0, sizeof(iso14a_card_select_t));
|
||||||
|
|
||||||
if (activateField) {
|
DropField();
|
||||||
cmdc |= ISO14A_CONNECT;
|
|
||||||
|
// Anticollision + SELECT card
|
||||||
|
UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
|
||||||
|
SendCommand(&ca);
|
||||||
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
|
PrintAndLogEx(ERR, "Proxmark connection timeout.");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check result
|
||||||
|
if (resp.arg[0] == 0) {
|
||||||
|
PrintAndLogEx(ERR, "No card in field.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.arg[0] != 1 && resp.arg[0] != 2) {
|
||||||
|
PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
|
||||||
|
// get ATS
|
||||||
|
UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}};
|
||||||
|
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
|
||||||
|
memcpy(cr.d.asBytes, rats, 2);
|
||||||
|
SendCommand(&cr);
|
||||||
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
|
PrintAndLogEx(ERR, "Proxmark connection timeout.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.arg[0] <= 0) { // ats_len
|
||||||
|
PrintAndLogEx(ERR, "Can't get ATS.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get frame length from ATS in data field
|
||||||
|
if (resp.arg[0] > 1) {
|
||||||
|
uint8_t fsci = resp.d.asBytes[1] & 0x0f;
|
||||||
|
if (fsci < sizeof(atsFSC))
|
||||||
|
frameLength = atsFSC[fsci];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// get frame length from ATS in card data structure
|
||||||
|
iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.d.asBytes;
|
||||||
|
if (vcard->ats_len > 1) {
|
||||||
|
uint8_t fsci = vcard->ats[1] & 0x0f;
|
||||||
|
if (fsci < sizeof(atsFSC))
|
||||||
|
frameLength = atsFSC[fsci];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card)
|
||||||
|
memcpy(card, vcard, sizeof(iso14a_card_select_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disconnect)
|
||||||
|
DropField();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) {
|
||||||
|
*chainingout = false;
|
||||||
|
|
||||||
|
if (activateField) {
|
||||||
|
// select with no disconnect and set frameLength
|
||||||
|
int selres = SelectCard14443_4(false, NULL);
|
||||||
|
if (selres)
|
||||||
|
return selres;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t cmdc = 0;
|
||||||
|
if (chainingin)
|
||||||
|
cmdc = ISO14A_SEND_CHAINING;
|
||||||
|
|
||||||
// "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
|
// "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
|
||||||
// https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
|
// https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
|
||||||
// here length USB_CMD_DATA_SIZE=512
|
// here length USB_CMD_DATA_SIZE=512
|
||||||
|
@ -856,18 +934,6 @@ int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t
|
||||||
uint8_t *recv;
|
uint8_t *recv;
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
|
|
||||||
if (activateField) {
|
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
|
||||||
PrintAndLogEx(ERR, "APDU: Proxmark connection timeout.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (resp.arg[0] != 1) {
|
|
||||||
PrintAndLogEx(ERR, "APDU: Proxmark error %d.", resp.arg[0]);
|
|
||||||
DropField();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
recv = resp.d.asBytes;
|
recv = resp.d.asBytes;
|
||||||
int iLen = resp.arg[0];
|
int iLen = resp.arg[0];
|
||||||
|
@ -883,13 +949,20 @@ int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I-block ACK
|
||||||
|
if ((res & 0xf2) == 0xa2) {
|
||||||
|
*dataoutlen = 0;
|
||||||
|
*chainingout = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(!iLen) {
|
if(!iLen) {
|
||||||
PrintAndLogEx(ERR, "APDU: No APDU response.");
|
PrintAndLogEx(ERR, "APDU: No APDU response.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check apdu length
|
// check apdu length
|
||||||
if (iLen < 4 && iLen >= 0) {
|
if (iLen < 2 && iLen >= 0) {
|
||||||
PrintAndLogEx(ERR, "APDU: Small APDU response. Len=%d", iLen);
|
PrintAndLogEx(ERR, "APDU: Small APDU response. Len=%d", iLen);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -904,7 +977,7 @@ int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t
|
||||||
|
|
||||||
// chaining
|
// chaining
|
||||||
if ((res & 0x10) != 0) {
|
if ((res & 0x10) != 0) {
|
||||||
*chaining = true;
|
*chainingout = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRC Check
|
// CRC Check
|
||||||
|
@ -923,12 +996,57 @@ int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t
|
||||||
int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
|
int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
|
||||||
*dataoutlen = 0;
|
*dataoutlen = 0;
|
||||||
bool chaining = false;
|
bool chaining = false;
|
||||||
|
int res;
|
||||||
int res = CmdExchangeAPDU(datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining);
|
|
||||||
|
|
||||||
|
// 3 byte here - 1b framing header, 2b crc16
|
||||||
|
if (APDUInFramingEnable &&
|
||||||
|
( (frameLength && (datainlen > frameLength - 3)) || (datainlen > USB_CMD_DATA_SIZE - 3)) ) {
|
||||||
|
int clen = 0;
|
||||||
|
|
||||||
|
bool vActivateField = activateField;
|
||||||
|
|
||||||
|
do {
|
||||||
|
int vlen = MIN(frameLength - 3, datainlen - clen);
|
||||||
|
bool chainBlockNotLast = ((clen + vlen) < datainlen);
|
||||||
|
|
||||||
|
*dataoutlen = 0;
|
||||||
|
res = CmdExchangeAPDU(chainBlockNotLast, &datain[clen], vlen, vActivateField, dataout, maxdataoutlen, dataoutlen, &chaining);
|
||||||
|
if (res) {
|
||||||
|
if (!leaveSignalON)
|
||||||
|
DropField();
|
||||||
|
|
||||||
|
return 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check R-block ACK
|
||||||
|
if ((*dataoutlen == 0) && (*dataoutlen != 0 || chaining != chainBlockNotLast)) {
|
||||||
|
if (!leaveSignalON)
|
||||||
|
DropField();
|
||||||
|
|
||||||
|
return 201;
|
||||||
|
}
|
||||||
|
|
||||||
|
clen += vlen;
|
||||||
|
vActivateField = false;
|
||||||
|
if (*dataoutlen) {
|
||||||
|
if (clen != datainlen)
|
||||||
|
PrintAndLogEx(WARNING, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (clen < datainlen);
|
||||||
|
} else {
|
||||||
|
res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining);
|
||||||
|
if (res) {
|
||||||
|
if (!leaveSignalON)
|
||||||
|
DropField();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (chaining) {
|
while (chaining) {
|
||||||
// I-block with chaining
|
// I-block with chaining
|
||||||
res = CmdExchangeAPDU(NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining);
|
res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining);
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
if (!leaveSignalON)
|
if (!leaveSignalON)
|
||||||
|
@ -1205,16 +1323,48 @@ int CmdHF14AAntiFuzz(const char *cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CmdHF14AChaining(const char *cmd) {
|
||||||
|
|
||||||
|
CLIParserInit("hf 14a chaining",
|
||||||
|
"Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
|
||||||
|
"Usage:\n"
|
||||||
|
"\thf 14a chaining disable -> disable chaining\n"
|
||||||
|
"\thf 14a chaining -> show chaining enable/disable state\n");
|
||||||
|
|
||||||
|
void* argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_str0(NULL, NULL, "<enable/disable or 0/1>", NULL),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(cmd, argtable, true);
|
||||||
|
|
||||||
|
struct arg_str *str = arg_get_str(1);
|
||||||
|
int len = arg_get_str_len(1);
|
||||||
|
|
||||||
|
if (len && (!strcmp(str->sval[0], "enable") || !strcmp(str->sval[0], "1")))
|
||||||
|
APDUInFramingEnable = true;
|
||||||
|
|
||||||
|
if (len && (!strcmp(str->sval[0], "disable") || !strcmp(str->sval[0], "0")))
|
||||||
|
APDUInFramingEnable = false;
|
||||||
|
|
||||||
|
CLIParserFree();
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, 1, "This help"},
|
{"help", CmdHelp, 1, "This help"},
|
||||||
{"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443-a history"},
|
{"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443-a history"},
|
||||||
{"info", CmdHF14AInfo, 0, "Tag information"},
|
{"info", CmdHF14AInfo, 0, "Tag information"},
|
||||||
{"reader", CmdHF14AReader, 0, "Act like an ISO14443-a reader"},
|
{"reader", CmdHF14AReader, 0, "Act like an ISO14443-a reader"},
|
||||||
{"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443-a UIDs in one go"},
|
{"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443-a UIDs in one go"},
|
||||||
{"sim", CmdHF14ASim, 0, "<UID> -- Simulate ISO 14443-a tag"},
|
{"sim", CmdHF14ASim, 0, "<UID> -- Simulate ISO 14443-a tag"},
|
||||||
{"sniff", CmdHF14ASniff, 0, "sniff ISO 14443-a traffic"},
|
{"sniff", CmdHF14ASniff, 0, "sniff ISO 14443-a traffic"},
|
||||||
{"apdu", CmdHF14AAPDU, 0, "Send ISO 14443-4 APDU to tag"},
|
{"apdu", CmdHF14AAPDU, 0, "Send ISO 14443-4 APDU to tag"},
|
||||||
{"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"},
|
{"chaining", CmdHF14AChaining, 0, "Control ISO 14443-4 input chaining"},
|
||||||
|
{"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"},
|
||||||
{"antifuzz", CmdHF14AAntiFuzz, 0, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
|
{"antifuzz", CmdHF14AAntiFuzz, 0, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -519,21 +519,21 @@ int CmdHF15Info(const char *Cmd) {
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
|
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
|
||||||
PrintAndLogEx(NORMAL, "iso15693 card select failed");
|
PrintAndLogEx(WARNING, "iso15693 card select failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t status = resp.arg[0];
|
uint32_t status = resp.arg[0];
|
||||||
|
|
||||||
if ( status < 2 ) {
|
if ( status < 2 ) {
|
||||||
PrintAndLogEx(NORMAL, "iso15693 card doesn't answer to systeminfo command");
|
PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
recv = resp.d.asBytes;
|
recv = resp.d.asBytes;
|
||||||
|
|
||||||
if ( recv[0] & ISO15_RES_ERROR ) {
|
if ( recv[0] & ISO15_RES_ERROR ) {
|
||||||
PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0]));
|
PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0]));
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,8 +575,8 @@ int CmdHF15Info(const char *Cmd) {
|
||||||
// Record Activity without enabeling carrier
|
// Record Activity without enabeling carrier
|
||||||
//helptext
|
//helptext
|
||||||
int CmdHF15Record(const char *Cmd) {
|
int CmdHF15Record(const char *Cmd) {
|
||||||
char cmdp = param_getchar(Cmd, 0);
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
if (cmdp == 'h' || cmdp == 'H') return usage_15_record();
|
if (cmdp == 'h') return usage_15_record();
|
||||||
|
|
||||||
UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}};
|
UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}};
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
@ -598,8 +598,8 @@ int HF15Reader(const char *Cmd, bool verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF15Reader(const char *Cmd) {
|
int CmdHF15Reader(const char *Cmd) {
|
||||||
char cmdp = param_getchar(Cmd, 0);
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
if (cmdp == 'h' || cmdp == 'H') return usage_15_reader();
|
if (cmdp == 'h') return usage_15_reader();
|
||||||
|
|
||||||
HF15Reader(Cmd, true);
|
HF15Reader(Cmd, true);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -608,16 +608,16 @@ int CmdHF15Reader(const char *Cmd) {
|
||||||
// Simulation is still not working very good
|
// Simulation is still not working very good
|
||||||
// helptext
|
// helptext
|
||||||
int CmdHF15Sim(const char *Cmd) {
|
int CmdHF15Sim(const char *Cmd) {
|
||||||
char cmdp = param_getchar(Cmd, 0);
|
char cmdp =tolower(param_getchar(Cmd, 0));
|
||||||
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_15_sim();
|
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim();
|
||||||
|
|
||||||
uint8_t uid[8] = {0,0,0,0,0,0,0,0};
|
uint8_t uid[8] = {0,0,0,0,0,0,0,0};
|
||||||
if (param_gethex(Cmd, 0, uid, 16)) {
|
if (param_gethex(Cmd, 0, uid, 16)) {
|
||||||
PrintAndLogEx(NORMAL, "UID must include 16 HEX symbols");
|
PrintAndLogEx(WARNING, "UID must include 16 HEX symbols");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) );
|
PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) );
|
||||||
|
|
||||||
UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}};
|
UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}};
|
||||||
memcpy(c.d.asBytes, uid, 8);
|
memcpy(c.d.asBytes, uid, 8);
|
||||||
|
@ -630,10 +630,10 @@ int CmdHF15Sim(const char *Cmd) {
|
||||||
// (There is no standard way of reading the AFI, allthough some tags support this)
|
// (There is no standard way of reading the AFI, allthough some tags support this)
|
||||||
// helptext
|
// helptext
|
||||||
int CmdHF15Afi(const char *Cmd) {
|
int CmdHF15Afi(const char *Cmd) {
|
||||||
char cmdp = param_getchar(Cmd, 0);
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
if (cmdp == 'h' || cmdp == 'H') return usage_15_findafi();
|
if (cmdp == 'h') return usage_15_findafi();
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "press pm3-button to cancel");
|
PrintAndLogEx(SUCCESS, "press pm3-button to cancel");
|
||||||
|
|
||||||
UsbCommand c = {CMD_ISO_15693_FIND_AFI, {strtol(Cmd, NULL, 0), 0, 0}};
|
UsbCommand c = {CMD_ISO_15693_FIND_AFI, {strtol(Cmd, NULL, 0), 0, 0}};
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
@ -689,7 +689,7 @@ int CmdHF15Dump(const char*Cmd) {
|
||||||
}
|
}
|
||||||
// detect blocksize from card :)
|
// detect blocksize from card :)
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprintUID(NULL, uid));
|
PrintAndLogEx(NORMAL, "Reading memory from tag UID " _YELLOW_(%s), sprintUID(NULL, uid));
|
||||||
|
|
||||||
int blocknum = 0;
|
int blocknum = 0;
|
||||||
uint8_t *recv = NULL;
|
uint8_t *recv = NULL;
|
||||||
|
@ -764,7 +764,7 @@ int CmdHF15Dump(const char*Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF15Restore(const char*Cmd) {
|
int CmdHF15Restore(const char*Cmd) {
|
||||||
FILE *file;
|
FILE *f;
|
||||||
|
|
||||||
uint8_t uid[8]={0x00};
|
uint8_t uid[8]={0x00};
|
||||||
char filename[FILE_PATH_SIZE] = {0x00};
|
char filename[FILE_PATH_SIZE] = {0x00};
|
||||||
|
@ -774,10 +774,10 @@ int CmdHF15Restore(const char*Cmd) {
|
||||||
char newCmdPrefix[255] = {0x00}, tmpCmd[255] = {0x00};
|
char newCmdPrefix[255] = {0x00}, tmpCmd[255] = {0x00};
|
||||||
char param[FILE_PATH_SIZE]="";
|
char param[FILE_PATH_SIZE]="";
|
||||||
char hex[255]="";
|
char hex[255]="";
|
||||||
uint8_t retries = 3, tried = 0;
|
uint8_t retries = 3, tried = 0, i = 0;
|
||||||
int retval=0;
|
int retval=0;
|
||||||
size_t bytes_read;
|
size_t bytes_read;
|
||||||
uint8_t i=0;
|
|
||||||
while(param_getchar(Cmd, cmdp) != 0x00) {
|
while(param_getchar(Cmd, cmdp) != 0x00) {
|
||||||
switch(tolower(param_getchar(Cmd, cmdp))) {
|
switch(tolower(param_getchar(Cmd, cmdp))) {
|
||||||
case '-':
|
case '-':
|
||||||
|
@ -785,7 +785,8 @@ int CmdHF15Restore(const char*Cmd) {
|
||||||
switch(param[1])
|
switch(param[1])
|
||||||
{
|
{
|
||||||
case '2':
|
case '2':
|
||||||
case 'o': strncpy(newCmdPrefix, " ",sizeof(newCmdPrefix)-1);
|
case 'o':
|
||||||
|
strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix)-1);
|
||||||
strncat(newCmdPrefix, param, sizeof(newCmdPrefix)-1);
|
strncat(newCmdPrefix, param, sizeof(newCmdPrefix)-1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -815,18 +816,18 @@ int CmdHF15Restore(const char*Cmd) {
|
||||||
default:
|
default:
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||||
return usage_15_restore();
|
return usage_15_restore();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
cmdp++;
|
cmdp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO,"Blocksize: %u",blocksize);
|
PrintAndLogEx(INFO,"Blocksize: %u",blocksize);
|
||||||
if(filename[0]=='\0')
|
|
||||||
{
|
if ( !strlen(filename)) {
|
||||||
PrintAndLogEx(WARNING,"Please provide a filename");
|
PrintAndLogEx(WARNING,"Please provide a filename");
|
||||||
return 1;
|
return usage_15_restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((file = fopen(filename,"rb")) == NULL) {
|
if ((f = fopen(filename, "rb")) == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Could not find file %s", filename);
|
PrintAndLogEx(WARNING, "Could not find file %s", filename);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -835,40 +836,43 @@ int CmdHF15Restore(const char*Cmd) {
|
||||||
PrintAndLogEx(WARNING, "No tag found");
|
PrintAndLogEx(WARNING, "No tag found");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
tried=0;
|
tried = 0;
|
||||||
hex[0]=0x00;
|
hex[0] = 0x00;
|
||||||
tmpCmd[0]=0x00;
|
tmpCmd[0] = 0x00;
|
||||||
|
|
||||||
bytes_read = fread( buff, 1, blocksize, file );
|
bytes_read = fread( buff, 1, blocksize, f );
|
||||||
if ( bytes_read == 0) {
|
if ( bytes_read == 0) {
|
||||||
PrintAndLogEx(SUCCESS, "File reading done (%s).", filename);
|
PrintAndLogEx(SUCCESS, "File reading done `%s`", filename);
|
||||||
fclose(file);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else if ( bytes_read != blocksize) {
|
||||||
else if ( bytes_read != blocksize) {
|
|
||||||
PrintAndLogEx(WARNING, "File reading error (%s), %u bytes read instead of %u bytes.", filename, bytes_read, blocksize);
|
PrintAndLogEx(WARNING, "File reading error (%s), %u bytes read instead of %u bytes.", filename, bytes_read, blocksize);
|
||||||
fclose(file);
|
fclose(f);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
for(int j=0;j<blocksize;j++)
|
|
||||||
snprintf(hex+j*2,3,"%02X", (unsigned char)buff[j]);
|
for(int j=0; j < blocksize; j++)
|
||||||
for(int j=0;j<sizeof(uid)/sizeof(uid[0]);j++)
|
snprintf(hex+j*2, 3, "%02X", buff[j]);
|
||||||
|
|
||||||
|
for(int j=0; j < sizeof(uid)/sizeof(uid[0]); j++)
|
||||||
snprintf(buff+j*2,3,"%02X", uid[j]);
|
snprintf(buff+j*2,3,"%02X", uid[j]);
|
||||||
|
|
||||||
//TODO: Addressed mode currently not work
|
//TODO: Addressed mode currently not work
|
||||||
//snprintf(tmpCmd, sizeof(tmpCmd), "%s %s %d %s", newCmdPrefix, buff, i, hex);
|
//snprintf(tmpCmd, sizeof(tmpCmd), "%s %s %d %s", newCmdPrefix, buff, i, hex);
|
||||||
snprintf(tmpCmd, sizeof(tmpCmd), "%s u %d %s", newCmdPrefix, i, hex);
|
snprintf(tmpCmd, sizeof(tmpCmd), "%s u %u %s", newCmdPrefix, i, hex);
|
||||||
PrintAndLogEx(DEBUG, "Command to be sent: %s", tmpCmd);
|
PrintAndLogEx(DEBUG, "Command to be sent| %s", tmpCmd);
|
||||||
|
|
||||||
for(tried=0;tried<retries;tried++)
|
for(tried=0; tried < retries; tried++)
|
||||||
if(!(retval=CmdHF15Write(tmpCmd)))
|
if(!(retval = CmdHF15Write(tmpCmd)))
|
||||||
break;
|
break;
|
||||||
if(tried >= retries)
|
if(tried >= retries)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
fclose(file);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF15List(const char *Cmd) {
|
int CmdHF15List(const char *Cmd) {
|
||||||
|
@ -1241,7 +1245,7 @@ int CmdHF15Write(const char *Cmd) {
|
||||||
AddCrc(req, reqlen);
|
AddCrc(req, reqlen);
|
||||||
c.arg[0] = reqlen+2;
|
c.arg[0] = reqlen+2;
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x&02X) | data ", pagenum, pagenum);
|
PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum);
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
|
@ -43,7 +43,7 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
|
||||||
PrintAndLogEx(FAILED, "Error in step %d, Return code: %d",resp.arg[0],(int)resp.arg[1]);
|
PrintAndLogEx(FAILED, "Error in step %d, Return code: %d",resp.arg[0],(int)resp.arg[1]);
|
||||||
} else {
|
} else {
|
||||||
size_t nonce_length = resp.arg[1];
|
size_t nonce_length = resp.arg[1];
|
||||||
char *nonce = (char *) malloc(2 * nonce_length + 1);
|
char *nonce = (char *) calloc(2 * nonce_length + 1, sizeof(uint8_t));
|
||||||
for(int j = 0; j < nonce_length; j++) {
|
for(int j = 0; j < nonce_length; j++) {
|
||||||
sprintf(nonce + (2 * j), "%02X", resp.d.asBytes[j]);
|
sprintf(nonce + (2 * j), "%02X", resp.d.asBytes[j]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -404,7 +404,7 @@ int CmdHFiClassSim(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
size_t datalen = NUM_CSNS * 24;
|
size_t datalen = NUM_CSNS * 24;
|
||||||
void* dump = malloc(datalen);
|
void* dump = calloc(datalen, sizeof(uint8_t));
|
||||||
if ( !dump ) {
|
if ( !dump ) {
|
||||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -456,7 +456,7 @@ int CmdHFiClassSim(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
size_t datalen = NUM_CSNS * 24;
|
size_t datalen = NUM_CSNS * 24;
|
||||||
void* dump = malloc(datalen);
|
void* dump = calloc(datalen, sizeof(uint8_t));
|
||||||
if ( !dump ) {
|
if ( !dump ) {
|
||||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -2463,7 +2463,7 @@ static void shave(uint8_t *data, uint8_t len){
|
||||||
data[i] &= 0xFE;
|
data[i] &= 0xFE;
|
||||||
}
|
}
|
||||||
static void generate_rev(uint8_t *data, uint8_t len) {
|
static void generate_rev(uint8_t *data, uint8_t len) {
|
||||||
uint8_t *key = calloc(len,1);
|
uint8_t *key = calloc(len, sizeof(uint8_t));
|
||||||
PrintAndLogEx(SUCCESS, "input permuted key | %s \n", sprint_hex(data, len));
|
PrintAndLogEx(SUCCESS, "input permuted key | %s \n", sprint_hex(data, len));
|
||||||
permute_rev(data, len, key);
|
permute_rev(data, len, key);
|
||||||
PrintAndLogEx(SUCCESS, " unpermuted key | %s \n", sprint_hex(key, len));
|
PrintAndLogEx(SUCCESS, " unpermuted key | %s \n", sprint_hex(key, len));
|
||||||
|
@ -2472,8 +2472,8 @@ static void generate_rev(uint8_t *data, uint8_t len) {
|
||||||
free(key);
|
free(key);
|
||||||
}
|
}
|
||||||
static void generate(uint8_t *data, uint8_t len) {
|
static void generate(uint8_t *data, uint8_t len) {
|
||||||
uint8_t *key = calloc(len,1);
|
uint8_t *key = calloc(len, sizeof(uint8_t));
|
||||||
uint8_t *pkey = calloc(len,1);
|
uint8_t *pkey = calloc(len, sizeof(uint8_t));
|
||||||
PrintAndLogEx(SUCCESS, " input key | %s \n", sprint_hex(data, len));
|
PrintAndLogEx(SUCCESS, " input key | %s \n", sprint_hex(data, len));
|
||||||
permute(data, len, pkey);
|
permute(data, len, pkey);
|
||||||
PrintAndLogEx(SUCCESS, "permuted key | %s \n", sprint_hex(pkey, len));
|
PrintAndLogEx(SUCCESS, "permuted key | %s \n", sprint_hex(pkey, len));
|
||||||
|
|
|
@ -180,15 +180,14 @@ int CmdLegicInfo(const char *Cmd) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Reading tag memory %d b...", card.cardsize);
|
PrintAndLogEx(SUCCESS, "Reading tag memory %d b...", card.cardsize);
|
||||||
|
|
||||||
// allocate receiver buffer
|
// allocate receiver buffer
|
||||||
uint8_t *data = malloc(card.cardsize);
|
uint8_t *data = calloc(card.cardsize, sizeof(uint8_t));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
PrintAndLogEx(WARNING, "Cannot allocate memory");
|
PrintAndLogEx(WARNING, "Cannot allocate memory");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
memset(data, 0, card.cardsize);
|
|
||||||
|
|
||||||
int status = legic_read_mem(0, card.cardsize, 0x55, data, &datalen);
|
int status = legic_read_mem(0, card.cardsize, 0x55, data, &datalen);
|
||||||
if ( status > 0 ) {
|
if ( status > 0 ) {
|
||||||
|
@ -480,15 +479,20 @@ int CmdLegicRdmem(const char *Cmd) {
|
||||||
uint16_t datalen = 0;
|
uint16_t datalen = 0;
|
||||||
sscanf(Cmd, "%x %x %x", &offset, &len, &iv);
|
sscanf(Cmd, "%x %x %x", &offset, &len, &iv);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Reading %d bytes, from offset %d", len, offset);
|
// sanity checks
|
||||||
|
if ( len + offset >= MAX_LENGTH ) {
|
||||||
|
PrintAndLogEx(WARNING, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", MAX_LENGTH, len + offset);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "Reading %d bytes, from offset %d", len, offset);
|
||||||
|
|
||||||
// allocate receiver buffer
|
// allocate receiver buffer
|
||||||
uint8_t *data = malloc(len);
|
uint8_t *data = calloc(len, sizeof(uint8_t));
|
||||||
if ( !data ){
|
if ( !data ){
|
||||||
PrintAndLogEx(WARNING, "Cannot allocate memory");
|
PrintAndLogEx(WARNING, "Cannot allocate memory");
|
||||||
return 2;
|
return -2;
|
||||||
}
|
}
|
||||||
memset(data, 0, len);
|
|
||||||
|
|
||||||
int status = legic_read_mem(offset, len, iv, data, &datalen);
|
int status = legic_read_mem(offset, len, iv, data, &datalen);
|
||||||
if ( status == 0 ) {
|
if ( status == 0 ) {
|
||||||
|
@ -540,9 +544,9 @@ int CmdLegicRfWrite(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// limit number of bytes to write. This is not a 'restore' command.
|
// limit number of bytes to write. This is not a 'restore' command.
|
||||||
if ( (len>>1) > 100 ){
|
if ( (len >> 1) > 100 ){
|
||||||
PrintAndLogEx(NORMAL, "Max bound on 100bytes to write a one time.");
|
PrintAndLogEx(WARNING, "Max bound on 100bytes to write a one time.");
|
||||||
PrintAndLogEx(NORMAL, "Use the 'hf legic restore' command if you want to write the whole tag at once");
|
PrintAndLogEx(WARNING, "Use the 'hf legic restore' command if you want to write the whole tag at once");
|
||||||
errors = true;
|
errors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,7 +555,7 @@ int CmdLegicRfWrite(const char *Cmd) {
|
||||||
if (data)
|
if (data)
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
data = malloc(len >> 1);
|
data = calloc(len >> 1, sizeof(uint8_t));
|
||||||
if ( data == NULL ) {
|
if ( data == NULL ) {
|
||||||
PrintAndLogEx(WARNING, "Can't allocate memory. exiting");
|
PrintAndLogEx(WARNING, "Can't allocate memory. exiting");
|
||||||
errors = true;
|
errors = true;
|
||||||
|
@ -598,12 +602,12 @@ int CmdLegicRfWrite(const char *Cmd) {
|
||||||
// OUT-OF-BOUNDS checks
|
// OUT-OF-BOUNDS checks
|
||||||
// UID 4+1 bytes can't be written to.
|
// UID 4+1 bytes can't be written to.
|
||||||
if ( offset < 5 ) {
|
if ( offset < 5 ) {
|
||||||
PrintAndLogEx(NORMAL, "Out-of-bounds, bytes 0-1-2-3-4 can't be written to. Offset = %d", offset);
|
PrintAndLogEx(WARNING, "Out-of-bounds, bytes 0-1-2-3-4 can't be written to. Offset = %d", offset);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( len + offset >= card.cardsize ) {
|
if ( len + offset >= card.cardsize ) {
|
||||||
PrintAndLogEx(NORMAL, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset);
|
PrintAndLogEx(WARNING, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +626,7 @@ int CmdLegicRfWrite(const char *Cmd) {
|
||||||
|
|
||||||
legic_chk_iv(&IV);
|
legic_chk_iv(&IV);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Writing to tag");
|
PrintAndLogEx(SUCCESS, "Writing to tag");
|
||||||
|
|
||||||
UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}};
|
UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}};
|
||||||
memcpy(c.d.asBytes, data, len);
|
memcpy(c.d.asBytes, data, len);
|
||||||
|
@ -630,10 +634,18 @@ int CmdLegicRfWrite(const char *Cmd) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
|
||||||
PrintAndLogEx(WARNING, "command execution time out");
|
uint8_t timeout = 0;
|
||||||
return 1;
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
}
|
++timeout;
|
||||||
|
printf("."); fflush(stdout);
|
||||||
|
if (timeout > 7) {
|
||||||
|
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "\n");
|
||||||
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xFF;
|
uint8_t isOK = resp.arg[0] & 0xFF;
|
||||||
if ( !isOK ) {
|
if ( !isOK ) {
|
||||||
PrintAndLogEx(WARNING, "Failed writing tag");
|
PrintAndLogEx(WARNING, "Failed writing tag");
|
||||||
|
@ -673,7 +685,7 @@ int CmdLegicCalcCrc(const char *Cmd){
|
||||||
// it's possible for user to accidentally enter "b" parameter
|
// it's possible for user to accidentally enter "b" parameter
|
||||||
// more than once - we have to clean previous malloc
|
// more than once - we have to clean previous malloc
|
||||||
if (data) free(data);
|
if (data) free(data);
|
||||||
data = malloc(len >> 1);
|
data = calloc(len >> 1, sizeof(uint8_t) );
|
||||||
if ( data == NULL ) {
|
if ( data == NULL ) {
|
||||||
PrintAndLogEx(WARNING, "Can't allocate memory. exiting");
|
PrintAndLogEx(WARNING, "Can't allocate memory. exiting");
|
||||||
errors = true;
|
errors = true;
|
||||||
|
@ -714,10 +726,10 @@ int CmdLegicCalcCrc(const char *Cmd){
|
||||||
switch (type){
|
switch (type){
|
||||||
case 16:
|
case 16:
|
||||||
init_table(CRC_LEGIC);
|
init_table(CRC_LEGIC);
|
||||||
PrintAndLogEx(NORMAL, "Legic crc16: %X", crc16_legic(data, len, uidcrc));
|
PrintAndLogEx(SUCCESS, "Legic crc16: %X", crc16_legic(data, len, uidcrc));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PrintAndLogEx(NORMAL, "Legic crc8: %X", CRC8Legic(data, len) );
|
PrintAndLogEx(SUCCESS, "Legic crc8: %X", CRC8Legic(data, len) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -733,11 +745,18 @@ int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uin
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 3000) ) {
|
|
||||||
PrintAndLogEx(WARNING, "command execution time out");
|
uint8_t timeout = 0;
|
||||||
return 1;
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
}
|
++timeout;
|
||||||
|
printf("."); fflush(stdout);
|
||||||
|
if (timeout > 7) {
|
||||||
|
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "\n");
|
||||||
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xFF;
|
uint8_t isOK = resp.arg[0] & 0xFF;
|
||||||
*outlen = resp.arg[1];
|
*outlen = resp.arg[1];
|
||||||
if ( !isOK ) {
|
if ( !isOK ) {
|
||||||
|
@ -762,13 +781,13 @@ int legic_print_type(uint32_t tagtype, uint8_t spaces){
|
||||||
char *spacer = spc + (10-spaces);
|
char *spacer = spc + (10-spaces);
|
||||||
|
|
||||||
if ( tagtype == 22 )
|
if ( tagtype == 22 )
|
||||||
PrintAndLogEx(NORMAL, "%sTYPE : MIM%d card (outdated)", spacer, tagtype);
|
PrintAndLogEx(SUCCESS, "%sTYPE : MIM%d card (outdated)", spacer, tagtype);
|
||||||
else if ( tagtype == 256 )
|
else if ( tagtype == 256 )
|
||||||
PrintAndLogEx(NORMAL, "%sTYPE : MIM%d card (234 bytes)", spacer, tagtype);
|
PrintAndLogEx(SUCCESS, "%sTYPE : MIM%d card (234 bytes)", spacer, tagtype);
|
||||||
else if ( tagtype == 1024 )
|
else if ( tagtype == 1024 )
|
||||||
PrintAndLogEx(NORMAL, "%sTYPE : MIM%d card (1002 bytes)", spacer, tagtype);
|
PrintAndLogEx(SUCCESS, "%sTYPE : MIM%d card (1002 bytes)", spacer, tagtype);
|
||||||
else
|
else
|
||||||
PrintAndLogEx(NORMAL, "%sTYPE : Unknown %06x", spacer, tagtype);
|
PrintAndLogEx(INFO, "%sTYPE : Unknown %06x", spacer, tagtype);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int legic_get_type(legic_card_select_t *card){
|
int legic_get_type(legic_card_select_t *card){
|
||||||
|
@ -792,12 +811,12 @@ int legic_get_type(legic_card_select_t *card){
|
||||||
void legic_chk_iv(uint32_t *iv){
|
void legic_chk_iv(uint32_t *iv){
|
||||||
if ( (*iv & 0x7F) != *iv ){
|
if ( (*iv & 0x7F) != *iv ){
|
||||||
*iv &= 0x7F;
|
*iv &= 0x7F;
|
||||||
PrintAndLogEx(NORMAL, "Truncating IV to 7bits, %u", *iv);
|
PrintAndLogEx(INFO, "Truncating IV to 7bits, %u", *iv);
|
||||||
}
|
}
|
||||||
// IV must be odd
|
// IV must be odd
|
||||||
if ( (*iv & 1) == 0 ){
|
if ( (*iv & 1) == 0 ){
|
||||||
*iv |= 0x01;
|
*iv |= 0x01;
|
||||||
PrintAndLogEx(NORMAL, "LSB of IV must be SET %u", *iv);
|
PrintAndLogEx(INFO, "LSB of IV must be SET %u", *iv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) {
|
void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) {
|
||||||
|
@ -828,11 +847,11 @@ int HFLegicReader(const char *Cmd, bool verbose) {
|
||||||
if ( verbose ) PrintAndLogEx(WARNING, "command execution time out");
|
if ( verbose ) PrintAndLogEx(WARNING, "command execution time out");
|
||||||
return 1;
|
return 1;
|
||||||
case 3:
|
case 3:
|
||||||
if ( verbose ) PrintAndLogEx(NORMAL, "legic card select failed");
|
if ( verbose ) PrintAndLogEx(WARNING, "legic card select failed");
|
||||||
return 2;
|
return 2;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, sizeof(card.uid)));
|
PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, sizeof(card.uid)));
|
||||||
legic_print_type(card.cardsize, 0);
|
legic_print_type(card.cardsize, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -882,16 +901,23 @@ int CmdLegicDump(const char *Cmd){
|
||||||
dumplen = card.cardsize;
|
dumplen = card.cardsize;
|
||||||
|
|
||||||
legic_print_type(dumplen, 0);
|
legic_print_type(dumplen, 0);
|
||||||
PrintAndLogEx(NORMAL, "Reading tag memory %d b...", dumplen);
|
PrintAndLogEx(SUCCESS, "Reading tag memory %d b...", dumplen);
|
||||||
|
|
||||||
UsbCommand c = {CMD_READER_LEGIC_RF, {0x00, dumplen, 0x55}};
|
UsbCommand c = {CMD_READER_LEGIC_RF, {0x00, dumplen, 0x55}};
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) {
|
|
||||||
PrintAndLogEx(NORMAL, "Command execute time-out");
|
uint8_t timeout = 0;
|
||||||
return 1;
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
}
|
++timeout;
|
||||||
|
printf("."); fflush(stdout);
|
||||||
|
if (timeout > 7) {
|
||||||
|
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "\n");
|
||||||
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xFF;
|
uint8_t isOK = resp.arg[0] & 0xFF;
|
||||||
if ( !isOK ) {
|
if ( !isOK ) {
|
||||||
|
@ -900,12 +926,11 @@ int CmdLegicDump(const char *Cmd){
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t readlen = resp.arg[1];
|
uint16_t readlen = resp.arg[1];
|
||||||
uint8_t *data = malloc(readlen);
|
uint8_t *data = calloc(readlen, sizeof(uint8_t));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
memset(data, 0, readlen);
|
|
||||||
|
|
||||||
if ( readlen != dumplen )
|
if ( readlen != dumplen )
|
||||||
PrintAndLogEx(WARNING, "Fail, only managed to read 0x%02X bytes of 0x%02X", readlen, dumplen);
|
PrintAndLogEx(WARNING, "Fail, only managed to read 0x%02X bytes of 0x%02X", readlen, dumplen);
|
||||||
|
@ -923,7 +948,7 @@ int CmdLegicDump(const char *Cmd){
|
||||||
else
|
else
|
||||||
sprintf(fnameptr + fileNlen,".bin");
|
sprintf(fnameptr + fileNlen,".bin");
|
||||||
|
|
||||||
f = fopen(filename,"wb");
|
f = fopen(filename, "wb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
PrintAndLogEx(WARNING, "Could not create file name %s", filename);
|
PrintAndLogEx(WARNING, "Could not create file name %s", filename);
|
||||||
if (data)
|
if (data)
|
||||||
|
@ -934,7 +959,7 @@ int CmdLegicDump(const char *Cmd){
|
||||||
fflush(f);
|
fflush(f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
free(data);
|
free(data);
|
||||||
PrintAndLogEx(NORMAL, "Wrote %d bytes to %s", readlen, filename);
|
PrintAndLogEx(SUCCESS, "Wrote %d bytes to %s", readlen, filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,12 +1007,11 @@ int CmdLegicRestore(const char *Cmd){
|
||||||
numofbytes = card.cardsize;
|
numofbytes = card.cardsize;
|
||||||
|
|
||||||
// set up buffer
|
// set up buffer
|
||||||
uint8_t *data = malloc(numofbytes);
|
uint8_t *data = calloc(numofbytes, sizeof(uint8_t) );
|
||||||
if (!data) {
|
if (!data) {
|
||||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
memset(data, 0, numofbytes);
|
|
||||||
|
|
||||||
legic_print_type(numofbytes, 0);
|
legic_print_type(numofbytes, 0);
|
||||||
|
|
||||||
|
@ -997,7 +1021,7 @@ int CmdLegicRestore(const char *Cmd){
|
||||||
|
|
||||||
f = fopen(filename,"rb");
|
f = fopen(filename,"rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
PrintAndLogEx(NORMAL, "File %s not found or locked", filename);
|
PrintAndLogEx(WARNING, "File %s not found or locked", filename);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1018,12 +1042,12 @@ int CmdLegicRestore(const char *Cmd){
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
if ( bytes_read == 0){
|
if ( bytes_read == 0){
|
||||||
PrintAndLogEx(NORMAL, "File reading error");
|
PrintAndLogEx(WARNING, "File reading error");
|
||||||
free(data);
|
free(data);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Restoring to card");
|
PrintAndLogEx(SUCCESS, "Restoring to card");
|
||||||
|
|
||||||
// transfer to device
|
// transfer to device
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
@ -1038,22 +1062,29 @@ int CmdLegicRestore(const char *Cmd){
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
|
uint8_t timeout = 0;
|
||||||
PrintAndLogEx(WARNING, "command execution time out");
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
free(data);
|
++timeout;
|
||||||
return 1;
|
printf("."); fflush(stdout);
|
||||||
}
|
if (timeout > 7) {
|
||||||
|
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
||||||
|
free(data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "\n");
|
||||||
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xFF;
|
uint8_t isOK = resp.arg[0] & 0xFF;
|
||||||
if ( !isOK ) {
|
if ( !isOK ) {
|
||||||
PrintAndLogEx(WARNING, "Failed writing tag [msg = %u]", resp.arg[1] & 0xFF);
|
PrintAndLogEx(WARNING, "Failed writing tag [msg = %u]", resp.arg[1] & 0xFF);
|
||||||
free(data);
|
free(data);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "Wrote chunk [offset %d | len %d | total %d", i, len, i+len);
|
PrintAndLogEx(SUCCESS, "Wrote chunk [offset %d | len %d | total %d", i, len, i+len);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
PrintAndLogEx(NORMAL, "\nWrote %d bytes to card from file %s", numofbytes, filename);
|
PrintAndLogEx(SUCCESS, "\nWrote %d bytes to card from file %s", numofbytes, filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,12 +1108,11 @@ int CmdLegicELoad(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up buffer
|
// set up buffer
|
||||||
uint8_t *data = malloc(numofbytes);
|
uint8_t *data = calloc(numofbytes, sizeof(uint8_t));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
memset(data, 0, numofbytes);
|
|
||||||
|
|
||||||
// set up file
|
// set up file
|
||||||
len = param_getstr(Cmd, nameParamNo, filename, FILE_PATH_SIZE);
|
len = param_getstr(Cmd, nameParamNo, filename, FILE_PATH_SIZE);
|
||||||
|
@ -1094,7 +1124,7 @@ int CmdLegicELoad(const char *Cmd) {
|
||||||
// open file
|
// open file
|
||||||
f = fopen(filename,"rb");
|
f = fopen(filename,"rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
PrintAndLogEx(NORMAL, "File %s not found or locked", filename);
|
PrintAndLogEx(WARNING, "File %s not found or locked", filename);
|
||||||
free(data);
|
free(data);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1102,7 +1132,7 @@ int CmdLegicELoad(const char *Cmd) {
|
||||||
// load file
|
// load file
|
||||||
size_t bytes_read = fread(data, 1, numofbytes, f);
|
size_t bytes_read = fread(data, 1, numofbytes, f);
|
||||||
if ( bytes_read == 0){
|
if ( bytes_read == 0){
|
||||||
PrintAndLogEx(NORMAL, "File reading error");
|
PrintAndLogEx(WARNING, "File reading error");
|
||||||
free(data);
|
free(data);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
f = NULL;
|
f = NULL;
|
||||||
|
@ -1115,7 +1145,7 @@ int CmdLegicELoad(const char *Cmd) {
|
||||||
legic_seteml(data, 0, numofbytes);
|
legic_seteml(data, 0, numofbytes);
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
PrintAndLogEx(NORMAL, "\nLoaded %d bytes from file: %s to emulator memory", numofbytes, filename);
|
PrintAndLogEx(SUCCESS, "\nLoaded %d bytes from file: %s to emulator memory", numofbytes, filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1146,15 +1176,14 @@ int CmdLegicESave(const char *Cmd) {
|
||||||
fileNlen = FILE_PATH_SIZE - 5;
|
fileNlen = FILE_PATH_SIZE - 5;
|
||||||
|
|
||||||
// set up buffer
|
// set up buffer
|
||||||
uint8_t *data = malloc(numofbytes);
|
uint8_t *data = calloc(numofbytes, sizeof(uint8_t));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
memset(data, 0, numofbytes);
|
|
||||||
|
|
||||||
// download emulator memory
|
// download emulator memory
|
||||||
PrintAndLogEx(NORMAL, "Reading emulator memory...");
|
PrintAndLogEx(SUCCESS, "Reading emulator memory...");
|
||||||
if (!GetFromDevice( BIG_BUF_EML, data, numofbytes, 0, NULL, 2500, false)) {
|
if (!GetFromDevice( BIG_BUF_EML, data, numofbytes, 0, NULL, 2500, false)) {
|
||||||
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
|
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -1185,16 +1214,15 @@ int CmdLegicWipe(const char *Cmd){
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up buffer
|
// set up buffer
|
||||||
uint8_t *data = malloc(card.cardsize);
|
uint8_t *data = calloc(card.cardsize, sizeof(uint8_t));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
memset(data, 0, card.cardsize);
|
|
||||||
|
|
||||||
legic_print_type(card.cardsize, 0);
|
legic_print_type(card.cardsize, 0);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Erasing");
|
PrintAndLogEx(SUCCESS, "Erasing");
|
||||||
|
|
||||||
// transfer to device
|
// transfer to device
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
@ -1210,11 +1238,18 @@ int CmdLegicWipe(const char *Cmd){
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
|
uint8_t timeout = 0;
|
||||||
PrintAndLogEx(WARNING, "command execution time out");
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
free(data);
|
++timeout;
|
||||||
return 3;
|
printf("."); fflush(stdout);
|
||||||
}
|
if (timeout > 7) {
|
||||||
|
PrintAndLogEx(WARNING, "\ncommand execution time out");
|
||||||
|
free(data);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "\n");
|
||||||
|
|
||||||
uint8_t isOK = resp.arg[0] & 0xFF;
|
uint8_t isOK = resp.arg[0] & 0xFF;
|
||||||
if ( !isOK ) {
|
if ( !isOK ) {
|
||||||
PrintAndLogEx(WARNING, "Failed writing tag [msg = %u]", resp.arg[1] & 0xFF);
|
PrintAndLogEx(WARNING, "Failed writing tag [msg = %u]", resp.arg[1] & 0xFF);
|
||||||
|
@ -1222,7 +1257,7 @@ int CmdLegicWipe(const char *Cmd){
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "ok\n");
|
PrintAndLogEx(SUCCESS, "ok\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1236,7 +1271,7 @@ static command_t CommandTable[] = {
|
||||||
{"reader", CmdLegicReader, 1, "LEGIC Prime Reader UID and tag info"},
|
{"reader", CmdLegicReader, 1, "LEGIC Prime Reader UID and tag info"},
|
||||||
{"info", CmdLegicInfo, 0, "Display deobfuscated and decoded LEGIC Prime tag data"},
|
{"info", CmdLegicInfo, 0, "Display deobfuscated and decoded LEGIC Prime tag data"},
|
||||||
{"dump", CmdLegicDump, 0, "Dump LEGIC Prime tag to binary file"},
|
{"dump", CmdLegicDump, 0, "Dump LEGIC Prime tag to binary file"},
|
||||||
{"restore", CmdLegicRestore, 0, "Restore a dump onto a LEGIC Prime tag"},
|
{"restore", CmdLegicRestore, 0, "Restore a dump file onto a LEGIC Prime tag"},
|
||||||
{"rdmem", CmdLegicRdmem, 0, "Read bytes from a LEGIC Prime tag"},
|
{"rdmem", CmdLegicRdmem, 0, "Read bytes from a LEGIC Prime tag"},
|
||||||
{"sim", CmdLegicRfSim, 0, "Start tag simulator"},
|
{"sim", CmdLegicRfSim, 0, "Start tag simulator"},
|
||||||
{"write", CmdLegicRfWrite, 0, "Write data to a LEGIC Prime tag"},
|
{"write", CmdLegicRfWrite, 0, "Write data to a LEGIC Prime tag"},
|
||||||
|
|
|
@ -357,7 +357,7 @@ void annotateIso7816(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){
|
||||||
case ISO7816_EXTERNAL_AUTHENTICATION :snprintf(exp, size, "EXTERNAL AUTH");break;
|
case ISO7816_EXTERNAL_AUTHENTICATION :snprintf(exp, size, "EXTERNAL AUTH");break;
|
||||||
case ISO7816_GET_CHALLENGE :snprintf(exp, size, "GET CHALLENGE");break;
|
case ISO7816_GET_CHALLENGE :snprintf(exp, size, "GET CHALLENGE");break;
|
||||||
case ISO7816_MANAGE_CHANNEL :snprintf(exp, size, "MANAGE CHANNEL");break;
|
case ISO7816_MANAGE_CHANNEL :snprintf(exp, size, "MANAGE CHANNEL");break;
|
||||||
case ISO7816_GETSTATUS :snprintf(exp, size, "GET RESPONSE");break;
|
case ISO7816_GET_RESPONSE :snprintf(exp, size, "GET RESPONSE");break;
|
||||||
default :snprintf(exp,size,"?"); break;
|
default :snprintf(exp,size,"?"); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
279
client/cmdhfmf.c
279
client/cmdhfmf.c
|
@ -11,11 +11,16 @@
|
||||||
#include "cmdhfmf.h"
|
#include "cmdhfmf.h"
|
||||||
#include "mifare4.h"
|
#include "mifare4.h"
|
||||||
|
|
||||||
#define MIFARE_4K_MAXBLOCK 255
|
#define MIFARE_4K_MAXBLOCK 256
|
||||||
#define MIFARE_2K_MAXBLOCK 128
|
#define MIFARE_2K_MAXBLOCK 128
|
||||||
#define MIFARE_1K_MAXBLOCK 64
|
#define MIFARE_1K_MAXBLOCK 64
|
||||||
#define MIFARE_MINI_MAXBLOCK 20
|
#define MIFARE_MINI_MAXBLOCK 20
|
||||||
|
|
||||||
|
#define MIFARE_MINI_MAXSECTOR 5
|
||||||
|
#define MIFARE_1K_MAXSECTOR 16
|
||||||
|
#define MIFARE_2K_MAXSECTOR 32
|
||||||
|
#define MIFARE_4K_MAXSECTOR 40
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
int usage_hf14_ice(void){
|
int usage_hf14_ice(void){
|
||||||
|
@ -415,7 +420,7 @@ int GetHFMF14AUID(uint8_t *uid, int *uidlen) {
|
||||||
char * GenerateFilename(const char *prefix, const char *suffix){
|
char * GenerateFilename(const char *prefix, const char *suffix){
|
||||||
uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0};
|
uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0};
|
||||||
int uidlen=0;
|
int uidlen=0;
|
||||||
char * fptr = malloc (sizeof (char) * (strlen(prefix) + strlen(suffix)) + sizeof(uid)*2 + 1);
|
char * fptr = calloc (sizeof (char) * (strlen(prefix) + strlen(suffix)) + sizeof(uid)*2 + 1, sizeof(uint8_t));
|
||||||
|
|
||||||
GetHFMF14AUID(uid, &uidlen);
|
GetHFMF14AUID(uid, &uidlen);
|
||||||
if (!uidlen) {
|
if (!uidlen) {
|
||||||
|
@ -591,7 +596,7 @@ int CmdHF14AMfRdSc(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sectorNo = param_get8(Cmd, 0);
|
sectorNo = param_get8(Cmd, 0);
|
||||||
if (sectorNo > 39) {
|
if (sectorNo > MIFARE_4K_MAXSECTOR ) {
|
||||||
PrintAndLogEx(NORMAL, "Sector number must be less than 40");
|
PrintAndLogEx(NORMAL, "Sector number must be less than 40");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -645,7 +650,7 @@ int CmdHF14AMfRdSc(const char *Cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t NumOfBlocks(char card){
|
uint16_t NumOfBlocks(char card){
|
||||||
switch(card){
|
switch(card){
|
||||||
case '0' : return MIFARE_MINI_MAXBLOCK;
|
case '0' : return MIFARE_MINI_MAXBLOCK;
|
||||||
case '1' : return MIFARE_1K_MAXBLOCK;
|
case '1' : return MIFARE_1K_MAXBLOCK;
|
||||||
|
@ -656,11 +661,11 @@ uint8_t NumOfBlocks(char card){
|
||||||
}
|
}
|
||||||
uint8_t NumOfSectors(char card){
|
uint8_t NumOfSectors(char card){
|
||||||
switch(card){
|
switch(card){
|
||||||
case '0' : return 5;
|
case '0' : return MIFARE_MINI_MAXSECTOR;
|
||||||
case '1' : return 16;
|
case '1' : return MIFARE_1K_MAXSECTOR;
|
||||||
case '2' : return 32;
|
case '2' : return MIFARE_2K_MAXSECTOR;
|
||||||
case '4' : return 40;
|
case '4' : return MIFARE_4K_MAXSECTOR;
|
||||||
default : return 16;
|
default : return MIFARE_1K_MAXSECTOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -729,7 +734,7 @@ int CmdHF14AMfDump(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fin = fopen(keyFilename, "rb")) == NULL) {
|
if ((fin = fopen(keyFilename, "rb")) == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Could not find file %s", keyFilename);
|
PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), keyFilename);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,7 +743,7 @@ int CmdHF14AMfDump(const char *Cmd) {
|
||||||
for (sectorNo=0; sectorNo<numSectors; sectorNo++) {
|
for (sectorNo=0; sectorNo<numSectors; sectorNo++) {
|
||||||
bytes_read = fread( keyA[sectorNo], 1, 6, fin );
|
bytes_read = fread( keyA[sectorNo], 1, 6, fin );
|
||||||
if ( bytes_read != 6) {
|
if ( bytes_read != 6) {
|
||||||
PrintAndLogEx(NORMAL, "File reading error.");
|
PrintAndLogEx(WARNING, "File reading error.");
|
||||||
fclose(fin);
|
fclose(fin);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -748,7 +753,7 @@ int CmdHF14AMfDump(const char *Cmd) {
|
||||||
for (sectorNo=0; sectorNo<numSectors; sectorNo++) {
|
for (sectorNo=0; sectorNo<numSectors; sectorNo++) {
|
||||||
bytes_read = fread( keyB[sectorNo], 1, 6, fin );
|
bytes_read = fread( keyB[sectorNo], 1, 6, fin );
|
||||||
if ( bytes_read != 6) {
|
if ( bytes_read != 6) {
|
||||||
PrintAndLogEx(NORMAL, "File reading error.");
|
PrintAndLogEx(WARNING, "File reading error.");
|
||||||
fclose(fin);
|
fclose(fin);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -874,13 +879,13 @@ int CmdHF14AMfDump(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fout = fopen(dataFilename,"wb")) == NULL) {
|
if ((fout = fopen(dataFilename,"wb")) == NULL) {
|
||||||
PrintAndLogEx(WARNING, "could not create file name %s", dataFilename);
|
PrintAndLogEx(WARNING, "could not create file name " _YELLOW_(%s), dataFilename);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
uint16_t numblocks = FirstBlockOfSector(numSectors - 1) + NumBlocksPerSector(numSectors - 1);
|
uint16_t numblocks = FirstBlockOfSector(numSectors - 1) + NumBlocksPerSector(numSectors - 1);
|
||||||
fwrite(carddata, 1, 16*numblocks, fout);
|
fwrite(carddata, 1, 16*numblocks, fout);
|
||||||
fclose(fout);
|
fclose(fout);
|
||||||
PrintAndLogEx(SUCCESS, "dumped %d blocks (%d bytes) to file %s", numblocks, 16*numblocks, dataFilename);
|
PrintAndLogEx(SUCCESS, "dumped %d blocks (%d bytes) to file " _YELLOW_(%s), numblocks, 16*numblocks, dataFilename);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -940,7 +945,7 @@ int CmdHF14AMfRestore(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fkeys = fopen(keyFilename, "rb")) == NULL) {
|
if ((fkeys = fopen(keyFilename, "rb")) == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Could not find file %s", keyFilename);
|
PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), keyFilename);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,7 +953,7 @@ int CmdHF14AMfRestore(const char *Cmd) {
|
||||||
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
||||||
bytes_read = fread( keyA[sectorNo], 1, 6, fkeys );
|
bytes_read = fread( keyA[sectorNo], 1, 6, fkeys );
|
||||||
if ( bytes_read != 6 ) {
|
if ( bytes_read != 6 ) {
|
||||||
PrintAndLogEx(NORMAL, "File reading error (%s).", keyFilename);
|
PrintAndLogEx(WARNING, "File reading error " _YELLOW_(%s), keyFilename);
|
||||||
fclose(fkeys);
|
fclose(fkeys);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -957,7 +962,7 @@ int CmdHF14AMfRestore(const char *Cmd) {
|
||||||
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
||||||
bytes_read = fread( keyB[sectorNo], 1, 6, fkeys );
|
bytes_read = fread( keyB[sectorNo], 1, 6, fkeys );
|
||||||
if ( bytes_read != 6 ) {
|
if ( bytes_read != 6 ) {
|
||||||
PrintAndLogEx(NORMAL, "File reading error (%s).", keyFilename);
|
PrintAndLogEx(WARNING, "File reading error " _YELLOW_(%s), keyFilename);
|
||||||
fclose(fkeys);
|
fclose(fkeys);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -974,10 +979,10 @@ int CmdHF14AMfRestore(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fdump = fopen(dataFilename, "rb")) == NULL) {
|
if ((fdump = fopen(dataFilename, "rb")) == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Could not find file %s", dataFilename);
|
PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), dataFilename);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "Restoring %s to card", dataFilename);
|
PrintAndLogEx(INFO, "Restoring " _YELLOW_(%s)" to card", dataFilename);
|
||||||
|
|
||||||
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
|
||||||
for (blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
|
for (blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
|
||||||
|
@ -985,7 +990,7 @@ int CmdHF14AMfRestore(const char *Cmd) {
|
||||||
memcpy(c.d.asBytes, key, 6);
|
memcpy(c.d.asBytes, key, 6);
|
||||||
bytes_read = fread(bldata, 1, 16, fdump);
|
bytes_read = fread(bldata, 1, 16, fdump);
|
||||||
if ( bytes_read != 16) {
|
if ( bytes_read != 16) {
|
||||||
PrintAndLogEx(NORMAL, "File reading error (%s).", dataFilename);
|
PrintAndLogEx(WARNING, "File reading error " _YELLOW_(%s), dataFilename);
|
||||||
fclose(fdump);
|
fclose(fdump);
|
||||||
fdump = NULL;
|
fdump = NULL;
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -1015,9 +1020,9 @@ int CmdHF14AMfRestore(const char *Cmd) {
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||||
uint8_t isOK = resp.arg[0] & 0xff;
|
uint8_t isOK = resp.arg[0] & 0xff;
|
||||||
PrintAndLogEx(NORMAL, "isOk:%02x", isOK);
|
PrintAndLogEx(SUCCESS, "isOk:%02x", isOK);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(NORMAL, "Command execute timeout");
|
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1187,7 +1192,7 @@ int CmdHF14AMfNested(const char *Cmd) {
|
||||||
|
|
||||||
|
|
||||||
// 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
|
// 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
|
||||||
PrintAndLogEx(SUCCESS, "trying to read key B...");
|
PrintAndLogEx(INFO, "trying to read key B...");
|
||||||
for (i = 0; i < SectorsCnt; i++) {
|
for (i = 0; i < SectorsCnt; i++) {
|
||||||
// KEY A but not KEY B
|
// KEY A but not KEY B
|
||||||
if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) {
|
if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) {
|
||||||
|
@ -1230,8 +1235,8 @@ int CmdHF14AMfNested(const char *Cmd) {
|
||||||
if (e_sector[i].foundKey[1])
|
if (e_sector[i].foundKey[1])
|
||||||
num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]);
|
num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]);
|
||||||
mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
|
mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
|
||||||
PrintAndLogEx(SUCCESS, "key transferred to emulator memory.");
|
}
|
||||||
}
|
PrintAndLogEx(SUCCESS, "key transferred to emulator memory.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create dump file
|
// Create dump file
|
||||||
|
@ -1241,12 +1246,12 @@ int CmdHF14AMfNested(const char *Cmd) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if ((fkeys = fopen(fptr, "wb")) == NULL) {
|
if ((fkeys = fopen(fptr, "wb")) == NULL) {
|
||||||
PrintAndLogEx(WARNING, "could not create file %s", fptr);
|
PrintAndLogEx(WARNING, "could not create file " _YELLOW_(%s), fptr);
|
||||||
free(e_sector);
|
free(e_sector);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "saving keys to binary file %s...", fptr);
|
PrintAndLogEx(SUCCESS, "saving keys to binary file " _YELLOW_(%s), fptr);
|
||||||
for (i=0; i<SectorsCnt; i++) {
|
for (i=0; i<SectorsCnt; i++) {
|
||||||
if (e_sector[i].foundKey[0]){
|
if (e_sector[i].foundKey[0]){
|
||||||
num_to_bytes(e_sector[i].Key[0], 6, tempkey);
|
num_to_bytes(e_sector[i].Key[0], 6, tempkey);
|
||||||
|
@ -1314,14 +1319,14 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
default:
|
default:
|
||||||
if (param_getchar(Cmd, cmdp) == 0x00)
|
if (param_getchar(Cmd, cmdp) == 0x00)
|
||||||
{
|
{
|
||||||
PrintAndLogEx(NORMAL, "Block number is missing");
|
PrintAndLogEx(WARNING, "Block number is missing");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
blockNo = param_get8(Cmd, cmdp);
|
blockNo = param_get8(Cmd, cmdp);
|
||||||
ctmp = tolower(param_getchar(Cmd, cmdp+1));
|
ctmp = tolower(param_getchar(Cmd, cmdp+1));
|
||||||
if (ctmp != 'a' && ctmp != 'b') {
|
if (ctmp != 'a' && ctmp != 'b') {
|
||||||
PrintAndLogEx(NORMAL, "Key type must be A or B");
|
PrintAndLogEx(WARNING, "Key type must be A or B");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1330,13 +1335,13 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param_gethex(Cmd, cmdp+2, key, 12)) {
|
if (param_gethex(Cmd, cmdp+2, key, 12)) {
|
||||||
PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols");
|
PrintAndLogEx(WARNING, "Key must include 12 HEX symbols");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param_getchar(Cmd, cmdp+3) == 0x00)
|
if (param_getchar(Cmd, cmdp+3) == 0x00)
|
||||||
{
|
{
|
||||||
PrintAndLogEx(NORMAL, "Target block number is missing");
|
PrintAndLogEx(WARNING, "Target block number is missing");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1344,7 +1349,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
|
|
||||||
ctmp = tolower(param_getchar(Cmd, cmdp+4));
|
ctmp = tolower(param_getchar(Cmd, cmdp+4));
|
||||||
if (ctmp != 'a' && ctmp != 'b') {
|
if (ctmp != 'a' && ctmp != 'b') {
|
||||||
PrintAndLogEx(NORMAL, "Target key type must be A or B");
|
PrintAndLogEx(WARNING, "Target key type must be A or B");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (ctmp != 'a') {
|
if (ctmp != 'a') {
|
||||||
|
@ -1402,7 +1407,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
SetSIMDInstr(SIMD_NONE);
|
SetSIMDInstr(SIMD_NONE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PrintAndLog("Unknown SIMD type. %c", ctmp);
|
PrintAndLogEx(WARNING, "Unknown SIMD type. %c", ctmp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
|
@ -1420,7 +1425,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
// check if we can authenticate to sector
|
// check if we can authenticate to sector
|
||||||
int res = mfCheckKeys(blockNo, keyType, true, 1, key, &key64);
|
int res = mfCheckKeys(blockNo, keyType, true, 1, key, &key64);
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(NORMAL, "Key is wrong. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A');
|
PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A');
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1497,11 +1502,11 @@ int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
|
|
||||||
// sectors
|
// sectors
|
||||||
switch(ctmp) {
|
switch(ctmp) {
|
||||||
case '0': sectorsCnt = 5; break;
|
case '0': sectorsCnt = MIFARE_MINI_MAXSECTOR; break;
|
||||||
case '1': sectorsCnt = 16; break;
|
case '1': sectorsCnt = MIFARE_1K_MAXSECTOR; break;
|
||||||
case '2': sectorsCnt = 32; break;
|
case '2': sectorsCnt = MIFARE_2K_MAXSECTOR; break;
|
||||||
case '4': sectorsCnt = 40; break;
|
case '4': sectorsCnt = MIFARE_4K_MAXSECTOR; break;
|
||||||
default: sectorsCnt = 16;
|
default: sectorsCnt = MIFARE_1K_MAXSECTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; param_getchar(Cmd, i); i++) {
|
for (i = 1; param_getchar(Cmd, i); i++) {
|
||||||
|
@ -1542,7 +1547,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
|
|
||||||
f = fopen( filename, "r");
|
f = fopen( filename, "r");
|
||||||
if ( !f ){
|
if ( !f ){
|
||||||
PrintAndLogEx(FAILED, "File: %s: not found or locked.", filename);
|
PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1556,7 +1561,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
if( buf[0]=='#' ) continue; //The line start with # is comment, skip
|
if( buf[0]=='#' ) continue; //The line start with # is comment, skip
|
||||||
|
|
||||||
if (!isxdigit(buf[0])){
|
if (!isxdigit(buf[0])){
|
||||||
PrintAndLogEx(FAILED, "File content error. '%s' must include 12 HEX symbols",buf);
|
PrintAndLogEx(FAILED, "File content error. '" _YELLOW_(%s)"' must include 12 HEX symbols", buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1578,7 +1583,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
PrintAndLogEx(SUCCESS, "Loaded %2d keys from %s", keycnt, filename);
|
PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_(%s), keycnt, filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1617,7 +1622,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
|
|
||||||
if (ukbhit()) {
|
if (ukbhit()) {
|
||||||
int gc = getchar(); (void)gc;
|
int gc = getchar(); (void)gc;
|
||||||
PrintAndLogEx(NORMAL, "\naborted via keyboard!\n");
|
PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1644,47 +1649,63 @@ out:
|
||||||
t1 = msclock() - t1;
|
t1 = msclock() - t1;
|
||||||
PrintAndLogEx(SUCCESS, "Time in checkkeys (fast): %.1fs\n", (float)(t1/1000.0));
|
PrintAndLogEx(SUCCESS, "Time in checkkeys (fast): %.1fs\n", (float)(t1/1000.0));
|
||||||
|
|
||||||
printKeyTable( sectorsCnt, e_sector );
|
// check..
|
||||||
|
uint8_t found_keys = 0;
|
||||||
if (transferToEml) {
|
for (uint8_t i = 0; i < sectorsCnt; ++i) {
|
||||||
uint8_t block[16] = {0x00};
|
|
||||||
for (uint8_t i = 0; i < sectorsCnt; ++i ) {
|
if ( e_sector[i].foundKey[0] )
|
||||||
mfEmlGetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
|
found_keys++;
|
||||||
if (e_sector[i].foundKey[0])
|
|
||||||
num_to_bytes(e_sector[i].Key[0], 6, block);
|
if ( e_sector[i].foundKey[1] )
|
||||||
if (e_sector[i].foundKey[1])
|
found_keys++;
|
||||||
num_to_bytes(e_sector[i].Key[1], 6, block+10);
|
|
||||||
mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
|
|
||||||
}
|
|
||||||
PrintAndLogEx(NORMAL, "Found keys have been transferred to the emulator memory");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createDumpFile) {
|
if ( found_keys == 0 ) {
|
||||||
fptr = GenerateFilename("hf-mf-", "-key.bin");
|
PrintAndLogEx(WARNING, "No keys found");
|
||||||
if (fptr == NULL)
|
} else {
|
||||||
return 1;
|
|
||||||
|
|
||||||
FILE *fkeys = fopen(fptr, "wb");
|
|
||||||
if (fkeys == NULL) {
|
|
||||||
PrintAndLogEx(WARNING, "Could not create file %s", fptr);
|
|
||||||
free(keyBlock);
|
|
||||||
free(e_sector);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
PrintAndLogEx(NORMAL, "Printing keys to binary file %s...", fptr);
|
|
||||||
|
|
||||||
for (i=0; i<sectorsCnt; i++) {
|
printKeyTable( sectorsCnt, e_sector );
|
||||||
num_to_bytes(e_sector[i].Key[0], 6, tempkey);
|
|
||||||
fwrite (tempkey, 1, 6, fkeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<sectorsCnt; i++) {
|
if (transferToEml) {
|
||||||
num_to_bytes(e_sector[i].Key[1], 6, tempkey);
|
uint8_t block[16] = {0x00};
|
||||||
fwrite (tempkey, 1, 6, fkeys );
|
for (uint8_t i = 0; i < sectorsCnt; ++i ) {
|
||||||
|
mfEmlGetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
|
||||||
|
if (e_sector[i].foundKey[0])
|
||||||
|
num_to_bytes(e_sector[i].Key[0], 6, block);
|
||||||
|
if (e_sector[i].foundKey[1])
|
||||||
|
num_to_bytes(e_sector[i].Key[1], 6, block+10);
|
||||||
|
mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
|
||||||
|
}
|
||||||
|
PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (createDumpFile) {
|
||||||
|
fptr = GenerateFilename("hf-mf-", "-key.bin");
|
||||||
|
if (fptr == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
fclose(fkeys);
|
FILE *fkeys = fopen(fptr, "wb");
|
||||||
PrintAndLogEx(NORMAL, "Found keys have been dumped to %s --> 0xffffffffffff has been inserted for unknown keys.", fptr);
|
if (fkeys == NULL) {
|
||||||
|
PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s), fptr);
|
||||||
|
free(keyBlock);
|
||||||
|
free(e_sector);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
PrintAndLogEx(SUCCESS, "Printing keys to binary file " _YELLOW_(%s)"...", fptr);
|
||||||
|
|
||||||
|
for (i=0; i<sectorsCnt; i++) {
|
||||||
|
num_to_bytes(e_sector[i].Key[0], 6, tempkey);
|
||||||
|
fwrite (tempkey, 1, 6, fkeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<sectorsCnt; i++) {
|
||||||
|
num_to_bytes(e_sector[i].Key[1], 6, tempkey);
|
||||||
|
fwrite (tempkey, 1, 6, fkeys );
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fkeys);
|
||||||
|
PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_(%s)" --> 0xffffffffffff has been inserted for unknown keys.", fptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
|
@ -1695,8 +1716,8 @@ out:
|
||||||
|
|
||||||
int CmdHF14AMfChk(const char *Cmd) {
|
int CmdHF14AMfChk(const char *Cmd) {
|
||||||
|
|
||||||
char ctmp = param_getchar(Cmd, 0);
|
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||||
if (strlen(Cmd) < 3 || ctmp == 'h' || ctmp == 'H') return usage_hf14_chk();
|
if (strlen(Cmd) < 3 || ctmp == 'h') return usage_hf14_chk();
|
||||||
|
|
||||||
FILE * f;
|
FILE * f;
|
||||||
char filename[FILE_PATH_SIZE]={0};
|
char filename[FILE_PATH_SIZE]={0};
|
||||||
|
@ -1729,23 +1750,21 @@ int CmdHF14AMfChk(const char *Cmd) {
|
||||||
blockNo = param_get8(Cmd, 0);
|
blockNo = param_get8(Cmd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctmp = param_getchar(Cmd, 1);
|
ctmp = tolower(param_getchar(Cmd, 1));
|
||||||
clen = param_getlength(Cmd, 1);
|
clen = param_getlength(Cmd, 1);
|
||||||
if (clen == 1) {
|
if (clen == 1) {
|
||||||
switch (ctmp) {
|
switch (ctmp) {
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'A':
|
|
||||||
keyType = 0;
|
keyType = 0;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'B':
|
|
||||||
keyType = 1;
|
keyType = 1;
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
keyType = 2;
|
keyType = 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PrintAndLogEx(NORMAL, "Key type must be A , B or ?");
|
PrintAndLogEx(FAILED, "Key type must be A , B or ?");
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
|
@ -1753,7 +1772,7 @@ int CmdHF14AMfChk(const char *Cmd) {
|
||||||
|
|
||||||
for (i = 2; param_getchar(Cmd, i); i++) {
|
for (i = 2; param_getchar(Cmd, i); i++) {
|
||||||
|
|
||||||
ctmp = param_getchar(Cmd, i);
|
ctmp = tolower(param_getchar(Cmd, i));
|
||||||
clen = param_getlength(Cmd, i);
|
clen = param_getlength(Cmd, i);
|
||||||
|
|
||||||
if (clen == 12) {
|
if (clen == 12) {
|
||||||
|
@ -1775,8 +1794,8 @@ int CmdHF14AMfChk(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "[%2d] key %s", keycnt, sprint_hex( (keyBlock + 6*keycnt), 6 ) );;
|
PrintAndLogEx(NORMAL, "[%2d] key %s", keycnt, sprint_hex( (keyBlock + 6*keycnt), 6 ) );;
|
||||||
keycnt++;
|
keycnt++;
|
||||||
} else if ( clen == 1 ) {
|
} else if ( clen == 1 ) {
|
||||||
if (ctmp == 't' || ctmp == 'T') { transferToEml = 1; continue; }
|
if (ctmp == 't' ) { transferToEml = 1; continue; }
|
||||||
if (ctmp == 'd' || ctmp == 'D') { createDumpFile = 1; continue; }
|
if (ctmp == 'd' ) { createDumpFile = 1; continue; }
|
||||||
} else {
|
} else {
|
||||||
// May be a dic file
|
// May be a dic file
|
||||||
if ( param_getstr(Cmd, i, filename, sizeof(filename)) >= FILE_PATH_SIZE ) {
|
if ( param_getstr(Cmd, i, filename, sizeof(filename)) >= FILE_PATH_SIZE ) {
|
||||||
|
@ -1786,7 +1805,7 @@ int CmdHF14AMfChk(const char *Cmd) {
|
||||||
|
|
||||||
f = fopen( filename , "r");
|
f = fopen( filename , "r");
|
||||||
if ( !f ) {
|
if ( !f ) {
|
||||||
PrintAndLogEx(FAILED, "File: %s: not found or locked.", filename);
|
PrintAndLogEx(FAILED, "File: " _YELLOW_(%s)": not found or locked.", filename);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1801,7 +1820,7 @@ int CmdHF14AMfChk(const char *Cmd) {
|
||||||
|
|
||||||
// codesmell, only checks first char?
|
// codesmell, only checks first char?
|
||||||
if (!isxdigit(buf[0])){
|
if (!isxdigit(buf[0])){
|
||||||
PrintAndLogEx(FAILED, "File content error. '%s' must include 12 HEX symbols",buf);
|
PrintAndLogEx(FAILED, "File content error. '" _YELLOW_(%s)"' must include 12 HEX symbols",buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1824,12 +1843,12 @@ int CmdHF14AMfChk(const char *Cmd) {
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
PrintAndLogEx(SUCCESS, "Loaded %2d keys from %s", keycnt, filename);
|
PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_(%s), keycnt, filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keycnt == 0) {
|
if (keycnt == 0) {
|
||||||
PrintAndLogEx(NORMAL, "No key specified, trying default keys");
|
PrintAndLogEx(INFO, "No key specified, trying default keys");
|
||||||
for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++)
|
for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++)
|
||||||
PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt,
|
PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt,
|
||||||
(keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],
|
(keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],
|
||||||
|
@ -1873,7 +1892,7 @@ int CmdHF14AMfChk(const char *Cmd) {
|
||||||
printf("."); fflush(stdout);
|
printf("."); fflush(stdout);
|
||||||
if (ukbhit()) {
|
if (ukbhit()) {
|
||||||
int gc = getchar(); (void)gc;
|
int gc = getchar(); (void)gc;
|
||||||
PrintAndLogEx(NORMAL, "\naborted via keyboard!\n");
|
PrintAndLogEx(INFO, "\naborted via keyboard!\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1892,12 +1911,12 @@ int CmdHF14AMfChk(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t1 = msclock() - t1;
|
t1 = msclock() - t1;
|
||||||
PrintAndLogEx(NORMAL, "\nTime in checkkeys: %.0f seconds\n", (float)t1/1000.0);
|
PrintAndLogEx(SUCCESS, "\nTime in checkkeys: %.0f seconds\n", (float)t1/1000.0);
|
||||||
|
|
||||||
|
|
||||||
// 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
|
// 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
|
||||||
if ( keyType != 1 ) {
|
if ( keyType != 1 ) {
|
||||||
PrintAndLogEx(NORMAL, "testing to read key B...");
|
PrintAndLogEx(INFO, "testing to read key B...");
|
||||||
for (i = 0; i < SectorsCnt; i++) {
|
for (i = 0; i < SectorsCnt; i++) {
|
||||||
// KEY A but not KEY B
|
// KEY A but not KEY B
|
||||||
if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) {
|
if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) {
|
||||||
|
@ -1943,7 +1962,7 @@ out:
|
||||||
num_to_bytes(e_sector[i].Key[1], 6, block+10);
|
num_to_bytes(e_sector[i].Key[1], 6, block+10);
|
||||||
mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
|
mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "Found keys have been transferred to the emulator memory");
|
PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createDumpFile) {
|
if (createDumpFile) {
|
||||||
|
@ -1953,12 +1972,12 @@ out:
|
||||||
|
|
||||||
FILE *fkeys = fopen(fptr, "wb");
|
FILE *fkeys = fopen(fptr, "wb");
|
||||||
if (fkeys == NULL) {
|
if (fkeys == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Could not create file %s", fptr);
|
PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s), fptr);
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
free(e_sector);
|
free(e_sector);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "Printing keys to binary file %s...", fptr);
|
PrintAndLogEx(INFO, "Printing keys to binary file " _YELLOW_(%s)"...", fptr);
|
||||||
|
|
||||||
for( i=0; i<SectorsCnt; i++) {
|
for( i=0; i<SectorsCnt; i++) {
|
||||||
num_to_bytes(e_sector[i].Key[0], 6, tempkey);
|
num_to_bytes(e_sector[i].Key[0], 6, tempkey);
|
||||||
|
@ -1969,7 +1988,7 @@ out:
|
||||||
fwrite ( tempkey, 1, 6, fkeys );
|
fwrite ( tempkey, 1, 6, fkeys );
|
||||||
}
|
}
|
||||||
fclose(fkeys);
|
fclose(fkeys);
|
||||||
PrintAndLogEx(NORMAL, "Found keys have been dumped to file %s. 0xffffffffffff has been inserted for unknown keys.", fptr);
|
PrintAndLogEx(SUCCESS, "Found keys have been dumped to file " _YELLOW_(%s)". 0xffffffffffff has been inserted for unknown keys.", fptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
|
@ -2018,7 +2037,7 @@ void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose) {
|
||||||
uint8_t sector = data.sector;
|
uint8_t sector = data.sector;
|
||||||
uint8_t keytype = data.keytype;
|
uint8_t keytype = data.keytype;
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Reader is trying authenticate with: Key %s, sector %02d: [%012" PRIx64 "]"
|
PrintAndLogEx(INFO, "Reader is trying authenticate with: Key %s, sector %02d: [%012" PRIx64 "]"
|
||||||
, keytype ? "B" : "A"
|
, keytype ? "B" : "A"
|
||||||
, sector
|
, sector
|
||||||
, key
|
, key
|
||||||
|
@ -2033,7 +2052,7 @@ void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose) {
|
||||||
num_to_bytes( k_sector[sector].Key[0], 6, memBlock);
|
num_to_bytes( k_sector[sector].Key[0], 6, memBlock);
|
||||||
num_to_bytes( k_sector[sector].Key[1], 6, memBlock+10);
|
num_to_bytes( k_sector[sector].Key[1], 6, memBlock+10);
|
||||||
//iceman, guessing this will not work so well for 4K tags.
|
//iceman, guessing this will not work so well for 4K tags.
|
||||||
PrintAndLogEx(NORMAL, "Setting Emulator Memory Block %02d: [%s]"
|
PrintAndLogEx(INFO, "Setting Emulator Memory Block %02d: [%s]"
|
||||||
, (sector*4) + 3
|
, (sector*4) + 3
|
||||||
, sprint_hex( memBlock, sizeof(memBlock))
|
, sprint_hex( memBlock, sizeof(memBlock))
|
||||||
);
|
);
|
||||||
|
@ -2108,7 +2127,7 @@ int CmdHF14AMf1kSim(const char *Cmd) {
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
|
|
||||||
if(flags & FLAG_INTERACTIVE) {
|
if(flags & FLAG_INTERACTIVE) {
|
||||||
PrintAndLogEx(NORMAL, "Press pm3-button or send another cmd to abort simulation");
|
PrintAndLogEx(INFO, "Press pm3-button or send another cmd to abort simulation");
|
||||||
|
|
||||||
while( !ukbhit() ){
|
while( !ukbhit() ){
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue;
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue;
|
||||||
|
@ -2144,8 +2163,8 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
|
|
||||||
memset(uid, 0x00, sizeof(uid));
|
memset(uid, 0x00, sizeof(uid));
|
||||||
|
|
||||||
char ctmp = param_getchar(Cmd, 0);
|
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||||
if ( ctmp == 'h' || ctmp == 'H' ) return usage_hf14_sniff();
|
if ( ctmp == 'h') return usage_hf14_sniff();
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
ctmp = tolower(param_getchar(Cmd, i));
|
ctmp = tolower(param_getchar(Cmd, i));
|
||||||
|
@ -2172,7 +2191,7 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
printf("."); fflush(stdout);
|
printf("."); fflush(stdout);
|
||||||
if (ukbhit()) {
|
if (ukbhit()) {
|
||||||
int gc = getchar(); (void)gc;
|
int gc = getchar(); (void)gc;
|
||||||
PrintAndLogEx(NORMAL, "\n[!] aborted via keyboard!\n");
|
PrintAndLogEx(INFO, "\naborted via keyboard!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2195,7 +2214,7 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
if (traceLen > bufsize || buf == NULL) {
|
if (traceLen > bufsize || buf == NULL) {
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
if (buf == NULL) // not yet allocated
|
if (buf == NULL) // not yet allocated
|
||||||
p = malloc(traceLen);
|
p = calloc(traceLen, sizeof(uint8_t));
|
||||||
else // need more memory
|
else // need more memory
|
||||||
p = realloc(buf, traceLen);
|
p = realloc(buf, traceLen);
|
||||||
|
|
||||||
|
@ -2412,14 +2431,14 @@ int CmdHF14AMfELoad(const char *Cmd) {
|
||||||
return usage_hf14_eload();
|
return usage_hf14_eload();
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '0' : numBlocks = 5*4; break;
|
case '0' : numBlocks = MIFARE_MINI_MAXBLOCK; break;
|
||||||
case '1' :
|
case '1' :
|
||||||
case '\0': numBlocks = 16*4; break;
|
case '\0': numBlocks = MIFARE_1K_MAXBLOCK; break;
|
||||||
case '2' : numBlocks = 32*4; break;
|
case '2' : numBlocks = MIFARE_2K_MAXBLOCK; break;
|
||||||
case '4' : numBlocks = 256; break;
|
case '4' : numBlocks = MIFARE_4K_MAXBLOCK; break;
|
||||||
case 'u' : numBlocks = 255; blockWidth = 4; break;
|
case 'u' : numBlocks = 255; blockWidth = 4; break;
|
||||||
default: {
|
default: {
|
||||||
numBlocks = 16*4;
|
numBlocks = MIFARE_1K_MAXBLOCK;
|
||||||
nameParamNo = 0;
|
nameParamNo = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2475,7 +2494,7 @@ int CmdHF14AMfELoad(const char *Cmd) {
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "Loaded %d blocks from file: %s", blockNum, filename);
|
PrintAndLogEx(SUCCESS, "Loaded %d blocks from file: " _YELLOW_(%s), blockNum, filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2496,14 +2515,14 @@ int CmdHF14AMfESave(const char *Cmd) {
|
||||||
blocks = NumOfBlocks(c);
|
blocks = NumOfBlocks(c);
|
||||||
bytes = blocks * MFBLOCK_SIZE;
|
bytes = blocks * MFBLOCK_SIZE;
|
||||||
|
|
||||||
dump = calloc(sizeof(uint8_t), bytes);
|
dump = calloc(bytes, sizeof(uint8_t));
|
||||||
if (!dump) {
|
if (!dump) {
|
||||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memset(dump, 0, bytes);
|
memset(dump, 0, bytes);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "dowingloading from emulator memory");
|
PrintAndLogEx(INFO, "downloading from emulator memory");
|
||||||
if (!GetFromDevice( BIG_BUF_EML, dump, bytes, 0, NULL, 2500, false)) {
|
if (!GetFromDevice( BIG_BUF_EML, dump, bytes, 0, NULL, 2500, false)) {
|
||||||
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
|
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
|
||||||
free(dump);
|
free(dump);
|
||||||
|
@ -2761,7 +2780,7 @@ int CmdHF14AMfCLoad(const char *Cmd) {
|
||||||
blockNum++;
|
blockNum++;
|
||||||
|
|
||||||
// magic card type - mifare 1K
|
// magic card type - mifare 1K
|
||||||
if (blockNum >= 16 * 4) break;
|
if (blockNum >= MIFARE_1K_MAXBLOCK ) break;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
PrintAndLogEx(NORMAL, "\n");
|
||||||
|
|
||||||
|
@ -2783,8 +2802,8 @@ int CmdHF14AMfCGetBlk(const char *Cmd) {
|
||||||
int res;
|
int res;
|
||||||
memset(data, 0x00, sizeof(data));
|
memset(data, 0x00, sizeof(data));
|
||||||
|
|
||||||
char ctmp = param_getchar(Cmd, 0);
|
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||||
if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_hf14_cgetblk();
|
if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_cgetblk();
|
||||||
|
|
||||||
blockNo = param_get8(Cmd, 0);
|
blockNo = param_get8(Cmd, 0);
|
||||||
|
|
||||||
|
@ -2819,8 +2838,8 @@ int CmdHF14AMfCGetSc(const char *Cmd) {
|
||||||
uint8_t sector = 0;
|
uint8_t sector = 0;
|
||||||
int i, res, flags;
|
int i, res, flags;
|
||||||
|
|
||||||
char ctmp = param_getchar(Cmd, 0);
|
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||||
if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_hf14_cgetsc();
|
if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_cgetsc();
|
||||||
|
|
||||||
sector = param_get8(Cmd, 0);
|
sector = param_get8(Cmd, 0);
|
||||||
if (sector > 39) {
|
if (sector > 39) {
|
||||||
|
@ -2912,7 +2931,7 @@ int CmdHF14AMfCSave(const char *Cmd) {
|
||||||
|
|
||||||
if (errors || cmdp == 0) return usage_hf14_csave();
|
if (errors || cmdp == 0) return usage_hf14_csave();
|
||||||
|
|
||||||
dump = malloc(bytes);
|
dump = calloc(bytes, sizeof(uint8_t));
|
||||||
if (!dump) {
|
if (!dump) {
|
||||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2958,8 +2977,8 @@ int CmdHF14AMfCSave(const char *Cmd) {
|
||||||
//needs nt, ar, at, Data to decrypt
|
//needs nt, ar, at, Data to decrypt
|
||||||
int CmdHf14AMfDecryptBytes(const char *Cmd){
|
int CmdHf14AMfDecryptBytes(const char *Cmd){
|
||||||
|
|
||||||
char ctmp = param_getchar(Cmd, 0);
|
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||||
if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_hf14_decryptbytes();
|
if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_decryptbytes();
|
||||||
|
|
||||||
uint32_t nt = param_get32ex(Cmd,0,0,16);
|
uint32_t nt = param_get32ex(Cmd,0,0,16);
|
||||||
uint32_t ar_enc = param_get32ex(Cmd,1,0,16);
|
uint32_t ar_enc = param_get32ex(Cmd,1,0,16);
|
||||||
|
@ -3010,7 +3029,7 @@ int CmdHf14AMfSetMod(const char *Cmd) {
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
uint8_t ok = resp.arg[0] & 0xff;
|
uint8_t ok = resp.arg[0] & 0xff;
|
||||||
PrintAndLogEx(NORMAL, "isOk:%02x", ok);
|
PrintAndLogEx(SUCCESS, "isOk:%02x", ok);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
PrintAndLogEx(FAILED, "Failed.");
|
PrintAndLogEx(FAILED, "Failed.");
|
||||||
} else {
|
} else {
|
||||||
|
@ -3023,12 +3042,12 @@ int CmdHf14AMfSetMod(const char *Cmd) {
|
||||||
int CmdHf14AMfNack(const char *Cmd) {
|
int CmdHf14AMfNack(const char *Cmd) {
|
||||||
|
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
char ctmp = param_getchar(Cmd, 0);
|
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||||
if ( ctmp == 'h' || ctmp == 'H' ) return usage_hf14_nack();
|
if ( ctmp == 'h' ) return usage_hf14_nack();
|
||||||
if ( ctmp == 'v' || ctmp == 'V' ) verbose = true;
|
if ( ctmp == 'v' ) verbose = true;
|
||||||
|
|
||||||
if ( verbose )
|
if ( verbose )
|
||||||
PrintAndLogEx(NORMAL, "Started testing card for NACK bug. Press key to abort");
|
PrintAndLogEx(INFO, "Started testing card for NACK bug. Press key to abort");
|
||||||
|
|
||||||
detect_classic_nackbug(verbose);
|
detect_classic_nackbug(verbose);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3086,7 +3105,7 @@ int CmdHF14AMfice(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "Collecting %u nonces \n", limit);
|
PrintAndLogEx(NORMAL, "Collecting %u nonces \n", limit);
|
||||||
|
|
||||||
if ((fnonces = fopen(filename,"wb")) == NULL) {
|
if ((fnonces = fopen(filename,"wb")) == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Could not create file %s",filename);
|
PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s),filename);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3097,7 +3116,7 @@ int CmdHF14AMfice(const char *Cmd) {
|
||||||
do {
|
do {
|
||||||
if (ukbhit()) {
|
if (ukbhit()) {
|
||||||
int gc = getchar(); (void)gc;
|
int gc = getchar(); (void)gc;
|
||||||
PrintAndLogEx(NORMAL, "\naborted via keyboard!\n");
|
PrintAndLogEx(INFO, "\naborted via keyboard!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3119,7 +3138,7 @@ int CmdHF14AMfice(const char *Cmd) {
|
||||||
|
|
||||||
total_num_nonces += items;
|
total_num_nonces += items;
|
||||||
if ( total_num_nonces > part_limit ) {
|
if ( total_num_nonces > part_limit ) {
|
||||||
PrintAndLogEx(NORMAL, "Total nonces %u\n", total_num_nonces);
|
PrintAndLogEx(INFO, "Total nonces %u\n", total_num_nonces);
|
||||||
part_limit += 3000;
|
part_limit += 3000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3130,7 +3149,7 @@ int CmdHF14AMfice(const char *Cmd) {
|
||||||
} while (!acquisition_completed);
|
} while (!acquisition_completed);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
PrintAndLogEx(NORMAL, "time: %" PRIu64 " seconds\n", (msclock()-t1)/1000);
|
PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds\n", (msclock()-t1)/1000);
|
||||||
|
|
||||||
if ( fnonces ) {
|
if ( fnonces ) {
|
||||||
fflush(fnonces);
|
fflush(fnonces);
|
||||||
|
|
|
@ -209,7 +209,7 @@ static int compare_count_bitflip_bitarrays(const void *b1, const void *b2)
|
||||||
|
|
||||||
static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size)
|
static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size)
|
||||||
{
|
{
|
||||||
return malloc(items*size);
|
return calloc(items*size, sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1038,8 +1038,11 @@ static bool shrink_key_space(float *brute_forces)
|
||||||
}
|
}
|
||||||
*brute_forces = MIN(brute_forces1, brute_forces2);
|
*brute_forces = MIN(brute_forces1, brute_forces2);
|
||||||
float reduction_rate = update_reduction_rate(*brute_forces, false);
|
float reduction_rate = update_reduction_rate(*brute_forces, false);
|
||||||
return ((hardnested_stage & CHECK_2ND_BYTES)
|
|
||||||
&& reduction_rate >= 0.0 && reduction_rate < brute_force_per_second * sample_period / 1000.0);
|
//iceman 2018
|
||||||
|
return ((hardnested_stage & CHECK_2ND_BYTES) &&
|
||||||
|
reduction_rate >= 0.0 &&
|
||||||
|
( reduction_rate < brute_force_per_second * (float)sample_period / 1000.0 || *brute_forces < 0x1F000000000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -980,11 +980,11 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
||||||
if ( hasAuthKey ) return 1;
|
if ( hasAuthKey ) return 1;
|
||||||
|
|
||||||
// also try to diversify default keys.. look into CmdHF14AMfuGenDiverseKeys
|
// also try to diversify default keys.. look into CmdHF14AMfuGenDiverseKeys
|
||||||
PrintAndLogEx(NORMAL, "Trying some default 3des keys");
|
PrintAndLogEx(INFO, "Trying some default 3des keys");
|
||||||
for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) {
|
for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) {
|
||||||
key = default_3des_keys[i];
|
key = default_3des_keys[i];
|
||||||
if (ulc_authentication(key, true)) {
|
if (ulc_authentication(key, true)) {
|
||||||
PrintAndLogEx(NORMAL, "Found default 3des key: ");
|
PrintAndLogEx(SUCCESS, "Found default 3des key: ");
|
||||||
uint8_t keySwap[16];
|
uint8_t keySwap[16];
|
||||||
memcpy(keySwap, SwapEndian64(key,16,8), 16);
|
memcpy(keySwap, SwapEndian64(key,16,8), 16);
|
||||||
ulc_print_3deskey(keySwap);
|
ulc_print_3deskey(keySwap);
|
||||||
|
@ -1079,7 +1079,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
||||||
num_to_bytes( ul_ev1_pwdgenA(card.uid), 4, key);
|
num_to_bytes( ul_ev1_pwdgenA(card.uid), 4, key);
|
||||||
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
||||||
if (len > -1) {
|
if (len > -1) {
|
||||||
PrintAndLogEx(NORMAL, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
|
PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1089,7 +1089,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
||||||
num_to_bytes( ul_ev1_pwdgenB(card.uid), 4, key);
|
num_to_bytes( ul_ev1_pwdgenB(card.uid), 4, key);
|
||||||
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
||||||
if (len > -1) {
|
if (len > -1) {
|
||||||
PrintAndLogEx(NORMAL, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
|
PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,7 +1099,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
||||||
num_to_bytes( ul_ev1_pwdgenC(card.uid), 4, key);
|
num_to_bytes( ul_ev1_pwdgenC(card.uid), 4, key);
|
||||||
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
||||||
if (len > -1) {
|
if (len > -1) {
|
||||||
PrintAndLogEx(NORMAL, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
|
PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1109,7 +1109,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
||||||
num_to_bytes( ul_ev1_pwdgenD(card.uid), 4, key);
|
num_to_bytes( ul_ev1_pwdgenD(card.uid), 4, key);
|
||||||
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
||||||
if (len > -1) {
|
if (len > -1) {
|
||||||
PrintAndLogEx(NORMAL, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
|
PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,13 +1119,13 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
||||||
key = default_pwd_pack[i];
|
key = default_pwd_pack[i];
|
||||||
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
||||||
if (len > -1) {
|
if (len > -1) {
|
||||||
PrintAndLogEx(NORMAL, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
|
PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
|
if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (len < 1) PrintAndLogEx(NORMAL, "password not known");
|
if (len < 1) PrintAndLogEx(WARNING, "password not known");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
@ -1250,7 +1250,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
uint8_t isOK = resp.arg[0] & 0xff;
|
uint8_t isOK = resp.arg[0] & 0xff;
|
||||||
PrintAndLogEx(NORMAL, "isOk:%02x", isOK);
|
PrintAndLogEx(SUCCESS, "isOk:%02x", isOK);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "Command execute timeout");
|
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
}
|
}
|
||||||
|
@ -1365,7 +1365,7 @@ int CmdHF14AMfURdBl(const char *Cmd){
|
||||||
PrintAndLogEx(WARNING, "Failed reading block: (%02x)", isOK);
|
PrintAndLogEx(WARNING, "Failed reading block: (%02x)", isOK);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(NORMAL, "Command execute time-out");
|
PrintAndLogEx(WARNING, "Command execute time-out");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1743,7 +1743,7 @@ int CmdHF14AMfUDump(const char *Cmd){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ul_print_type(tagtype, 0);
|
ul_print_type(tagtype, 0);
|
||||||
PrintAndLogEx(NORMAL, "Reading tag memory...");
|
PrintAndLogEx(SUCCESS, "Reading tag memory...");
|
||||||
UsbCommand c = {CMD_MIFAREU_READCARD, {startPage, pages}};
|
UsbCommand c = {CMD_MIFAREU_READCARD, {startPage, pages}};
|
||||||
if ( hasAuthKey ) {
|
if ( hasAuthKey ) {
|
||||||
if (tagtype & UL_C)
|
if (tagtype & UL_C)
|
||||||
|
@ -1912,12 +1912,10 @@ int CmdHF14AMfURestore(const char *Cmd){
|
||||||
memset(authkey, 0x00, sizeof(authkey));
|
memset(authkey, 0x00, sizeof(authkey));
|
||||||
|
|
||||||
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||||
switch(param_getchar(Cmd, cmdp)) {
|
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||||
case 'h':
|
case 'h':
|
||||||
case 'H':
|
|
||||||
return usage_hf_mfu_restore();
|
return usage_hf_mfu_restore();
|
||||||
case 'k':
|
case 'k':
|
||||||
case 'K':
|
|
||||||
keylen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
|
keylen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
|
||||||
if (keylen == 32 || keylen == 8) { //ul-c or ev1/ntag key length
|
if (keylen == 32 || keylen == 8) { //ul-c or ev1/ntag key length
|
||||||
errors = param_gethex(tempStr, 0, authkey, keylen);
|
errors = param_gethex(tempStr, 0, authkey, keylen);
|
||||||
|
@ -1930,12 +1928,10 @@ int CmdHF14AMfURestore(const char *Cmd){
|
||||||
hasKey = true;
|
hasKey = true;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
case 'L':
|
|
||||||
swapEndian = true;
|
swapEndian = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'F':
|
|
||||||
filelen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE);
|
filelen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE);
|
||||||
|
|
||||||
if (filelen > FILE_PATH_SIZE-5)
|
if (filelen > FILE_PATH_SIZE-5)
|
||||||
|
@ -1947,17 +1943,14 @@ int CmdHF14AMfURestore(const char *Cmd){
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
case 'S':
|
|
||||||
cmdp++;
|
cmdp++;
|
||||||
write_special = true;
|
write_special = true;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
|
||||||
cmdp++;
|
cmdp++;
|
||||||
write_extra = true;
|
write_extra = true;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
case 'R':
|
|
||||||
cmdp++;
|
cmdp++;
|
||||||
read_key = true;
|
read_key = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1972,7 +1965,7 @@ int CmdHF14AMfURestore(const char *Cmd){
|
||||||
if (errors || cmdp == 0) return usage_hf_mfu_restore();
|
if (errors || cmdp == 0) return usage_hf_mfu_restore();
|
||||||
|
|
||||||
if ((f = fopen(filename,"rb")) == NULL) {
|
if ((f = fopen(filename,"rb")) == NULL) {
|
||||||
PrintAndLogEx(WARNING, "Could not find file %s", filename);
|
PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), filename);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2000,7 +1993,7 @@ int CmdHF14AMfURestore(const char *Cmd){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Restoring %s to card", filename);
|
PrintAndLogEx(INFO, "Restoring " _YELLOW_(%s)" to card", filename);
|
||||||
|
|
||||||
mfu_dump_t *mem = (mfu_dump_t*)dump;
|
mfu_dump_t *mem = (mfu_dump_t*)dump;
|
||||||
uint8_t pages = (bytes_read-48)/4;
|
uint8_t pages = (bytes_read-48)/4;
|
||||||
|
@ -2084,7 +2077,7 @@ int CmdHF14AMfURestore(const char *Cmd){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Restoring data blocks.");
|
PrintAndLogEx(INFO, "Restoring data blocks.");
|
||||||
// write all other data
|
// write all other data
|
||||||
// Skip block 0,1,2,3 (only magic tags can write to them)
|
// Skip block 0,1,2,3 (only magic tags can write to them)
|
||||||
// Skip last 5 blocks usually is configuration
|
// Skip last 5 blocks usually is configuration
|
||||||
|
@ -2103,7 +2096,7 @@ int CmdHF14AMfURestore(const char *Cmd){
|
||||||
// write special data last
|
// write special data last
|
||||||
if (write_special) {
|
if (write_special) {
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Restoring configuration blocks.\n");
|
PrintAndLogEx(INFO, "Restoring configuration blocks.\n");
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "authentication with keytype[%x] %s\n", (uint8_t)(c.arg[1] & 0xff), sprint_hex(p_authkey,4));
|
PrintAndLogEx(NORMAL, "authentication with keytype[%x] %s\n", (uint8_t)(c.arg[1] & 0xff), sprint_hex(p_authkey,4));
|
||||||
|
|
||||||
|
@ -2128,16 +2121,16 @@ int CmdHF14AMfURestore(const char *Cmd){
|
||||||
// Load emulator with dump file
|
// Load emulator with dump file
|
||||||
//
|
//
|
||||||
int CmdHF14AMfUeLoad(const char *Cmd){
|
int CmdHF14AMfUeLoad(const char *Cmd){
|
||||||
char c = param_getchar(Cmd, 0);
|
char c = tolower(param_getchar(Cmd, 0));
|
||||||
if ( c == 'h' || c == 'H' || c == 0x00) return usage_hf_mfu_eload();
|
if ( c == 'h' || c == 0x00) return usage_hf_mfu_eload();
|
||||||
return CmdHF14AMfELoad(Cmd);
|
return CmdHF14AMfELoad(Cmd);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Simulate tag
|
// Simulate tag
|
||||||
//
|
//
|
||||||
int CmdHF14AMfUSim(const char *Cmd){
|
int CmdHF14AMfUSim(const char *Cmd){
|
||||||
char c = param_getchar(Cmd, 0);
|
char c = tolower(param_getchar(Cmd, 0));
|
||||||
if ( c == 'h' || c == 'H' || c == 0x00) return usage_hf_mfu_sim();
|
if ( c == 'h' || c == 0x00) return usage_hf_mfu_sim();
|
||||||
return CmdHF14ASim(Cmd);
|
return CmdHF14ASim(Cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2153,16 +2146,16 @@ int CmdHF14AMfucAuth(const char *Cmd){
|
||||||
uint8_t keyNo = 3;
|
uint8_t keyNo = 3;
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
|
|
||||||
char cmdp = param_getchar(Cmd, 0);
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
|
|
||||||
//Change key to user defined one
|
//Change key to user defined one
|
||||||
if (cmdp == 'k' || cmdp == 'K'){
|
if (cmdp == 'k'){
|
||||||
keyNo = param_get8(Cmd, 1);
|
keyNo = param_get8(Cmd, 1);
|
||||||
if(keyNo >= KEYS_3DES_COUNT)
|
if(keyNo >= KEYS_3DES_COUNT)
|
||||||
errors = true;
|
errors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmdp == 'h' || cmdp == 'H') errors = true;
|
if (cmdp == 'h') errors = true;
|
||||||
|
|
||||||
if (errors) return usage_hf_mfu_ucauth();
|
if (errors) return usage_hf_mfu_ucauth();
|
||||||
|
|
||||||
|
@ -2278,9 +2271,9 @@ int CmdTestDES(const char * cmd)
|
||||||
int CmdHF14AMfucSetPwd(const char *Cmd){
|
int CmdHF14AMfucSetPwd(const char *Cmd){
|
||||||
|
|
||||||
uint8_t pwd[16] = {0x00};
|
uint8_t pwd[16] = {0x00};
|
||||||
char cmdp = param_getchar(Cmd, 0);
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
|
|
||||||
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_hf_mfu_ucsetpwd();
|
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_ucsetpwd();
|
||||||
|
|
||||||
if (param_gethex(Cmd, 0, pwd, 32)) {
|
if (param_gethex(Cmd, 0, pwd, 32)) {
|
||||||
PrintAndLogEx(WARNING, "Password must include 32 HEX symbols");
|
PrintAndLogEx(WARNING, "Password must include 32 HEX symbols");
|
||||||
|
@ -2295,7 +2288,7 @@ int CmdHF14AMfucSetPwd(const char *Cmd){
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
|
||||||
if ( (resp.arg[0] & 0xff) == 1) {
|
if ( (resp.arg[0] & 0xff) == 1) {
|
||||||
PrintAndLogEx(NORMAL, "Ultralight-C new password: %s", sprint_hex(pwd,16));
|
PrintAndLogEx(INFO, "Ultralight-C new password: %s", sprint_hex(pwd,16));
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "Failed writing at block %d", resp.arg[1] & 0xff);
|
PrintAndLogEx(WARNING, "Failed writing at block %d", resp.arg[1] & 0xff);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2315,9 +2308,9 @@ int CmdHF14AMfucSetUid(const char *Cmd){
|
||||||
UsbCommand c = {CMD_MIFAREU_READBL};
|
UsbCommand c = {CMD_MIFAREU_READBL};
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
uint8_t uid[7] = {0x00};
|
uint8_t uid[7] = {0x00};
|
||||||
char cmdp = param_getchar(Cmd, 0);
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
|
|
||||||
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_hf_mfu_ucsetuid();
|
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_ucsetuid();
|
||||||
|
|
||||||
if (param_gethex(Cmd, 0, uid, 14)) {
|
if (param_gethex(Cmd, 0, uid, 14)) {
|
||||||
PrintAndLogEx(WARNING, "UID must include 14 HEX symbols");
|
PrintAndLogEx(WARNING, "UID must include 14 HEX symbols");
|
||||||
|
|
|
@ -194,7 +194,7 @@ static int topaz_print_CC(uint8_t *data) {
|
||||||
PrintAndLogEx(NORMAL, " %02x: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f);
|
PrintAndLogEx(NORMAL, " %02x: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f);
|
||||||
uint16_t memsize = (data[2] + 1) * 8;
|
uint16_t memsize = (data[2] + 1) * 8;
|
||||||
topaz_tag.size = memsize;
|
topaz_tag.size = memsize;
|
||||||
topaz_tag.dynamic_memory = malloc(memsize - TOPAZ_STATIC_MEMORY);
|
topaz_tag.dynamic_memory = calloc(memsize - TOPAZ_STATIC_MEMORY, sizeof(uint8_t));
|
||||||
PrintAndLogEx(NORMAL, " %02x: Physical Memory Size of this tag: %d bytes", data[2], memsize);
|
PrintAndLogEx(NORMAL, " %02x: Physical Memory Size of this tag: %d bytes", data[2], memsize);
|
||||||
PrintAndLogEx(NORMAL, " %02x: %s / %s", data[3],
|
PrintAndLogEx(NORMAL, " %02x: %s / %s", data[3],
|
||||||
(data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security",
|
(data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security",
|
||||||
|
@ -278,12 +278,12 @@ static void topaz_print_control_TLVs(uint8_t *memory) {
|
||||||
dynamic_lock_area_t *old = topaz_tag.dynamic_lock_areas;
|
dynamic_lock_area_t *old = topaz_tag.dynamic_lock_areas;
|
||||||
dynamic_lock_area_t *new = topaz_tag.dynamic_lock_areas;
|
dynamic_lock_area_t *new = topaz_tag.dynamic_lock_areas;
|
||||||
if (old == NULL) {
|
if (old == NULL) {
|
||||||
new = topaz_tag.dynamic_lock_areas = (dynamic_lock_area_t *)malloc(sizeof(dynamic_lock_area_t));
|
new = topaz_tag.dynamic_lock_areas = (dynamic_lock_area_t *) calloc(sizeof(dynamic_lock_area_t) , sizeof(uint8_t));
|
||||||
} else {
|
} else {
|
||||||
while(old->next != NULL) {
|
while(old->next != NULL) {
|
||||||
old = old->next;
|
old = old->next;
|
||||||
}
|
}
|
||||||
new = old->next = (dynamic_lock_area_t *)malloc(sizeof(dynamic_lock_area_t));
|
new = old->next = (dynamic_lock_area_t *) calloc(sizeof(dynamic_lock_area_t), sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
new->next = NULL;
|
new->next = NULL;
|
||||||
if (area_start <= next_lockable_byte) {
|
if (area_start <= next_lockable_byte) {
|
||||||
|
|
|
@ -257,9 +257,9 @@ int CmdVersion(const char *Cmd) {
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
|
||||||
#ifdef __WIN32
|
#ifdef __WIN32
|
||||||
PrintAndLogEx(NORMAL, "\nProxmark3 RFID instrument\n");
|
PrintAndLogEx(NORMAL, "\n [ Proxmark3 RFID instrument ]\n");
|
||||||
#else
|
#else
|
||||||
PrintAndLogEx(NORMAL, "\n\e[34mProxmark3 RFID instrument\e[0m\n");
|
PrintAndLogEx(NORMAL, "\n\e[34m [ Proxmark3 RFID instrument ]\e[0m\n");
|
||||||
#endif
|
#endif
|
||||||
char s[50] = {0};
|
char s[50] = {0};
|
||||||
#if defined(WITH_FLASH) || defined(WITH_SMARTCARD) || defined(WITH_FPC)
|
#if defined(WITH_FLASH) || defined(WITH_SMARTCARD) || defined(WITH_FPC)
|
||||||
|
@ -275,7 +275,7 @@ int CmdVersion(const char *Cmd) {
|
||||||
strncat(s, "fpc; ", sizeof(s) - strlen(s) - 1);
|
strncat(s, "fpc; ", sizeof(s) - strlen(s) - 1);
|
||||||
#endif
|
#endif
|
||||||
PrintAndLogEx(NORMAL, "\n [ CLIENT ]");
|
PrintAndLogEx(NORMAL, "\n [ CLIENT ]");
|
||||||
PrintAndLogEx(NORMAL, " client: iceman %s \n", s);
|
PrintAndLogEx(NORMAL, " client: iceman %s \n", s);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, (char*)resp.d.asBytes);
|
PrintAndLogEx(NORMAL, (char*)resp.d.asBytes);
|
||||||
lookupChipID(resp.arg[0], resp.arg[1]);
|
lookupChipID(resp.arg[0], resp.arg[1]);
|
||||||
|
|
|
@ -141,21 +141,33 @@ int usage_t55xx_wakup(){
|
||||||
PrintAndLogEx(NORMAL, " lf t55xx wakeup p 11223344 - send wakeup password");
|
PrintAndLogEx(NORMAL, " lf t55xx wakeup p 11223344 - send wakeup password");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int usage_t55xx_bruteforce(){
|
int usage_t55xx_chk(){
|
||||||
PrintAndLogEx(NORMAL, "This command uses A) bruteforce to scan a number range");
|
PrintAndLogEx(NORMAL, "This command uses a dictionary attack");
|
||||||
PrintAndLogEx(NORMAL, " B) a dictionary attack");
|
|
||||||
PrintAndLogEx(NORMAL, "press 'enter' to cancel the command");
|
PrintAndLogEx(NORMAL, "press 'enter' to cancel the command");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] <start password> <end password> [i <*.dic>]");
|
PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] <m> [i <*.dic>]");
|
||||||
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
|
PrintAndLogEx(NORMAL, " h - this help");
|
||||||
|
PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n");
|
||||||
|
PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
|
PrintAndLogEx(NORMAL, " lf t55xx bruteforce m");
|
||||||
|
PrintAndLogEx(NORMAL, " lf t55xx bruteforce i default_pwd.dic");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int usage_t55xx_bruteforce(){
|
||||||
|
PrintAndLogEx(NORMAL, "This command uses bruteforce to scan a number range");
|
||||||
|
PrintAndLogEx(NORMAL, "press 'enter' to cancel the command");
|
||||||
|
PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] <start password> <end password>");
|
||||||
PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)");
|
PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h - this help");
|
PrintAndLogEx(NORMAL, " h - this help");
|
||||||
PrintAndLogEx(NORMAL, " <start_pwd> - 4 byte hex value to start pwd search at");
|
PrintAndLogEx(NORMAL, " <start_pwd> - 4 byte hex value to start pwd search at");
|
||||||
PrintAndLogEx(NORMAL, " <end_pwd> - 4 byte hex value to end pwd search at");
|
PrintAndLogEx(NORMAL, " <end_pwd> - 4 byte hex value to end pwd search at");
|
||||||
PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf t55xx bruteforce aaaaaaaa bbbbbbbb");
|
PrintAndLogEx(NORMAL, " lf t55xx bruteforce aaaaaaaa bbbbbbbb");
|
||||||
PrintAndLogEx(NORMAL, " lf t55xx bruteforce i default_pwd.dic");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -224,10 +236,9 @@ int CmdT55xxSetConfig(const char *Cmd) {
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||||
tmp = param_getchar(Cmd, cmdp);
|
tmp = tolower(param_getchar(Cmd, cmdp));
|
||||||
switch(tmp) {
|
switch(tmp) {
|
||||||
case 'h':
|
case 'h':
|
||||||
case 'H':
|
|
||||||
return usage_t55xx_config();
|
return usage_t55xx_config();
|
||||||
case 'b':
|
case 'b':
|
||||||
errors |= param_getdec(Cmd, cmdp+1, &bitRate);
|
errors |= param_getdec(Cmd, cmdp+1, &bitRate);
|
||||||
|
@ -292,12 +303,10 @@ int CmdT55xxSetConfig(const char *Cmd) {
|
||||||
config.offset = offset;
|
config.offset = offset;
|
||||||
cmdp+=2;
|
cmdp+=2;
|
||||||
break;
|
break;
|
||||||
case 'Q':
|
|
||||||
case 'q':
|
case 'q':
|
||||||
config.Q5 = true;
|
config.Q5 = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
case 'S':
|
|
||||||
case 's':
|
case 's':
|
||||||
config.ST = true;
|
config.ST = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
|
@ -343,8 +352,8 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32
|
||||||
if (!AquireData(page1, block, usepwd, password) ) return 0;
|
if (!AquireData(page1, block, usepwd, password) ) return 0;
|
||||||
if (!DecodeT55xxBlock()) return 0;
|
if (!DecodeT55xxBlock()) return 0;
|
||||||
|
|
||||||
char blk[10]={0};
|
char blk[10] = {0};
|
||||||
sprintf(blk,"%02d", block);
|
sprintf(blk, "%02d", block);
|
||||||
printT55xxBlock(blk);
|
printT55xxBlock(blk);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -358,22 +367,18 @@ int CmdT55xxReadBlock(const char *Cmd) {
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||||
switch(param_getchar(Cmd, cmdp)) {
|
switch ( tolower(param_getchar(Cmd, cmdp))) {
|
||||||
case 'h':
|
case 'h':
|
||||||
case 'H':
|
|
||||||
return usage_t55xx_read();
|
return usage_t55xx_read();
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'B':
|
|
||||||
errors |= param_getdec(Cmd, cmdp+1, &block);
|
errors |= param_getdec(Cmd, cmdp+1, &block);
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
case 'O':
|
|
||||||
override = true;
|
override = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'P':
|
|
||||||
password = param_get32ex(Cmd, cmdp+1, 0, 16);
|
password = param_get32ex(Cmd, cmdp+1, 0, 16);
|
||||||
usepwd = true;
|
usepwd = true;
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
|
@ -1503,23 +1508,68 @@ bool IsCancelled(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdT55xxBruteForce(const char *Cmd) {
|
int CmdT55xxChkPwds(const char *Cmd) {
|
||||||
|
|
||||||
// load a default pwd file.
|
// load a default pwd file.
|
||||||
char line[9];
|
char line[9];
|
||||||
char filename[FILE_PATH_SIZE] = {0};
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
int keycnt = 0;
|
int keycnt = 0;
|
||||||
uint8_t stKeyBlock = 20;
|
uint8_t stKeyBlock = 20;
|
||||||
uint8_t *keyBlock = NULL, *p = NULL;
|
uint8_t *keyBlock = NULL, *p = NULL;
|
||||||
uint32_t start_password = 0x00000000; //start password
|
|
||||||
uint32_t end_password = 0xFFFFFFFF; //end password
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
uint8_t timeout = 0;
|
||||||
|
|
||||||
memset(line, 0, sizeof(line));
|
memset(line, 0, sizeof(line));
|
||||||
|
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
if (cmdp == 'h') return usage_t55xx_bruteforce();
|
if (cmdp == 'h') return usage_t55xx_chk();
|
||||||
|
|
||||||
|
/*
|
||||||
|
if ( T55xxReadBlock(7, 0, 0, 0, 0) ) {
|
||||||
|
|
||||||
|
// now try to validate it..
|
||||||
|
PrintAndLogEx(WARNING, "\n Block 7 was readable");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint64_t t1 = msclock();
|
||||||
|
|
||||||
|
if ( cmdp == 'm' ) {
|
||||||
|
UsbCommand c = {CMD_T55XX_CHKPWDS, {0,0,0} };
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommand(&c);
|
||||||
|
UsbCommand resp;
|
||||||
|
|
||||||
|
while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
|
||||||
|
timeout++;
|
||||||
|
printf("."); fflush(stdout);
|
||||||
|
if (timeout > 180) {
|
||||||
|
PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting...");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( resp.arg[0] ) {
|
||||||
|
PrintAndLogEx(SUCCESS, "\nFound a candidate [ %08X ]. Trying to validate", resp.arg[1]);
|
||||||
|
|
||||||
|
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.arg[1])) {
|
||||||
|
PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
found = tryDetectModulation();
|
||||||
|
if (found) {
|
||||||
|
PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", resp.arg[1]);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(WARNING, "Password NOT found.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(WARNING, "Password NOT found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
keyBlock = calloc(stKeyBlock, 4);
|
keyBlock = calloc(stKeyBlock, 4);
|
||||||
if (keyBlock == NULL) return 1;
|
if (keyBlock == NULL) return 1;
|
||||||
|
|
||||||
|
@ -1531,7 +1581,7 @@ int CmdT55xxBruteForce(const char *Cmd) {
|
||||||
|
|
||||||
FILE * f = fopen( filename , "r");
|
FILE * f = fopen( filename , "r");
|
||||||
if ( !f ) {
|
if ( !f ) {
|
||||||
PrintAndLogEx(NORMAL, "File: %s: not found or locked.", filename);
|
PrintAndLogEx(WARNING, "File: %s: not found or locked.", filename);
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1546,7 +1596,7 @@ int CmdT55xxBruteForce(const char *Cmd) {
|
||||||
if( line[0]=='#' ) continue;
|
if( line[0]=='#' ) continue;
|
||||||
|
|
||||||
if (!isxdigit(line[0])) {
|
if (!isxdigit(line[0])) {
|
||||||
PrintAndLogEx(NORMAL, "File content error. '%s' must include 8 HEX symbols", line);
|
PrintAndLogEx(WARNING, "File content error. '%s' must include 8 HEX symbols", line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1569,7 +1619,7 @@ int CmdT55xxBruteForce(const char *Cmd) {
|
||||||
|
|
||||||
num_to_bytes( strtoll(line, NULL, 16), 4, keyBlock + 4*keycnt);
|
num_to_bytes( strtoll(line, NULL, 16), 4, keyBlock + 4*keycnt);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4 * keycnt, 4) );
|
// PrintAndLogEx(NORMAL, "chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4 * keycnt, 4) );
|
||||||
keycnt++;
|
keycnt++;
|
||||||
memset(line, 0, sizeof(line));
|
memset(line, 0, sizeof(line));
|
||||||
}
|
}
|
||||||
|
@ -1577,11 +1627,11 @@ int CmdT55xxBruteForce(const char *Cmd) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
if (keycnt == 0) {
|
if (keycnt == 0) {
|
||||||
PrintAndLogEx(NORMAL, "No keys found in file");
|
PrintAndLogEx(WARNING, "No keys found in file");
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "Loaded %d keys", keycnt);
|
PrintAndLogEx(SUCCESS, "Loaded %d keys", keycnt);
|
||||||
|
|
||||||
// loop
|
// loop
|
||||||
uint64_t testpwd = 0x00;
|
uint64_t testpwd = 0x00;
|
||||||
|
@ -1600,69 +1650,87 @@ int CmdT55xxBruteForce(const char *Cmd) {
|
||||||
|
|
||||||
testpwd = bytes_to_num(keyBlock + 4*c, 4);
|
testpwd = bytes_to_num(keyBlock + 4*c, 4);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Testing %08X", testpwd);
|
PrintAndLogEx(INFO, "Testing %08X", testpwd);
|
||||||
|
|
||||||
if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd)) {
|
if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd)) {
|
||||||
PrintAndLogEx(NORMAL, "Aquireing data from device failed. Quitting");
|
PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting");
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
found = tryDetectModulation();
|
found = tryDetectModulation();
|
||||||
if ( found ) {
|
if ( found )
|
||||||
PrintAndLogEx(NORMAL, "Found valid password: [%08X]", testpwd);
|
break;
|
||||||
//free(keyBlock);
|
|
||||||
//return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "Password NOT found.");
|
if ( found )
|
||||||
free(keyBlock);
|
PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", testpwd);
|
||||||
return 0;
|
else
|
||||||
|
PrintAndLogEx(WARNING, "Password NOT found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(keyBlock);
|
||||||
|
|
||||||
|
out:
|
||||||
|
t1 = msclock() - t1;
|
||||||
|
PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdT55xxBruteForce(const char *Cmd) {
|
||||||
|
|
||||||
|
uint32_t start_password = 0x00000000; //start password
|
||||||
|
uint32_t end_password = 0xFFFFFFFF; //end password
|
||||||
|
uint32_t curr = 0;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
|
||||||
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
|
if (cmdp == 'h') return usage_t55xx_bruteforce();
|
||||||
|
|
||||||
|
uint64_t t1 = msclock();
|
||||||
|
|
||||||
// Try to read Block 7, first :)
|
// Try to read Block 7, first :)
|
||||||
|
|
||||||
// incremental pwd range search
|
// incremental pwd range search
|
||||||
start_password = param_get32ex(Cmd, 0, 0, 16);
|
start_password = param_get32ex(Cmd, 0, 0, 16);
|
||||||
end_password = param_get32ex(Cmd, 1, 0, 16);
|
end_password = param_get32ex(Cmd, 1, 0, 16);
|
||||||
|
|
||||||
|
curr = start_password;
|
||||||
|
|
||||||
if ( start_password >= end_password ) {
|
if ( start_password >= end_password ) {
|
||||||
free(keyBlock);
|
|
||||||
return usage_t55xx_bruteforce();
|
return usage_t55xx_bruteforce();
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Search password range [%08X -> %08X]", start_password, end_password);
|
PrintAndLogEx(INFO, "Search password range [%08X -> %08X]", start_password, end_password);
|
||||||
|
|
||||||
uint32_t i = start_password;
|
|
||||||
|
|
||||||
while ((!found) && (i <= end_password)){
|
while ((!found) || (curr <= end_password)){
|
||||||
|
|
||||||
printf("."); fflush(stdout);
|
printf("."); fflush(stdout);
|
||||||
|
|
||||||
if (IsCancelled()) {
|
if (IsCancelled()) {
|
||||||
free(keyBlock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, i)) {
|
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr)) {
|
||||||
PrintAndLogEx(NORMAL, "Aquireing data from device failed. Quitting");
|
PrintAndLogEx(WARNING, "Aquireing data from device failed. Quitting");
|
||||||
free(keyBlock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
found = tryDetectModulation();
|
found = tryDetectModulation();
|
||||||
|
|
||||||
if (found) break;
|
if (found) break;
|
||||||
i++;
|
++curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
PrintAndLogEx(NORMAL, "Found valid password: [%08x]", i);
|
PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", curr);
|
||||||
else
|
else
|
||||||
PrintAndLogEx(NORMAL, "Password NOT found. Last tried: [%08x]", --i);
|
PrintAndLogEx(WARNING, "Password NOT found. Last tried: [ %08X ]", --curr);
|
||||||
|
|
||||||
free(keyBlock);
|
t1 = msclock() - t1;
|
||||||
|
PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1746,9 +1814,9 @@ int CmdT55xxRecoverPW(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
if (found == 1)
|
if (found == 1)
|
||||||
PrintAndLogEx(NORMAL, "Found valid password: [%08x]", curr_password);
|
PrintAndLogEx(SUCCESS, "Found valid password: [%08x]", curr_password);
|
||||||
else
|
else
|
||||||
PrintAndLogEx(NORMAL, "Password NOT found.");
|
PrintAndLogEx(WARNING, "Password NOT found.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1959,6 +2027,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, 1, "This help"},
|
{"help", CmdHelp, 1, "This help"},
|
||||||
{"bruteforce", CmdT55xxBruteForce,0, "<start password> <end password> [i <*.dic>] Simple bruteforce attack to find password"},
|
{"bruteforce", CmdT55xxBruteForce,0, "<start password> <end password> [i <*.dic>] Simple bruteforce attack to find password"},
|
||||||
{"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
|
{"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
|
||||||
|
{"chk", CmdT55xxChkPwds, 1, "Check passwords"},
|
||||||
{"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."},
|
{"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."},
|
||||||
{"deviceconfig", CmdT55xxSetDeviceConfig, 1, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"},
|
{"deviceconfig", CmdT55xxSetDeviceConfig, 1, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"},
|
||||||
{"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"},
|
{"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"},
|
||||||
|
|
|
@ -133,6 +133,7 @@ t55xx_conf_block_t Get_t55xx_Config(void);
|
||||||
void Set_t55xx_Config(t55xx_conf_block_t conf);
|
void Set_t55xx_Config(t55xx_conf_block_t conf);
|
||||||
|
|
||||||
extern int CmdLFT55XX(const char *Cmd);
|
extern int CmdLFT55XX(const char *Cmd);
|
||||||
|
extern int CmdT55xxChk(const char *Cmd);
|
||||||
extern int CmdT55xxBruteForce(const char *Cmd);
|
extern int CmdT55xxBruteForce(const char *Cmd);
|
||||||
extern int CmdT55xxSetConfig(const char *Cmd);
|
extern int CmdT55xxSetConfig(const char *Cmd);
|
||||||
extern int CmdT55xxReadBlock(const char *Cmd);
|
extern int CmdT55xxReadBlock(const char *Cmd);
|
||||||
|
|
|
@ -356,7 +356,7 @@ static int smart_responseEx(uint8_t *data, bool silent) {
|
||||||
if (needGetData) {
|
if (needGetData) {
|
||||||
int len = data[datalen - 1];
|
int len = data[datalen - 1];
|
||||||
if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len);
|
if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len);
|
||||||
uint8_t getstatus[] = {0x00, ISO7816_GETSTATUS, 0x00, 0x00, len};
|
uint8_t getstatus[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, len};
|
||||||
UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}};
|
UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}};
|
||||||
memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) );
|
memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) );
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
@ -372,7 +372,7 @@ static int smart_responseEx(uint8_t *data, bool silent) {
|
||||||
if (datalen != len + 2) {
|
if (datalen != len + 2) {
|
||||||
// data with ACK
|
// data with ACK
|
||||||
if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK
|
if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK
|
||||||
if (data[0] != ISO7816_GETSTATUS) {
|
if (data[0] != ISO7816_GET_RESPONSE) {
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]);
|
PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]);
|
||||||
}
|
}
|
||||||
|
@ -1012,7 +1012,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) {
|
||||||
json_t *root = NULL;
|
json_t *root = NULL;
|
||||||
smart_loadjson("aidlist", "json", &root);
|
smart_loadjson("aidlist", "json", &root);
|
||||||
|
|
||||||
uint8_t* buf = malloc(USB_CMD_DATA_SIZE);
|
uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t));
|
||||||
if ( !buf )
|
if ( !buf )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
@ -711,4 +711,47 @@ FD8705E721B0,
|
||||||
00ada2cd516d,
|
00ada2cd516d,
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
D3F7D3F7D3F7
|
D3F7D3F7D3F7
|
||||||
|
##
|
||||||
|
237a4d0d9119,
|
||||||
|
0ed7846c2bc9,
|
||||||
|
FFFFD06F83E3,
|
||||||
|
FFFFAE82366C,
|
||||||
|
F89C86B2A961,
|
||||||
|
F83466888612,
|
||||||
|
ED3A7EFBFF56,
|
||||||
|
E96246531342,
|
||||||
|
E1DD284379D4,
|
||||||
|
DFED39FFBB76,
|
||||||
|
DB5181C92CBE,
|
||||||
|
CFC738403AB0,
|
||||||
|
BCFE01BCFE01,
|
||||||
|
BA28CFD15EE8,
|
||||||
|
B0699AD03D17,
|
||||||
|
AABBCC660429,
|
||||||
|
A4EF6C3BB692,
|
||||||
|
A2B2C9D187FB,
|
||||||
|
9B1DD7C030A1,
|
||||||
|
9AEDF9931EC1,
|
||||||
|
8F9B229047AC,
|
||||||
|
872B71F9D15A,
|
||||||
|
833FBD3CFE51,
|
||||||
|
5D293AFC8D7E,
|
||||||
|
5554AAA96321,
|
||||||
|
474249437569,
|
||||||
|
435330666666,
|
||||||
|
1A2B3C4D5E6F,
|
||||||
|
123456ABCDEF,
|
||||||
|
83BAB5ACAD62,
|
||||||
|
64E2283FCF5E,
|
||||||
|
64A2EE93B12B,
|
||||||
|
46868F6D5677,
|
||||||
|
40E5EA1EFC00,
|
||||||
|
37D4DCA92451,
|
||||||
|
2012053082AD,
|
||||||
|
2011092119F1,
|
||||||
|
200306202033,
|
||||||
|
1795902DBAF9,
|
||||||
|
17505586EF02,
|
||||||
|
022FE48B3072,
|
||||||
|
013940233313,
|
||||||
|
|
|
@ -96,6 +96,7 @@ FABADA11, //china?
|
||||||
69696969,
|
69696969,
|
||||||
12121212,
|
12121212,
|
||||||
12344321,
|
12344321,
|
||||||
|
1234ABCD,
|
||||||
11112222,
|
11112222,
|
||||||
13131313,
|
13131313,
|
||||||
10041004,
|
10041004,
|
||||||
|
@ -104,8 +105,8 @@ FABADA11, //china?
|
||||||
abcd1234,
|
abcd1234,
|
||||||
20002000,
|
20002000,
|
||||||
19721972,
|
19721972,
|
||||||
aa55aa55, //amiboo
|
aa55aa55, // amiboo
|
||||||
55aa55aa, //rev amiboo
|
55aa55aa, // rev amiboo
|
||||||
4f271149, // seeds ul-ev1
|
4f271149, // seeds ul-ev1
|
||||||
07d7bb0b, // seeds ul-ev1
|
07d7bb0b, // seeds ul-ev1
|
||||||
9636ef8f, // seeds ul-ev1
|
9636ef8f, // seeds ul-ev1
|
||||||
|
@ -113,4 +114,4 @@ b5f44686, // seeds ul-ev1
|
||||||
9E3779B9, // TEA
|
9E3779B9, // TEA
|
||||||
C6EF3720, // TEA
|
C6EF3720, // TEA
|
||||||
7854794A, // xbox tea constant :)
|
7854794A, // xbox tea constant :)
|
||||||
F1EA5EED, //burtle
|
F1EA5EED, // burtle
|
||||||
|
|
1000
client/dictionaries/bmp_sort_keys.dic
Normal file
1000
client/dictionaries/bmp_sort_keys.dic
Normal file
File diff suppressed because it is too large
Load diff
1001
client/dictionaries/icbpm_sort_keys.dic
Normal file
1001
client/dictionaries/icbpm_sort_keys.dic
Normal file
File diff suppressed because it is too large
Load diff
57
client/dictionaries/mrzd_sort_keys.dic
Normal file
57
client/dictionaries/mrzd_sort_keys.dic
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
010203040506,
|
||||||
|
013940233313,
|
||||||
|
022FE48B3072,
|
||||||
|
123456789ABC,
|
||||||
|
123456ABCDEF,
|
||||||
|
17505586EF02,
|
||||||
|
1795902DBAF9,
|
||||||
|
1A2B3C4D5E6F,
|
||||||
|
1A982C7E459A,
|
||||||
|
200306202033,
|
||||||
|
2011092119F1,
|
||||||
|
2012053082AD,
|
||||||
|
37D4DCA92451,
|
||||||
|
40E5EA1EFC00,
|
||||||
|
435330666666,
|
||||||
|
46868F6D5677,
|
||||||
|
474249437569,
|
||||||
|
4D3A99C351DD,
|
||||||
|
533CB6C723F6,
|
||||||
|
5554AAA96321,
|
||||||
|
587EE5F9350F,
|
||||||
|
5A1B85FCE20A,
|
||||||
|
5D293AFC8D7E,
|
||||||
|
64A2EE93B12B,
|
||||||
|
64E2283FCF5E,
|
||||||
|
714C5C886E97,
|
||||||
|
833FBD3CFE51,
|
||||||
|
83BAB5ACAD62,
|
||||||
|
872B71F9D15A,
|
||||||
|
8F9B229047AC,
|
||||||
|
8FD0A4F256E9,
|
||||||
|
9AEDF9931EC1,
|
||||||
|
9B1DD7C030A1,
|
||||||
|
A0478CC39091,
|
||||||
|
A0A1A2A3A4A5,
|
||||||
|
A2B2C9D187FB,
|
||||||
|
A4EF6C3BB692,
|
||||||
|
AABBCC660429,
|
||||||
|
AABBCCDDEEFF,
|
||||||
|
ABCDEF123456,
|
||||||
|
B0699AD03D17,
|
||||||
|
B0B1B2B3B4B5,
|
||||||
|
BA28CFD15EE8,
|
||||||
|
BCFE01BCFE01,
|
||||||
|
C0C1C2C3C4C5,
|
||||||
|
CFC738403AB0,
|
||||||
|
D0D1D2D3D4D5,
|
||||||
|
D3F7D3F7D3F7,
|
||||||
|
DB5181C92CBE,
|
||||||
|
DFED39FFBB76,
|
||||||
|
E1DD284379D4,
|
||||||
|
E96246531342,
|
||||||
|
ED3A7EFBFF56,
|
||||||
|
F83466888612,
|
||||||
|
F89C86B2A961,
|
||||||
|
FFFFAE82366C,
|
||||||
|
FFFFD06F83E3,
|
|
@ -623,7 +623,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;}
|
#define dreturn(n) {free(pdol_data_tlv); tlvdb_free(tlvSelect); tlvdb_free(tlvRoot); DropFieldEx( channel ); return n;}
|
||||||
|
|
||||||
void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, enum TransactionType TrType, bool GenACGPO) {
|
void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, enum TransactionType TrType, bool GenACGPO) {
|
||||||
|
|
||||||
|
@ -1244,7 +1244,7 @@ int CmdEMVExec(const char *cmd) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
|
|
||||||
// Destroy TLV's
|
// Destroy TLV's
|
||||||
free(pdol_data_tlv);
|
free(pdol_data_tlv);
|
||||||
|
@ -1346,7 +1346,7 @@ int CmdEMVScan(const char *cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// drop field at start
|
// drop field at start
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
|
|
||||||
// iso 14443 select
|
// iso 14443 select
|
||||||
PrintAndLogEx(NORMAL, "--> GET UID, ATS.");
|
PrintAndLogEx(NORMAL, "--> GET UID, ATS.");
|
||||||
|
@ -1399,7 +1399,7 @@ int CmdEMVScan(const char *cmd) {
|
||||||
if (EMVSearch(channel, false, true, decodeTLV, tlvSelect)) {
|
if (EMVSearch(channel, false, true, decodeTLV, tlvSelect)) {
|
||||||
PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
|
PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
|
||||||
tlvdb_free(tlvSelect);
|
tlvdb_free(tlvSelect);
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1415,7 +1415,7 @@ int CmdEMVScan(const char *cmd) {
|
||||||
|
|
||||||
if (!AIDlen) {
|
if (!AIDlen) {
|
||||||
PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
|
PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1434,7 +1434,7 @@ int CmdEMVScan(const char *cmd) {
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
|
PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
|
||||||
tlvdb_free(tlvRoot);
|
tlvdb_free(tlvRoot);
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1462,7 +1462,7 @@ int CmdEMVScan(const char *cmd) {
|
||||||
if (!pdol_data_tlv){
|
if (!pdol_data_tlv){
|
||||||
PrintAndLogEx(ERR, "Can't create PDOL TLV.");
|
PrintAndLogEx(ERR, "Can't create PDOL TLV.");
|
||||||
tlvdb_free(tlvRoot);
|
tlvdb_free(tlvRoot);
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1471,7 +1471,7 @@ int CmdEMVScan(const char *cmd) {
|
||||||
if (!pdol_data_tlv_data) {
|
if (!pdol_data_tlv_data) {
|
||||||
PrintAndLogEx(ERR, "Can't create PDOL data.");
|
PrintAndLogEx(ERR, "Can't create PDOL data.");
|
||||||
tlvdb_free(tlvRoot);
|
tlvdb_free(tlvRoot);
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
|
PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
|
||||||
|
@ -1485,7 +1485,7 @@ int CmdEMVScan(const char *cmd) {
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
|
PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
|
||||||
tlvdb_free(tlvRoot);
|
tlvdb_free(tlvRoot);
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV);
|
ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV);
|
||||||
|
@ -1577,8 +1577,7 @@ int CmdEMVScan(const char *cmd) {
|
||||||
// free tlv object
|
// free tlv object
|
||||||
tlvdb_free(tlvRoot);
|
tlvdb_free(tlvRoot);
|
||||||
|
|
||||||
// DropField
|
DropFieldEx( channel );
|
||||||
DropField();
|
|
||||||
|
|
||||||
res = json_dump_file(root, fname, JSON_INDENT(2));
|
res = json_dump_file(root, fname, JSON_INDENT(2));
|
||||||
if (res) {
|
if (res) {
|
||||||
|
@ -1631,6 +1630,14 @@ int CmdEMVRoca(const char *cmd) {
|
||||||
if (arg_get_lit(2))
|
if (arg_get_lit(2))
|
||||||
channel = ECC_CONTACT;
|
channel = ECC_CONTACT;
|
||||||
PrintChannel(channel);
|
PrintChannel(channel);
|
||||||
|
|
||||||
|
#ifndef WITH_SMARTCARD
|
||||||
|
// not compiled with smartcard functionality, we need to exit
|
||||||
|
if ( channel == ECC_CONTACT ) {
|
||||||
|
PrintAndLogEx(WARNING, "PM3 Client is not compiled with support for SMARTCARD. Exiting.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// select card
|
// select card
|
||||||
uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
|
uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
|
||||||
|
@ -1654,7 +1661,7 @@ int CmdEMVRoca(const char *cmd) {
|
||||||
if (EMVSearch(channel, false, true, false, tlvSelect)) {
|
if (EMVSearch(channel, false, true, false, tlvSelect)) {
|
||||||
PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
|
PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
|
||||||
tlvdb_free(tlvSelect);
|
tlvdb_free(tlvSelect);
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1670,7 +1677,7 @@ int CmdEMVRoca(const char *cmd) {
|
||||||
|
|
||||||
if (!AIDlen) {
|
if (!AIDlen) {
|
||||||
PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
|
PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit...");
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1685,7 +1692,7 @@ int CmdEMVRoca(const char *cmd) {
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
|
PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
|
||||||
tlvdb_free(tlvRoot);
|
tlvdb_free(tlvRoot);
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1697,7 +1704,7 @@ int CmdEMVRoca(const char *cmd) {
|
||||||
if (!pdol_data_tlv){
|
if (!pdol_data_tlv){
|
||||||
PrintAndLogEx(ERR, "Can't create PDOL TLV.");
|
PrintAndLogEx(ERR, "Can't create PDOL TLV.");
|
||||||
tlvdb_free(tlvRoot);
|
tlvdb_free(tlvRoot);
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1706,7 +1713,7 @@ int CmdEMVRoca(const char *cmd) {
|
||||||
if (!pdol_data_tlv_data) {
|
if (!pdol_data_tlv_data) {
|
||||||
PrintAndLogEx(ERR, "Can't create PDOL data.");
|
PrintAndLogEx(ERR, "Can't create PDOL data.");
|
||||||
tlvdb_free(tlvRoot);
|
tlvdb_free(tlvRoot);
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
|
PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
|
||||||
|
@ -1720,7 +1727,7 @@ int CmdEMVRoca(const char *cmd) {
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
|
PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
|
||||||
tlvdb_free(tlvRoot);
|
tlvdb_free(tlvRoot);
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
ProcessGPOResponseFormat1(tlvRoot, buf, len, false);
|
ProcessGPOResponseFormat1(tlvRoot, buf, len, false);
|
||||||
|
@ -1818,10 +1825,7 @@ out:
|
||||||
// free tlv object
|
// free tlv object
|
||||||
tlvdb_free(tlvRoot);
|
tlvdb_free(tlvRoot);
|
||||||
|
|
||||||
if ( channel == ECC_CONTACTLESS)
|
DropFieldEx( channel );
|
||||||
DropField();
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,7 +241,7 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
if (ActivateField) {
|
if (ActivateField) {
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
msleep(50);
|
msleep(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,8 +262,12 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ECC_CONTACT:
|
case ECC_CONTACT:
|
||||||
|
#ifdef WITH_SMARTCARD
|
||||||
//int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
|
//int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
|
||||||
res = ExchangeAPDUSC(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
|
res = ExchangeAPDUSC(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
|
||||||
|
#else
|
||||||
|
res = 1;
|
||||||
|
#endif
|
||||||
if (res) {
|
if (res) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -480,7 +484,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!LeaveFieldON)
|
if(!LeaveFieldON)
|
||||||
DropField();
|
DropFieldEx( channel );
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,23 @@
|
||||||
"U9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\r\n" \
|
"U9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\r\n" \
|
||||||
"-----END CERTIFICATE-----\r\n"
|
"-----END CERTIFICATE-----\r\n"
|
||||||
|
|
||||||
|
// Name: SoloKey U2F Root CA Serial 14143382635911888524 (0xc44763928ff4be8c)
|
||||||
|
// Issued: 2018-11-11
|
||||||
|
#define SOLOKEY_CA \
|
||||||
|
"-----BEGIN CERTIFICATE-----\r\n" \
|
||||||
|
"MIIB9DCCAZoCCQDER2OSj/S+jDAKBggqhkjOPQQDAjCBgDELMAkGA1UEBhMCVVMx\r\n" \
|
||||||
|
"ETAPBgNVBAgMCE1hcnlsYW5kMRIwEAYDVQQKDAlTb2xvIEtleXMxEDAOBgNVBAsM\r\n" \
|
||||||
|
"B1Jvb3QgQ0ExFTATBgNVBAMMDHNvbG9rZXlzLmNvbTEhMB8GCSqGSIb3DQEJARYS\r\n" \
|
||||||
|
"aGVsbG9Ac29sb2tleXMuY29tMCAXDTE4MTExMTEyNTE0MloYDzIwNjgxMDI5MTI1\r\n" \
|
||||||
|
"MTQyWjCBgDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE1hcnlsYW5kMRIwEAYDVQQK\r\n" \
|
||||||
|
"DAlTb2xvIEtleXMxEDAOBgNVBAsMB1Jvb3QgQ0ExFTATBgNVBAMMDHNvbG9rZXlz\r\n" \
|
||||||
|
"LmNvbTEhMB8GCSqGSIb3DQEJARYSaGVsbG9Ac29sb2tleXMuY29tMFkwEwYHKoZI\r\n" \
|
||||||
|
"zj0CAQYIKoZIzj0DAQcDQgAEWHAN0CCJVZdMs0oktZ5m93uxmB1iyq8ELRLtqVFL\r\n" \
|
||||||
|
"SOiHQEab56qRTB/QzrpGAY++Y2mw+vRuQMNhBiU0KzwjBjAKBggqhkjOPQQDAgNI\r\n" \
|
||||||
|
"ADBFAiEAz9SlrAXIlEu87vra54rICPs+4b0qhp3PdzcTg7rvnP0CIGjxzlteQQx+\r\n" \
|
||||||
|
"jQGd7rwSZuE5RWUPVygYhUstQO9zNUOs\r\n" \
|
||||||
|
"-----END CERTIFICATE-----\r\n"
|
||||||
|
|
||||||
/* Concatenation of all additional CA certificates in PEM format if available */
|
/* Concatenation of all additional CA certificates in PEM format if available */
|
||||||
const char additional_ca_pem[] = GLOBALSIGN_CA YUBICO_CA;
|
const char additional_ca_pem[] = GLOBALSIGN_CA YUBICO_CA SOLOKEY_CA;
|
||||||
const size_t additional_ca_pem_len = sizeof(additional_ca_pem);
|
const size_t additional_ca_pem_len = sizeof(additional_ca_pem);
|
||||||
|
|
|
@ -250,9 +250,9 @@ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *pu
|
||||||
uint32_t verifyflags = 0;
|
uint32_t verifyflags = 0;
|
||||||
res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL);
|
res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL);
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLog("ERROR: DER verify returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res));
|
PrintAndLog("ERROR: DER verify returned 0x%x - %s\n", (res<0)?-res:res, ecdsa_get_error(res));
|
||||||
} else {
|
} else {
|
||||||
PrintAndLog("Certificate OK.");
|
PrintAndLog("Certificate OK.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs,
|
||||||
flash_seg_t *seg;
|
flash_seg_t *seg;
|
||||||
uint32_t last_end = 0;
|
uint32_t last_end = 0;
|
||||||
|
|
||||||
ctx->segments = malloc(sizeof(flash_seg_t) * num_phdrs);
|
ctx->segments = calloc(sizeof(flash_seg_t) * num_phdrs, sizeof(uint8_t));
|
||||||
if (!ctx->segments) {
|
if (!ctx->segments) {
|
||||||
fprintf(stderr, "Out of memory\n");
|
fprintf(stderr, "Out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -88,7 +88,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs,
|
||||||
|
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
// make extra space if we need to move the data forward
|
// make extra space if we need to move the data forward
|
||||||
data = malloc(filesz + BLOCK_SIZE);
|
data = calloc(filesz + BLOCK_SIZE, sizeof(uint8_t));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
fprintf(stderr, "Error: Out of memory\n");
|
fprintf(stderr, "Error: Out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -111,7 +111,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs,
|
||||||
uint32_t new_length = this_end - prev_seg->start;
|
uint32_t new_length = this_end - prev_seg->start;
|
||||||
uint32_t this_offset = paddr - prev_seg->start;
|
uint32_t this_offset = paddr - prev_seg->start;
|
||||||
uint32_t hole = this_offset - prev_seg->length;
|
uint32_t hole = this_offset - prev_seg->length;
|
||||||
uint8_t *new_data = malloc(new_length);
|
uint8_t *new_data = calloc(new_length, sizeof(uint8_t));
|
||||||
if (!new_data) {
|
if (!new_data) {
|
||||||
fprintf(stderr, "Error: Out of memory\n");
|
fprintf(stderr, "Error: Out of memory\n");
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -223,7 +223,7 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) {
|
||||||
}
|
}
|
||||||
num_phdrs = le16(ehdr.e_phnum);
|
num_phdrs = le16(ehdr.e_phnum);
|
||||||
|
|
||||||
phdrs = malloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr));
|
phdrs = calloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr), sizeof(uint8_t));
|
||||||
if (!phdrs) {
|
if (!phdrs) {
|
||||||
fprintf(stderr, "Out of memory\n");
|
fprintf(stderr, "Out of memory\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -59,7 +59,7 @@ static void usage(void)
|
||||||
|
|
||||||
static voidpf fpga_deflate_malloc(voidpf opaque, uInt items, uInt size)
|
static voidpf fpga_deflate_malloc(voidpf opaque, uInt items, uInt size)
|
||||||
{
|
{
|
||||||
return malloc(items*size);
|
return calloc(items*size, sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,9 +89,9 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn
|
||||||
z_stream compressed_fpga_stream;
|
z_stream compressed_fpga_stream;
|
||||||
|
|
||||||
if (hardnested_mode) {
|
if (hardnested_mode) {
|
||||||
fpga_config = malloc(num_infiles * HARDNESTED_TABLE_SIZE);
|
fpga_config = calloc(num_infiles * HARDNESTED_TABLE_SIZE, sizeof(uint8_t));
|
||||||
} else {
|
} else {
|
||||||
fpga_config = malloc(num_infiles * FPGA_CONFIG_SIZE);
|
fpga_config = calloc(num_infiles * FPGA_CONFIG_SIZE, sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
// read the input files. Interleave them into fpga_config[]
|
// read the input files. Interleave them into fpga_config[]
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
|
@ -40,7 +40,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs,
|
||||||
flash_seg_t *seg;
|
flash_seg_t *seg;
|
||||||
uint32_t last_end = 0;
|
uint32_t last_end = 0;
|
||||||
|
|
||||||
ctx->segments = malloc(sizeof(flash_seg_t) * num_phdrs);
|
ctx->segments = calloc(sizeof(flash_seg_t) * num_phdrs, sizeof(uint8_t));
|
||||||
if (!ctx->segments) {
|
if (!ctx->segments) {
|
||||||
fprintf(stderr, "Out of memory\n");
|
fprintf(stderr, "Out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -90,7 +90,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs,
|
||||||
|
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
// make extra space if we need to move the data forward
|
// make extra space if we need to move the data forward
|
||||||
data = malloc(filesz + BLOCK_SIZE);
|
data = calloc(filesz + BLOCK_SIZE, sizeof(uint8_t));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
fprintf(stderr, "Out of memory\n");
|
fprintf(stderr, "Out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -226,7 +226,7 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl)
|
||||||
}
|
}
|
||||||
num_phdrs = le16(ehdr.e_phnum);
|
num_phdrs = le16(ehdr.e_phnum);
|
||||||
|
|
||||||
phdrs = malloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr));
|
phdrs = calloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr), sizeof(uint8_t));
|
||||||
if (!phdrs) {
|
if (!phdrs) {
|
||||||
fprintf(stderr, "Out of memory\n");
|
fprintf(stderr, "Out of memory\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -224,7 +224,7 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
|
||||||
{
|
{
|
||||||
uint8_t cc_nr[13] = { 0 };
|
uint8_t cc_nr[13] = { 0 };
|
||||||
uint8_t div_key[8];
|
uint8_t div_key[8];
|
||||||
//cc_nr=(uint8_t*)malloc(length+1);
|
//cc_nr=(uint8_t*) calloc(length+1, sizeof(uint8_t));
|
||||||
|
|
||||||
memcpy(cc_nr, cc_nr_p, 12);
|
memcpy(cc_nr, cc_nr_p, 12);
|
||||||
memcpy(div_key, div_key_p, 8);
|
memcpy(div_key, div_key_p, 8);
|
||||||
|
@ -244,7 +244,7 @@ void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_ke
|
||||||
{
|
{
|
||||||
uint8_t *address_data;
|
uint8_t *address_data;
|
||||||
uint8_t div_key[8];
|
uint8_t div_key[8];
|
||||||
address_data = (uint8_t*) malloc(address_data_size);
|
address_data = (uint8_t*) calloc(address_data_size, sizeof(uint8_t));
|
||||||
|
|
||||||
memcpy(address_data, address_data_p, address_data_size);
|
memcpy(address_data, address_data_p, address_data_size);
|
||||||
memcpy(div_key, div_key_p, 8);
|
memcpy(div_key, div_key_p, 8);
|
||||||
|
|
|
@ -52,7 +52,7 @@ typedef struct {
|
||||||
uint8_t * buffer;
|
uint8_t * buffer;
|
||||||
uint8_t numbits;
|
uint8_t numbits;
|
||||||
uint8_t position;
|
uint8_t position;
|
||||||
}BitstreamOut;
|
} BitstreamOut;
|
||||||
|
|
||||||
bool headBit( BitstreamIn *stream);
|
bool headBit( BitstreamIn *stream);
|
||||||
bool tailBit( BitstreamIn *stream);
|
bool tailBit( BitstreamIn *stream);
|
||||||
|
|
|
@ -493,7 +493,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) {
|
||||||
|
|
||||||
uint64_t t1 = msclock();
|
uint64_t t1 = msclock();
|
||||||
|
|
||||||
dumpdata* attack = (dumpdata* ) malloc(itemsize);
|
dumpdata* attack = (dumpdata* ) calloc(itemsize, sizeof(uint8_t));
|
||||||
|
|
||||||
for (i = 0 ; i * itemsize < dumpsize ; i++ ) {
|
for (i = 0 ; i * itemsize < dumpsize ; i++ ) {
|
||||||
memcpy(attack, dump + i * itemsize, itemsize);
|
memcpy(attack, dump + i * itemsize, itemsize);
|
||||||
|
|
|
@ -71,14 +71,14 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si
|
||||||
/*Opening file for writing in binary mode*/
|
/*Opening file for writing in binary mode*/
|
||||||
FILE *f = fopen(fileName, "wb");
|
FILE *f = fopen(fileName, "wb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
PrintAndLogDevice(WARNING, "file not found or locked. '%s'", fileName);
|
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName);
|
||||||
free(fileName);
|
free(fileName);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fwrite(data, 1, datalen, f);
|
fwrite(data, 1, datalen, f);
|
||||||
fflush(f);
|
fflush(f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
PrintAndLogDevice(SUCCESS, "saved %u bytes to binary file %s", datalen, fileName);
|
PrintAndLogDevice(SUCCESS, "saved %u bytes to binary file " _YELLOW_(%s), datalen, fileName);
|
||||||
free(fileName);
|
free(fileName);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -106,8 +106,8 @@ int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, si
|
||||||
|
|
||||||
/*Opening file for writing in text mode*/
|
/*Opening file for writing in text mode*/
|
||||||
FILE *f = fopen(fileName, "w+");
|
FILE *f = fopen(fileName, "w+");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
PrintAndLogDevice(WARNING, "file not found or locked. '%s'", fileName);
|
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, si
|
||||||
}
|
}
|
||||||
fflush(f);
|
fflush(f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
PrintAndLogDevice(SUCCESS, "saved %d blocks to text file %s", blocks, fileName);
|
PrintAndLogDevice(SUCCESS, "saved %d blocks to text file " _YELLOW_(%s), blocks, fileName);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(fileName);
|
free(fileName);
|
||||||
|
@ -240,13 +240,12 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
|
||||||
|
|
||||||
int res = json_dump_file(root, fileName, JSON_INDENT(2));
|
int res = json_dump_file(root, fileName, JSON_INDENT(2));
|
||||||
if (res) {
|
if (res) {
|
||||||
PrintAndLogDevice(FAILED, "error: can't save the file: %s", fileName);
|
PrintAndLogDevice(FAILED, "error: can't save the file: " _YELLOW_(%s), fileName);
|
||||||
json_decref(root);
|
json_decref(root);
|
||||||
retval = 200;
|
retval = 200;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
PrintAndLogDevice(SUCCESS, "File `%s` saved.", fileName);
|
PrintAndLogDevice(SUCCESS, "saved to json file " _YELLOW_(%s), fileName);
|
||||||
|
|
||||||
json_decref(root);
|
json_decref(root);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -266,7 +265,7 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t*
|
||||||
|
|
||||||
FILE *f = fopen(fileName, "rb");
|
FILE *f = fopen(fileName, "rb");
|
||||||
if ( !f ) {
|
if ( !f ) {
|
||||||
PrintAndLogDevice(FAILED, "file: %s: not found or locked.", fileName);
|
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -305,7 +304,7 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t*
|
||||||
memcpy( (data), dump, bytes_read);
|
memcpy( (data), dump, bytes_read);
|
||||||
free(dump);
|
free(dump);
|
||||||
|
|
||||||
PrintAndLogDevice(SUCCESS, "loaded %d bytes from binary file %s", bytes_read, fileName);
|
PrintAndLogDevice(SUCCESS, "loaded %d bytes from binary file " _YELLOW_(%s), bytes_read, fileName);
|
||||||
|
|
||||||
*datalen = bytes_read;
|
*datalen = bytes_read;
|
||||||
|
|
||||||
|
@ -328,7 +327,7 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_
|
||||||
|
|
||||||
FILE *f = fopen(fileName, "r");
|
FILE *f = fopen(fileName, "r");
|
||||||
if ( !f ) {
|
if ( !f ) {
|
||||||
PrintAndLogDevice(FAILED, "file: %s: not found or locked.", fileName);
|
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -359,7 +358,7 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
PrintAndLogDevice(SUCCESS, "loaded %d bytes from text file %s", counter, fileName);
|
PrintAndLogDevice(SUCCESS, "loaded %d bytes from text file " _YELLOW_(%s), counter, fileName);
|
||||||
*datalen = counter;
|
*datalen = counter;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -382,13 +381,13 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size
|
||||||
|
|
||||||
root = json_load_file(fileName, 0, &error);
|
root = json_load_file(fileName, 0, &error);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
PrintAndLog("ERROR: json (%s) error on line %d: %s", fileName, error.line, error.text);
|
PrintAndLog("ERROR: json " _YELLOW_(%s) " error on line %d: %s", fileName, error.line, error.text);
|
||||||
retval = 2;
|
retval = 2;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!json_is_object(root)) {
|
if (!json_is_object(root)) {
|
||||||
PrintAndLog("ERROR: Invalid json (%s) format. root must be an object.", fileName);
|
PrintAndLog("ERROR: Invalid json " _YELLOW_(%s) " format. root must be an object.", fileName);
|
||||||
retval = 3;
|
retval = 3;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -446,7 +445,7 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PrintAndLog("Loaded JSON: (%s) OK.", fileName);
|
PrintAndLog("loaded from JSON file " _YELLOW_(%s), fileName);
|
||||||
out:
|
out:
|
||||||
json_decref(root);
|
json_decref(root);
|
||||||
free(fileName);
|
free(fileName);
|
||||||
|
@ -479,7 +478,7 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data
|
||||||
|
|
||||||
FILE *f = fopen(fileName, "r");
|
FILE *f = fopen(fileName, "r");
|
||||||
if ( !f ) {
|
if ( !f ) {
|
||||||
PrintAndLogDevice(FAILED, "file: %s: not found or locked.", fileName);
|
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -512,7 +511,7 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data
|
||||||
counter += (keylen >> 1);
|
counter += (keylen >> 1);
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
PrintAndLogDevice(SUCCESS, "loaded " _GREEN_(%2d) "keys from dictionary file %s", *keycnt, fileName);
|
PrintAndLogDevice(SUCCESS, "loaded " _GREEN_(%2d) "keys from dictionary file " _YELLOW_(%s), *keycnt, fileName);
|
||||||
*datalen = counter;
|
*datalen = counter;
|
||||||
out:
|
out:
|
||||||
free(fileName);
|
free(fileName);
|
||||||
|
|
|
@ -1,72 +1,115 @@
|
||||||
local manufacturer = {}
|
local m = {}
|
||||||
manufacturer[0x01]='Motorola [UK]'
|
m[0x01]='Motorola UK'
|
||||||
manufacturer[0x02]='STMicroelectronics SA [France]'
|
m[0x02]='ST Microelectronics SA France'
|
||||||
manufacturer[0x03]='Hitachi, Ltd [Japan]'
|
m[0x03]='Hitachi, Ltd Japan'
|
||||||
manufacturer[0x04]='NXP Semiconductors [Germany]'
|
m[0x04]='NXP Semiconductors Germany'
|
||||||
manufacturer[0x05]='Infineon Technologies AG [Germany]'
|
m[0x05]='Infineon Technologies AG Germany'
|
||||||
manufacturer[0x06]='Cylink [USA]'
|
m[0x06]='Cylink USA'
|
||||||
manufacturer[0x07]='Texas Instrument [France]'
|
m[0x07]='Texas Instrument France'
|
||||||
manufacturer[0x08]='Fujitsu Limited [Japan]'
|
m[0x08]='Fujitsu Limited Japan'
|
||||||
manufacturer[0x09]='Matsushita Electronics Corporation, Semiconductor Company [Japan]'
|
m[0x09]='Matsushita Electronics Corporation, Semiconductor Company Japan'
|
||||||
manufacturer[0x0A]='NEC [Japan]'
|
m[0x0A]='NEC Japan'
|
||||||
manufacturer[0x0B]='Oki Electric Industry Co. Ltd [Japan]'
|
m[0x0B]='Oki Electric Industry Co. Ltd Japan'
|
||||||
manufacturer[0x0C]='Toshiba Corp. [Japan]'
|
m[0x0C]='Toshiba Corp. Japan'
|
||||||
manufacturer[0x0D]='Mitsubishi Electric Corp. [Japan]'
|
m[0x0D]='Mitsubishi Electric Corp. Japan'
|
||||||
manufacturer[0x0E]='Samsung Electronics Co. Ltd [Korea]'
|
m[0x0E]='Samsung Electronics Co. Ltd Korea'
|
||||||
manufacturer[0x0F]='Hynix [Korea]'
|
m[0x0F]='Hynix / Hyundai, Korea'
|
||||||
manufacturer[0x10]='LG-Semiconductors Co. Ltd [Korea]'
|
m[0x10]='LG-Semiconductors Co. Ltd Korea'
|
||||||
manufacturer[0x11]='Emosyn-EM Microelectronics [USA]'
|
m[0x11]='Emosyn-EM Microelectronics USA'
|
||||||
manufacturer[0x12]='INSIDE Technology [France]'
|
m[0x12]='INSIDE Technology France'
|
||||||
manufacturer[0x13]='ORGA Kartensysteme GmbH [Germany]'
|
m[0x13]='ORGA Kartensysteme GmbH Germany'
|
||||||
manufacturer[0x14]='SHARP Corporation [Japan]'
|
m[0x14]='SHARP Corporation Japan'
|
||||||
manufacturer[0x15]='ATMEL [France]'
|
m[0x15]='ATMEL France'
|
||||||
manufacturer[0x16]='EM Microelectronic-Marin SA [Switzerland]'
|
m[0x16]='EM Microelectronic-Marin SA Switzerland'
|
||||||
manufacturer[0x17]='KSW Microtec GmbH [Germany]'
|
m[0x17]='KSW Microtec GmbH Germany'
|
||||||
manufacturer[0x18]='ZMD AG [Germany]'
|
m[0x18]='ZMD AG Germany'
|
||||||
manufacturer[0x19]='XICOR, Inc. [USA]'
|
m[0x19]='XICOR, Inc. USA'
|
||||||
manufacturer[0x1A]='Sony Corporation [Japan]'
|
m[0x1A]='Sony Corporation Japan'
|
||||||
manufacturer[0x1B]='Malaysia Microelectronic Solutions Sdn. Bhd [Malaysia]'
|
m[0x1B]='Malaysia Microelectronic Solutions Sdn. Bhd Malaysia'
|
||||||
manufacturer[0x1C]='Emosyn [USA]'
|
m[0x1C]='Emosyn USA'
|
||||||
manufacturer[0x1D]='Shanghai Fudan Microelectronics Co. Ltd. P.R. [China]'
|
m[0x1D]='Shanghai Fudan Microelectronics Co. Ltd. P.R. China'
|
||||||
manufacturer[0x1E]='Magellan Technology Pty Limited [Australia]'
|
m[0x1E]='Magellan Technology Pty Limited Australia'
|
||||||
manufacturer[0x1F]='Melexis NV BO [Switzerland]'
|
m[0x1F]='Melexis NV BO Switzerland'
|
||||||
manufacturer[0x20]='Renesas Technology Corp. [Japan]'
|
m[0x20]='Renesas Technology Corp. Japan'
|
||||||
manufacturer[0x21]='TAGSYS [France]'
|
m[0x21]='TAGSYS France'
|
||||||
manufacturer[0x22]='Transcore [USA]'
|
m[0x22]='Transcore USA'
|
||||||
manufacturer[0x23]='Shanghai belling corp., ltd. [China]'
|
m[0x23]='Shanghai belling corp., ltd. China'
|
||||||
manufacturer[0x24]='Masktech Germany Gmbh [Germany]'
|
m[0x24]='Masktech Germany Gmbh Germany'
|
||||||
manufacturer[0x25]='Innovision Research and Technology Plc [UK]'
|
m[0x25]='Innovision Research and Technology Plc UK'
|
||||||
manufacturer[0x26]='Hitachi ULSI Systems Co., Ltd. [Japan]'
|
m[0x26]='Hitachi ULSI Systems Co., Ltd. Japan'
|
||||||
manufacturer[0x27]='Cypak AB [Sweden]'
|
m[0x27]='Cypak AB Sweden'
|
||||||
manufacturer[0x28]='Ricoh [Japan]'
|
m[0x28]='Ricoh Japan'
|
||||||
manufacturer[0x29]='ASK [France]'
|
m[0x29]='ASK France'
|
||||||
manufacturer[0x2A]='Unicore Microsystems, LLC [RussianFederation]'
|
m[0x2A]='Unicore Microsystems, LLC RussianFederation'
|
||||||
manufacturer[0x2B]='Dallas Semiconductor/Maxim [USA]'
|
m[0x2B]='Dallas Semiconductor/Maxim USA'
|
||||||
manufacturer[0x2C]='Impinj, Inc. [USA]'
|
m[0x2C]='Impinj, Inc. USA'
|
||||||
manufacturer[0x2D]='RightPlug Alliance [USA]'
|
m[0x2D]='RightPlug Alliance USA'
|
||||||
manufacturer[0x2E]='Broadcom Corporation [USA]'
|
m[0x2E]='Broadcom Corporation USA'
|
||||||
manufacturer[0x2F]='MStar Semiconductor, Inc Taiwan, [ROC]'
|
m[0x2F]='MStar Semiconductor, Inc Taiwan, ROC'
|
||||||
manufacturer[0x30]='BeeDar Technology Inc. [USA]'
|
m[0x30]='BeeDar Technology Inc. USA'
|
||||||
manufacturer[0x31]='RFIDsec [Denmark]'
|
m[0x31]='RFIDsec Denmark'
|
||||||
manufacturer[0x32]='Schweizer Electronic AG [Germany]'
|
m[0x32]='Schweizer Electronic AG Germany'
|
||||||
manufacturer[0x33]='AMIC Technology Corp [Taiwan]'
|
m[0x33]='AMIC Technology Corp Taiwan'
|
||||||
manufacturer[0x34]='Mikron JSC [Russia]'
|
m[0x34]='Mikron JSC Russia'
|
||||||
manufacturer[0x35]='Fraunhofer Institute for Photonic Microsystems [Germany]'
|
m[0x35]='Fraunhofer Institute for Photonic Microsystems Germany'
|
||||||
manufacturer[0x36]='IDS Microchip AG [Switzerland]'
|
m[0x36]='IDS Microchip AG Switzerland'
|
||||||
manufacturer[0x37]='Kovio [USA]'
|
m[0x37]='Kovio USA'
|
||||||
manufacturer[0x38]='HMT Microelectronic Ltd [Switzerland]'
|
m[0x38]='HMT Microelectronic Ltd Switzerland'
|
||||||
manufacturer[0x39]='Silicon Craft Technology [Thailand]'
|
m[0x39]='Silicon Craft Technology Thailand'
|
||||||
manufacturer[0x3A]='Advanced Film Device Inc. [Japan]'
|
m[0x3A]='Advanced Film Device Inc. Japan'
|
||||||
manufacturer[0x3B]='Nitecrest Ltd [UK]'
|
m[0x3B]='Nitecrest Ltd UK'
|
||||||
manufacturer[0x3C]='Verayo Inc. [USA]'
|
m[0x3C]='Verayo Inc. USA'
|
||||||
manufacturer[0x3D]='HID Global [USA]'
|
m[0x3D]='HID Global USA'
|
||||||
manufacturer[0x3E]='Productivity Engineering Gmbh [Germany]'
|
m[0x3E]='Productivity Engineering Gmbh Germany'
|
||||||
manufacturer[0x3F]='Austriamicrosystems AG (reserved) [Austria]'
|
m[0x3F]='Austriamicrosystems AG (reserved) Austria'
|
||||||
manufacturer[0x40]='Gemalto SA [France]'
|
m[0x40]='Gemalto SA France'
|
||||||
manufacturer[0x41]='Renesas Electronics Corporation [Japan]'
|
m[0x41]='Renesas Electronics Corporation Japan'
|
||||||
manufacturer[0x42]='3Alogics Inc [Korea]'
|
m[0x42]='3Alogics Inc Korea'
|
||||||
manufacturer[0x43]='Top TroniQ Asia Limited Hong [Kong]'
|
m[0x43]='Top TroniQ Asia Limited Hong Kong'
|
||||||
manufacturer[0x44]='Gentag Inc (USA) [USA]'
|
m[0x44]='Gentag Inc USA'
|
||||||
|
m[0x45]='Invengo Information Technology Co.Ltd China'
|
||||||
|
m[0x46]='Guangzhou Sysur Microelectronics, Inc China'
|
||||||
|
m[0x47]='CEITEC S.A. Brazil'
|
||||||
|
m[0x48]='Shanghai Quanray Electronics Co. Ltd. China'
|
||||||
|
m[0x49]='MediaTek Inc Taiwan'
|
||||||
|
m[0x4A]='Angstrem PJSC Russia'
|
||||||
|
m[0x4B]='Celisic Semiconductor (Hong Kong) Limited China'
|
||||||
|
m[0x4C]='LEGIC Identsystems AG Switzerland'
|
||||||
|
m[0x4D]='Balluff GmbH Germany'
|
||||||
|
m[0x4E]='Oberthur Technologies France'
|
||||||
|
m[0x4F]='Silterra Malaysia Sdn. Bhd. Malaysia'
|
||||||
|
m[0x50]='DELTA Danish Electronics, Light & Acoustics Denmark'
|
||||||
|
m[0x51]='Giesecke & Devrient GmbH Germany'
|
||||||
|
m[0x52]='Shenzhen China Vision Microelectronics Co., Ltd. China'
|
||||||
|
m[0x53]='Shanghai Feiju Microelectronics Co. Ltd. China'
|
||||||
|
m[0x54]='Intel Corporation USA'
|
||||||
|
m[0x55]='Microsensys GmbH Germany'
|
||||||
|
m[0x56]='Sonix Technology Co., Ltd. Taiwan'
|
||||||
|
m[0x57]='Qualcomm Technologies Inc USA'
|
||||||
|
m[0x58]='Realtek Semiconductor Corp Taiwan'
|
||||||
|
m[0x59]='Freevision Technologies Co. Ltd China'
|
||||||
|
m[0x5A]='Giantec Semiconductor Inc. China'
|
||||||
|
m[0x5B]='JSC Angstrem-T Russia'
|
||||||
|
m[0x5C]='STARCHIP France'
|
||||||
|
m[0x5D]='SPIRTECH France'
|
||||||
|
m[0x5E]='GANTNER Electronic GmbH Austria'
|
||||||
|
m[0x5F]='Nordic Semiconductor Norway'
|
||||||
|
m[0x60]='Verisiti Inc USA'
|
||||||
|
m[0x61]='Wearlinks Technology Inc. China'
|
||||||
|
m[0x62]='Userstar Information Systems Co., Ltd Taiwan'
|
||||||
|
m[0x63]='Pragmatic Printing Ltd. UK'
|
||||||
|
m[0x64]='Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil'
|
||||||
|
m[0x65]='Tendyron Corporation China'
|
||||||
|
m[0x66]='MUTO Smart Co., Ltd. Korea'
|
||||||
|
m[0x67]='ON Semiconductor USA'
|
||||||
|
m[0x68]='TUBITAK BILGEM Turkey'
|
||||||
|
m[0x69]='Huada Semiconductor Co., Ltd China'
|
||||||
|
m[0x6A]='SEVENEY France'
|
||||||
|
m[0x6B]='ISSM France'
|
||||||
|
m[0x6C]='Wisesec Ltd Israel'
|
||||||
|
m[0x7C]='DB HiTek Co Ltd Korea'
|
||||||
|
m[0x7D]='SATO Vicinity Australia'
|
||||||
|
m[0x7E]='Holtek Taiwan'
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lookupManufacturer = function (value)
|
lookupManufacturer = function (value)
|
||||||
|
@ -76,8 +119,6 @@ return {
|
||||||
value = v
|
value = v
|
||||||
end
|
end
|
||||||
|
|
||||||
return manufacturer[value] or "no tag-info available"
|
return m[value] or "no tag-info available"
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -173,18 +173,19 @@ int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
|
||||||
|
|
||||||
// success array. each byte is status of key
|
// success array. each byte is status of key
|
||||||
uint8_t arr[80];
|
uint8_t arr[80];
|
||||||
uint64_t foo = bytes_to_num(resp.d.asBytes+480, 8);
|
uint64_t foo = 0;
|
||||||
for (uint8_t i = 0; i < 64; ++i) {
|
uint16_t bar = 0;
|
||||||
arr[i] = (foo >> i) & 0x1;
|
foo = bytes_to_num(resp.d.asBytes+480, 8);
|
||||||
}
|
bar = (resp.d.asBytes[489] << 8 | resp.d.asBytes[488]);
|
||||||
foo = bytes_to_num(resp.d.asBytes+488, 2);
|
|
||||||
for (uint8_t i = 0; i < 16; ++i) {
|
|
||||||
arr[i+64] = (foo >> i) & 0x1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 64; i++)
|
||||||
|
arr[i] = (foo >> i) & 0x1;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 16; i++)
|
||||||
|
arr[i+64] = (bar >> i) & 0x1;
|
||||||
|
|
||||||
// initialize storage for found keys
|
// initialize storage for found keys
|
||||||
icesector_t *tmp = NULL;
|
icesector_t *tmp = calloc(sectorsCnt, sizeof(icesector_t));
|
||||||
tmp = calloc(sectorsCnt, sizeof(icesector_t));
|
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
memcpy(tmp, resp.d.asBytes, sectorsCnt * sizeof(icesector_t) );
|
memcpy(tmp, resp.d.asBytes, sectorsCnt * sizeof(icesector_t) );
|
||||||
|
|
|
@ -215,11 +215,11 @@ const char *get_my_executable_directory(void) {
|
||||||
static void set_my_executable_path(void) {
|
static void set_my_executable_path(void) {
|
||||||
int path_length = wai_getExecutablePath(NULL, 0, NULL);
|
int path_length = wai_getExecutablePath(NULL, 0, NULL);
|
||||||
if (path_length != -1) {
|
if (path_length != -1) {
|
||||||
my_executable_path = (char*)malloc(path_length + 1);
|
my_executable_path = (char*)calloc(path_length + 1, sizeof(uint8_t));
|
||||||
int dirname_length = 0;
|
int dirname_length = 0;
|
||||||
if (wai_getExecutablePath(my_executable_path, path_length, &dirname_length) != -1) {
|
if (wai_getExecutablePath(my_executable_path, path_length, &dirname_length) != -1) {
|
||||||
my_executable_path[path_length] = '\0';
|
my_executable_path[path_length] = '\0';
|
||||||
my_executable_directory = (char *)malloc(dirname_length + 2);
|
my_executable_directory = (char *)calloc(dirname_length + 2, sizeof(uint8_t));
|
||||||
strncpy(my_executable_directory, my_executable_path, dirname_length+1);
|
strncpy(my_executable_directory, my_executable_path, dirname_length+1);
|
||||||
my_executable_directory[dirname_length+1] = '\0';
|
my_executable_directory[dirname_length+1] = '\0';
|
||||||
}
|
}
|
||||||
|
@ -321,9 +321,9 @@ int main(int argc, char* argv[]) {
|
||||||
} else {
|
} else {
|
||||||
if (addLuaExec){
|
if (addLuaExec){
|
||||||
// add "script run " to command
|
// add "script run " to command
|
||||||
char *ctmp = NULL;
|
|
||||||
int len = strlen(script_cmd) + 11 + 1;
|
int len = strlen(script_cmd) + 11 + 1;
|
||||||
if ((ctmp = (char*) malloc(len)) != NULL) {
|
char *ctmp = (char*) calloc(len, sizeof(uint8_t));
|
||||||
|
if (ctmp != NULL) {
|
||||||
memset(ctmp, 0, len);
|
memset(ctmp, 0, len);
|
||||||
strcpy(ctmp, "script run ");
|
strcpy(ctmp, "script run ");
|
||||||
strcpy(&ctmp[11], script_cmd);
|
strcpy(&ctmp[11], script_cmd);
|
||||||
|
|
|
@ -377,7 +377,9 @@ ipqx:
|
||||||
|
|
||||||
/* allocate argument array */
|
/* allocate argument array */
|
||||||
args = argc - optind;
|
args = argc - optind;
|
||||||
if(!(apolys = malloc(args * sizeof(poly_t)))){
|
|
||||||
|
apolys = calloc(args * sizeof(poly_t), sizeof(char));
|
||||||
|
if ( !apolys ){
|
||||||
uerror("cannot allocate memory for argument list");
|
uerror("cannot allocate memory for argument list");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ char * mtostr(const model_t *model) {
|
||||||
+ (checkstr && *checkstr ? strlen(checkstr) : 6)
|
+ (checkstr && *checkstr ? strlen(checkstr) : 6)
|
||||||
+ (magicstr && *magicstr ? strlen(magicstr) : 6)
|
+ (magicstr && *magicstr ? strlen(magicstr) : 6)
|
||||||
+ (model->name && *model->name ? 2 + strlen(model->name) : 6);
|
+ (model->name && *model->name ? 2 + strlen(model->name) : 6);
|
||||||
if ((string = malloc(size))) {
|
if ((string = calloc(size, sizeof(uint8_t)))) {
|
||||||
sprintf(strbuf, "\"%s\"", model->name);
|
sprintf(strbuf, "\"%s\"", model->name);
|
||||||
sprintf(string,
|
sprintf(string,
|
||||||
"width=%lu "
|
"width=%lu "
|
||||||
|
|
|
@ -349,7 +349,7 @@ pxsubs(const poly_t poly, int flags, int bperhx, unsigned long start, unsigned l
|
||||||
size *= cperhx;
|
size *= cperhx;
|
||||||
if(!size || ~flags & P_SPACE) ++size; /* for trailing null */
|
if(!size || ~flags & P_SPACE) ++size; /* for trailing null */
|
||||||
|
|
||||||
if(!(sptr = string = (char *) malloc(size)))
|
if(!(sptr = string = (char *) calloc(size, sizeof(char))))
|
||||||
uerror("cannot allocate memory for string");
|
uerror("cannot allocate memory for string");
|
||||||
|
|
||||||
size = end - start;
|
size = end - start;
|
||||||
|
|
|
@ -811,7 +811,9 @@ int mbynam(model_t *dest, const char *key) {
|
||||||
|
|
||||||
if (!aliases->name)
|
if (!aliases->name)
|
||||||
return(-1);
|
return(-1);
|
||||||
if (!(ukey = malloc((size_t) 1 + strlen(key) + 1))) {
|
|
||||||
|
ukey = calloc((size_t) 1 + strlen(key) + 1, sizeof(char));
|
||||||
|
if (!ukey) {
|
||||||
uerror("[!] cannot allocate memory for comparison string");
|
uerror("[!] cannot allocate memory for comparison string");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
@ -861,7 +863,9 @@ char * mnames(void) {
|
||||||
++aptr;
|
++aptr;
|
||||||
}
|
}
|
||||||
if (!size) return(NULL);
|
if (!size) return(NULL);
|
||||||
if ((string = malloc(size))) {
|
|
||||||
|
string = calloc(size, sizeof(char));
|
||||||
|
if (string) {
|
||||||
aptr = aliases;
|
aptr = aliases;
|
||||||
sptr = string;
|
sptr = string;
|
||||||
while (aptr->name) {
|
while (aptr->name) {
|
||||||
|
|
|
@ -173,8 +173,9 @@ modpol(const poly_t init, int rflags, int args, const poly_t *argpolys) {
|
||||||
unsigned long alen, blen;
|
unsigned long alen, blen;
|
||||||
|
|
||||||
if(args < 2) return(NULL);
|
if(args < 2) return(NULL);
|
||||||
|
|
||||||
if(!(result = malloc(((((args - 1) * args) >> 1) + 1) * sizeof(poly_t))))
|
result = calloc(((((args - 1) * args) >> 1) + 1) * sizeof(poly_t), sizeof(char));
|
||||||
|
if(!result)
|
||||||
uerror("cannot allocate memory for codeword table");
|
uerror("cannot allocate memory for codeword table");
|
||||||
|
|
||||||
rptr = result;
|
rptr = result;
|
||||||
|
@ -240,7 +241,8 @@ engini(int *resc, model_t **result, const poly_t divisor, int flags, int args, c
|
||||||
dlen = plen(divisor);
|
dlen = plen(divisor);
|
||||||
|
|
||||||
/* Allocate the CRC matrix */
|
/* Allocate the CRC matrix */
|
||||||
if(!(mat = (poly_t *) malloc((dlen << 1) * sizeof(poly_t))))
|
mat = (poly_t *) calloc((dlen << 1) * sizeof(poly_t), sizeof(char));
|
||||||
|
if(!mat)
|
||||||
uerror("cannot allocate memory for CRC matrix");
|
uerror("cannot allocate memory for CRC matrix");
|
||||||
|
|
||||||
/* Find arguments of the two shortest lengths */
|
/* Find arguments of the two shortest lengths */
|
||||||
|
|
|
@ -51,7 +51,8 @@ int scandir (const char *dir,
|
||||||
nl = ntmp;
|
nl = ntmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(etmp = (struct dirent *) malloc (sizeof *ent))) {
|
etmp = (struct dirent *) calloc (sizeof *ent, sizeof(char));
|
||||||
|
if (!etmp) {
|
||||||
err_no = 1;
|
err_no = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,15 @@ int set_pm3_libraries(lua_State *L) {
|
||||||
//-- remove the global environment table from the stack
|
//-- remove the global environment table from the stack
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
|
||||||
|
//--add to the LUA_PATH (package.path in lua)
|
||||||
|
// so we can load scripts from the ./scripts/ - directory
|
||||||
|
char scripts_path[strlen(get_my_executable_directory()) + strlen(LUA_SCRIPTS_DIRECTORY) + strlen(LUA_LIBRARIES_WILDCARD) + 1];
|
||||||
|
strcpy(scripts_path, get_my_executable_directory());
|
||||||
|
strcat(scripts_path, LUA_SCRIPTS_DIRECTORY);
|
||||||
|
strcat(scripts_path, LUA_LIBRARIES_WILDCARD);
|
||||||
|
setLuaPath(L, scripts_path);
|
||||||
|
|
||||||
//-- Last but not least, add to the LUA_PATH (package.path in lua)
|
//-- Last but not least, add to the LUA_PATH (package.path in lua)
|
||||||
// so we can load libraries from the ./lualib/ - directory
|
// so we can load libraries from the ./lualib/ - directory
|
||||||
char libraries_path[strlen(get_my_executable_directory()) + strlen(LUA_LIBRARIES_DIRECTORY) + strlen(LUA_LIBRARIES_WILDCARD) + 1];
|
char libraries_path[strlen(get_my_executable_directory()) + strlen(LUA_LIBRARIES_DIRECTORY) + strlen(LUA_LIBRARIES_WILDCARD) + 1];
|
||||||
|
@ -765,6 +774,5 @@ int set_pm3_libraries(lua_State *L) {
|
||||||
strcat(libraries_path, LUA_LIBRARIES_DIRECTORY);
|
strcat(libraries_path, LUA_LIBRARIES_DIRECTORY);
|
||||||
strcat(libraries_path, LUA_LIBRARIES_WILDCARD);
|
strcat(libraries_path, LUA_LIBRARIES_WILDCARD);
|
||||||
setLuaPath(L, libraries_path);
|
setLuaPath(L, libraries_path);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ local utils = require('utils')
|
||||||
|
|
||||||
copyright = 'Copyright (c) 2018 IceSQL AB. All rights reserved.'
|
copyright = 'Copyright (c) 2018 IceSQL AB. All rights reserved.'
|
||||||
author = 'Christian Herrmann'
|
author = 'Christian Herrmann'
|
||||||
version = 'v1.0.3'
|
version = 'v1.0.4'
|
||||||
desc = [[
|
desc = [[
|
||||||
This script tries to set UID on a IS15693 SLIX magic card
|
This script tries to set UID on a IS15693 SLIX magic card
|
||||||
Remember the UID ->MUST<- start with 0xE0
|
Remember the UID ->MUST<- start with 0xE0
|
||||||
|
@ -15,6 +15,8 @@ example = [[
|
||||||
-- ISO15693 slix magic tag
|
-- ISO15693 slix magic tag
|
||||||
|
|
||||||
script run iso15_magic -u E004013344556677
|
script run iso15_magic -u E004013344556677
|
||||||
|
|
||||||
|
script run iso15_magic -u E004013344556677 -a
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
script run iso15_magic -h -u <uid>
|
script run iso15_magic -h -u <uid>
|
||||||
|
@ -22,6 +24,7 @@ script run iso15_magic -h -u <uid>
|
||||||
Arguments:
|
Arguments:
|
||||||
-h : this help
|
-h : this help
|
||||||
-u <UID> : UID (16 hexsymbols)
|
-u <UID> : UID (16 hexsymbols)
|
||||||
|
-a : use offical pm3 repo ISO15 commands instead of iceman fork.
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local DEBUG = true
|
local DEBUG = true
|
||||||
|
@ -82,11 +85,13 @@ function main(args)
|
||||||
print()
|
print()
|
||||||
|
|
||||||
local uid = 'E004013344556677'
|
local uid = 'E004013344556677'
|
||||||
|
local use_iceman = true
|
||||||
|
|
||||||
-- Read the parameters
|
-- Read the parameters
|
||||||
for o, a in getopt.getopt(args, 'hu:') do
|
for o, a in getopt.getopt(args, 'hu:a') do
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
if o == "u" then uid = a end
|
if o == "u" then uid = a end
|
||||||
|
if o == "a" then use_iceman = false end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- uid string checks
|
-- uid string checks
|
||||||
|
@ -103,8 +108,11 @@ function main(args)
|
||||||
|
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
magicUID_iceman(block0, block1)
|
if use_iceman then
|
||||||
--magicUID_offical(block0, block1)
|
magicUID_iceman(block0, block1)
|
||||||
|
else
|
||||||
|
magicUID_offical(block0, block1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|
|
@ -513,8 +513,8 @@ function readFromPM3()
|
||||||
return tag
|
return tag
|
||||||
end
|
end
|
||||||
|
|
||||||
function padString(str)
|
local function padString(str)
|
||||||
if (str:len() == 1) then
|
if (#str == 1) then
|
||||||
return '0'..str
|
return '0'..str
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -524,73 +524,84 @@ end
|
||||||
---
|
---
|
||||||
-- write virtual Tag to real Tag
|
-- write virtual Tag to real Tag
|
||||||
function writeToTag(tag)
|
function writeToTag(tag)
|
||||||
local bytes
|
local bytes
|
||||||
local filename='MylegicClone.hex'
|
local filename = 'MylegicClone.hex'
|
||||||
local taglen=22
|
local taglen = 22
|
||||||
if(utils.confirm(acred.."\nplace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then
|
if(utils.confirm(acred.."\nplace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- get used bytes / tag-len
|
|
||||||
if(istable(tag.SEG)) then
|
-- get used bytes / tag-len
|
||||||
if (istable(tag.Bck)) then
|
if (istable(tag.SEG)) then
|
||||||
for i=0, #tag.SEG do
|
if (istable(tag.Bck)) then
|
||||||
taglen=taglen+tag.SEG[i].len+5
|
for i=0, #tag.SEG do
|
||||||
end
|
taglen = taglen + tag.SEG[i] . len + 5
|
||||||
end
|
end
|
||||||
local uid_old=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
|
end
|
||||||
-- read new tag into memory so we can xor the new data with the new MCC
|
local uid_old = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
|
||||||
outTAG=readFromPM3()
|
|
||||||
outbytes=tagToBytes(outTAG)
|
-- read new tag into memory so we can xor the new data with the new MCC
|
||||||
-- copy 'inputbuffer' to 'outputbuffer'
|
outTAG = readFromPM3()
|
||||||
tag.MCD = outbytes[1]
|
outbytes = tagToBytes(outTAG)
|
||||||
tag.MSN0 = outbytes[2]
|
-- copy 'inputbuffer' to 'outputbuffer'
|
||||||
tag.MSN1 = outbytes[3]
|
tag.MCD = outbytes[1]
|
||||||
tag.MSN2 = outbytes[4]
|
tag.MSN0 = outbytes[2]
|
||||||
tag.MCC = outbytes[5]
|
tag.MSN1 = outbytes[3]
|
||||||
-- recheck all segments-crc/kghcrc (only on a credential)
|
tag.MSN2 = outbytes[4]
|
||||||
if(istable(tag.Bck)) then
|
tag.MCC = outbytes[5]
|
||||||
checkAllSegCrc(tag)
|
-- recheck all segments-crc/kghcrc (only on a credential)
|
||||||
checkAllKghCrc(tag)
|
if (istable(tag.Bck)) then
|
||||||
local uid_new=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
|
checkAllSegCrc(tag)
|
||||||
for i=0, #tag.SEG do
|
checkAllKghCrc(tag)
|
||||||
if (check43rdPartyCash1(uid_old, tag.SEG[i].data)) then
|
local uid_new = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
|
||||||
io.write(accyan.."\nfixing known checksums"..acoff.." ... ")
|
for i=0, #tag.SEG do
|
||||||
if (fix3rdPartyCash1(uid_new, tag.SEG[i].data)) then
|
if (check43rdPartyCash1(uid_old, tag.SEG[i].data)) then
|
||||||
io.write(acgreen.." done\n"..acoff)
|
io.write(accyan.."\nfixing known checksums"..acoff.." ... ")
|
||||||
else oops("\nsomething went wrong at the repair of the 3rd-party-cash-segment") end
|
if (fix3rdPartyCash1(uid_new, tag.SEG[i].data)) then
|
||||||
end
|
io.write(acgreen.." done\n"..acoff)
|
||||||
end
|
else
|
||||||
end
|
oops("\nsomething went wrong at the repair of the 3rd-party-cash-segment")
|
||||||
bytes=tagToBytes(tag)
|
end
|
||||||
-- master-token-crc
|
end
|
||||||
if (tag.Type ~= "SAM") then bytes[22] = calcMtCrc(bytes) end
|
end
|
||||||
if (bytes) then
|
end
|
||||||
print("write temp-file '"..filename.."'")
|
bytes = tagToBytes(tag)
|
||||||
print(accyan)
|
-- master-token-crc
|
||||||
writeFile(bytes, filename..".bin")
|
if (tag.Type ~= "SAM") then
|
||||||
print(acoff)
|
bytes[22] = calcMtCrc(bytes)
|
||||||
end
|
end
|
||||||
end
|
if (bytes) then
|
||||||
|
print("write temp-file '"..filename.."'")
|
||||||
|
print(accyan)
|
||||||
|
writeFile(bytes, filename..".bin")
|
||||||
|
print(acoff)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- write data to file
|
-- write data to file
|
||||||
if (taglen > 0) then
|
if (taglen > 0) then
|
||||||
WriteBytes = utils.input(acyellow.."enter number of bytes to write?"..acoff, taglen)
|
WriteBytes = utils.input(acyellow.."enter number of bytes to write?"..acoff, taglen)
|
||||||
-- load file into pm3-buffer
|
-- load file into pm3-buffer
|
||||||
if (type(filename) ~= "string") then filename=input(acyellow.."filename to load to pm3-buffer?"..acoff,"legic.temp") end
|
if (type(filename) ~= "string") then
|
||||||
|
filename = input(acyellow.."filename to load to pm3-buffer?"..acoff, "legic.temp")
|
||||||
|
end
|
||||||
|
|
||||||
cmd = 'hf legic eload 2 '..filename
|
cmd = 'hf legic eload 2 '..filename
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
-- write pm3-buffer to Tag
|
-- write pm3-buffer to Tag
|
||||||
for i=0, WriteBytes do
|
for i=0, WriteBytes do
|
||||||
if (i > 6) then
|
if (i > 6) then
|
||||||
cmd = 'hf legic write o '..string.format("%x", i)..' d '..padString(bytes[i])
|
cmd = ("hf legic write o %x d %s "):format(i, padString(bytes[i]))
|
||||||
print(acgreen..cmd..acoff)
|
print(acgreen..cmd..acoff)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
|
core.clearCommandBuffer()
|
||||||
elseif (i == 6) then
|
elseif (i == 6) then
|
||||||
-- write DCF in reverse order (requires 'mosci-patch')
|
-- write DCF in reverse order (requires 'mosci-patch')
|
||||||
cmd = 'hf legic write o 05 d '..padString(bytes[i-1])..padString(bytes[i])
|
cmd = ('hf legic write o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
|
||||||
print(acgreen..cmd..acoff)
|
print(acgreen..cmd..acoff)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
elseif (i == 5) then
|
core.clearCommandBuffer()
|
||||||
|
elseif (i == 5) then
|
||||||
print(acgreen.."skip byte 0x05 - will be written next step"..acoff)
|
print(acgreen.."skip byte 0x05 - will be written next step"..acoff)
|
||||||
else
|
else
|
||||||
print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff)
|
print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff)
|
||||||
|
@ -603,26 +614,28 @@ end
|
||||||
--- File I/O ---
|
--- File I/O ---
|
||||||
---
|
---
|
||||||
-- read file into virtual-tag
|
-- read file into virtual-tag
|
||||||
function readFile(filename)
|
local function readFile(filename)
|
||||||
print(accyan)
|
print(accyan)
|
||||||
local bytes = {}
|
local bytes = {}
|
||||||
local tag = {}
|
local tag = {}
|
||||||
if file_check(filename) == false then return oops("input file: "..filename.." not found") end
|
if file_check(filename) == false then
|
||||||
|
return oops("input file: "..filename.." not found")
|
||||||
|
end
|
||||||
|
|
||||||
bytes = getInputBytes(filename)
|
bytes = getInputBytes(filename)
|
||||||
|
|
||||||
if bytes == false then return oops('couldnt get input bytes') end
|
if bytes == false then return oops('couldnt get input bytes') end
|
||||||
|
|
||||||
-- make plain bytes
|
-- make plain bytes
|
||||||
bytes = xorBytes(bytes,bytes[5])
|
bytes = xorBytes(bytes,bytes[5])
|
||||||
print("create virtual tag from ".. #bytes .. " bytes")
|
print("create virtual tag from ".. #bytes .. " bytes")
|
||||||
-- create Tag for plain bytes
|
-- create Tag for plain bytes
|
||||||
tag=createTagTable()
|
tag = createTagTable()
|
||||||
-- load plain bytes to tag-table
|
-- load plain bytes to tag-table
|
||||||
print(acoff)
|
print(acoff)
|
||||||
tag=bytesToTag(bytes, tag)
|
tag = bytesToTag(bytes, tag)
|
||||||
|
|
||||||
return tag
|
return tag
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -631,14 +644,16 @@ function writeFile(bytes, filename)
|
||||||
if (filename ~= 'MylegicClone.hex') then
|
if (filename ~= 'MylegicClone.hex') then
|
||||||
if (file_check(filename)) then
|
if (file_check(filename)) then
|
||||||
local answer = confirm("\nthe output-file "..filename.." already exists!\nthis will delete the previous content!\ncontinue?")
|
local answer = confirm("\nthe output-file "..filename.." already exists!\nthis will delete the previous content!\ncontinue?")
|
||||||
if (answer==false) then return print("user abort") end
|
if not answer then return print("user abort") end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local line
|
local line
|
||||||
local bcnt=0
|
local bcnt = 0
|
||||||
local fho,err = io.open(filename, "w")
|
local fho, err = io.open(filename, "w")
|
||||||
if err then oops("OOps ... failed to open output-file ".. filename) end
|
if err then
|
||||||
bytes=xorBytes(bytes, bytes[5])
|
return oops("OOps ... failed to open output-file ".. filename)
|
||||||
|
end
|
||||||
|
bytes = xorBytes(bytes, bytes[5])
|
||||||
for i = 1, #bytes do
|
for i = 1, #bytes do
|
||||||
if (bcnt == 0) then
|
if (bcnt == 0) then
|
||||||
line = bytes[i]
|
line = bytes[i]
|
||||||
|
@ -662,96 +677,96 @@ end
|
||||||
--- Map related ---
|
--- Map related ---
|
||||||
---
|
---
|
||||||
-- make tagMap
|
-- make tagMap
|
||||||
function makeTagMap()
|
local function makeTagMap()
|
||||||
local tagMap={}
|
local tagMap = {}
|
||||||
if (#tagMap == 0) then
|
if (#tagMap == 0) then
|
||||||
tagMap['name'] = input(accyan.."enter Name for this Map: "..acoff , "newTagMap")
|
tagMap['name'] = input(accyan.."enter Name for this Map: "..acoff , "newTagMap")
|
||||||
tagMap['mappings']={}
|
tagMap['mappings'] = {}
|
||||||
tagMap['crc8']={}
|
tagMap['crc8'] = {}
|
||||||
-- insert fixed Tag-CRC
|
-- insert fixed Tag-CRC
|
||||||
table.insert(tagMap.crc8, {name='TAG-CRC', pos=5, seq={1, 4}})
|
table.insert(tagMap.crc8, {name = 'TAG-CRC', pos = 5, seq = {1, 4}})
|
||||||
tagMap['crc16']={}
|
tagMap['crc16'] = {}
|
||||||
end
|
end
|
||||||
print(accyan.."new tagMap created"..acoff)
|
print(accyan.."new tagMap created"..acoff)
|
||||||
return tagMap
|
return tagMap
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- save mapping to file
|
-- save mapping to file
|
||||||
function saveTagMap(map, filename)
|
local function saveTagMap(map, filename)
|
||||||
if (string.len(filename)>0) then
|
if (string.len(filename)>0) then
|
||||||
if (file_check(filename)) then
|
if (file_check(filename)) then
|
||||||
local answer = confirm("\nthe output-file "..filename.." alredy exists!\nthis will delete the previous content!\ncontinue?")
|
local answer = confirm("\nthe output-file "..filename.." alredy exists!\nthis will delete the previous content!\ncontinue?")
|
||||||
if (answer==false) then return print("user abort") end
|
if not answer then return print("user abort") end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local line
|
local line
|
||||||
local fho,err = io.open(filename, "w")
|
local fho,err = io.open(filename, "w")
|
||||||
if err then oops("OOps ... faild to open output-file ".. filename) end
|
if err then oops("OOps ... faild to open output-file ".. filename) end
|
||||||
|
|
||||||
-- write line to new file
|
-- write line to new file
|
||||||
for k, v in pairs(map) do
|
for k, v in pairs(map) do
|
||||||
if (istable(v)) then
|
if (istable(v)) then
|
||||||
for k2, v2 in pairs(v) do
|
for k2, v2 in pairs(v) do
|
||||||
if (k=='mappings') then
|
if (k == 'mappings') then
|
||||||
fho:write(k..","..k2..","..v2['name']..","..v2['start']..","..v2['end']..","..((v2['highlight']) and "1" or "0").."\n")
|
fho:write(k..","..k2..","..v2['name']..","..v2['start']..","..v2['end']..","..((v2['highlight']) and "1" or "0").."\n")
|
||||||
elseif (k=="crc8") then
|
elseif (k == "crc8") then
|
||||||
local tmp=""
|
local tmp = ""
|
||||||
tmp=k..","..k2..","..v2['name']..","..v2['pos']..","
|
tmp = k..","..k2..","..v2['name']..","..v2['pos']..","
|
||||||
tmp=tmp..tbl2seqstr(v2['seq'])
|
tmp=tmp..tbl2seqstr(v2['seq'])
|
||||||
fho:write(tmp.."\n")
|
fho:write(tmp.."\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
fho:write(k..","..v.."\n")
|
fho:write(k..","..v.."\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
fho:close()
|
fho:close()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- toggle higligh
|
-- toggle higligh
|
||||||
function toggleHighlight(tbl)
|
local function toggleHighlight(tbl)
|
||||||
if (tbl['highlight']) then
|
if (tbl['highlight']) then
|
||||||
tbl['highlight'] = false
|
tbl['highlight'] = false
|
||||||
else
|
else
|
||||||
tbl['highlight'] = true
|
tbl['highlight'] = true
|
||||||
end
|
end
|
||||||
return tbl
|
return tbl
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- return table od seqence-string
|
-- return table od seqence-string
|
||||||
function seqstr2tbl(seqstr)
|
local function seqstr2tbl(seqstr)
|
||||||
local s=split(seqstr)
|
local s = split(seqstr)
|
||||||
local res={}
|
local res = {}
|
||||||
if (#s>=1) then
|
if (#s >= 1) then
|
||||||
for sk, sv in pairs(s) do
|
for sk, sv in pairs(s) do
|
||||||
s2=split(sv, '-')
|
s2 = split(sv, '-')
|
||||||
if(#s2==2) then
|
if(#s2 == 2) then
|
||||||
table.insert(res, s2[1])
|
table.insert(res, s2[1])
|
||||||
table.insert(res, s2[2])
|
table.insert(res, s2[2])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- return sequence-string from table
|
-- return sequence-string from table
|
||||||
function tbl2seqstr(seqtbl)
|
local function tbl2seqstr(seqtbl)
|
||||||
local res=""
|
local res = ""
|
||||||
if (istable(seqtbl)) then
|
if (istable(seqtbl)) then
|
||||||
for sk, sv in pairs(seqtbl) do
|
for sk, sv in pairs(seqtbl) do
|
||||||
res=res..sv..((sk%2==0) and "," or "-")
|
res = res..sv..((sk%2==0) and "," or "-")
|
||||||
end
|
end
|
||||||
if (string.sub(res, string.len(res))==",") then
|
if (string.sub(res, string.len(res))== ",") then
|
||||||
res=string.sub(res, 1, string.len(res)-1)
|
res = string.sub(res, 1, string.len(res)-1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -12,8 +12,10 @@ This is a script which automates cracking and dumping mifare classic cards. It s
|
||||||
place by the device.
|
place by the device.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-d debug logging on
|
-h this help
|
||||||
-h this help
|
-d debug logging on
|
||||||
|
-k known key for Sector 0 , keytype A
|
||||||
|
|
||||||
|
|
||||||
Output files from this operation:
|
Output files from this operation:
|
||||||
<uid>.eml - emulator file
|
<uid>.eml - emulator file
|
||||||
|
@ -73,12 +75,12 @@ local function nested(key,sak)
|
||||||
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
|
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
|
||||||
typ = 4
|
typ = 4
|
||||||
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
|
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
|
||||||
typ= 1
|
typ = 1
|
||||||
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
|
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
|
||||||
typ = 0
|
typ = 0
|
||||||
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
|
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
|
||||||
typ = 2
|
typ = 2
|
||||||
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
|
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
|
||||||
typ = 1
|
typ = 1
|
||||||
else
|
else
|
||||||
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
||||||
|
@ -87,22 +89,40 @@ local function nested(key,sak)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dump(uid)
|
local function dump(uid, numsectors)
|
||||||
dbg('dumping tag memory')
|
dbg('dumping tag memory')
|
||||||
|
|
||||||
|
local typ = 1
|
||||||
|
if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k
|
||||||
|
typ = 4
|
||||||
|
elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K
|
||||||
|
typ = 1
|
||||||
|
elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k
|
||||||
|
typ = 0
|
||||||
|
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
|
||||||
|
typ = 2
|
||||||
|
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
|
||||||
|
typ = 1
|
||||||
|
end
|
||||||
|
|
||||||
if utils.confirm('Do you wish to create a memory dump of tag?') then
|
if utils.confirm('Do you wish to create a memory dump of tag?') then
|
||||||
|
|
||||||
core.console("hf mf dump")
|
local dumpfile = 'hf-mf-'..uid..'-data.bin'
|
||||||
|
|
||||||
|
local dmp = ('hf mf dump %s f %s'):format(typ, dumpfile)
|
||||||
|
core.console(dmp)
|
||||||
|
|
||||||
-- Save the global args, those are *our* arguments
|
-- Save the global args, those are *our* arguments
|
||||||
local myargs = args
|
local myargs = args
|
||||||
-- Set the arguments for htmldump script
|
-- Set the arguments for htmldump script
|
||||||
args =("-o %s.html"):format(uid)
|
args =('-i %s -o %s.html'):format(dumpfile, uid)
|
||||||
-- call it
|
-- call it
|
||||||
require('../scripts/htmldump')
|
require('htmldump')
|
||||||
|
|
||||||
args =""
|
|
||||||
-- dump to emulator
|
-- dump to emulator
|
||||||
require('../scripts/dumptoemul')
|
args =('-i %s -o %s.eml'):format(dumpfile, uid)
|
||||||
|
require('dumptoemul')
|
||||||
|
|
||||||
-- Set back args. Not that it's used, just for the karma...
|
-- Set back args. Not that it's used, just for the karma...
|
||||||
args = myargs
|
args = myargs
|
||||||
end
|
end
|
||||||
|
@ -177,9 +197,9 @@ local function main(args)
|
||||||
print("Found valid key: "..key);
|
print("Found valid key: "..key);
|
||||||
end
|
end
|
||||||
-- Use nested attack
|
-- Use nested attack
|
||||||
nested(key,sak)
|
nested(key, sak)
|
||||||
-- Dump info
|
-- Dump info
|
||||||
dump(uid)
|
dump(uid, sak)
|
||||||
|
|
||||||
if #key == 12 then exit = true end
|
if #key == 12 then exit = true end
|
||||||
else
|
else
|
||||||
|
|
|
@ -24,13 +24,13 @@ local example = "script run xxx"
|
||||||
local author = "Martin Holst Swende & Asper"
|
local author = "Martin Holst Swende & Asper"
|
||||||
---
|
---
|
||||||
-- PrintAndLog
|
-- PrintAndLog
|
||||||
function prlog(...)
|
local function prlog(...)
|
||||||
-- TODO; replace this with a call to the proper PrintAndLog
|
-- TODO; replace this with a call to the proper PrintAndLog
|
||||||
print(...)
|
print(...)
|
||||||
end
|
end
|
||||||
---
|
---
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
function oops(err)
|
local function oops(err)
|
||||||
prlog("ERROR: ",err)
|
prlog("ERROR: ",err)
|
||||||
return nil,err
|
return nil,err
|
||||||
end
|
end
|
||||||
|
@ -70,13 +70,13 @@ local utils = {
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
local function help()
|
||||||
prlog(desc)
|
prlog(desc)
|
||||||
prlog("Example usage")
|
prlog("Example usage")
|
||||||
prlog(example)
|
prlog(example)
|
||||||
end
|
end
|
||||||
|
|
||||||
function debug(...)
|
local function debug(...)
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
prlog("debug:", ...)
|
prlog("debug:", ...)
|
||||||
end
|
end
|
||||||
|
@ -158,7 +158,7 @@ end
|
||||||
|
|
||||||
--- This function is a lua-implementation of
|
--- This function is a lua-implementation of
|
||||||
-- cmdhf14a.c:waitCmd(uint8_t iSelect)
|
-- cmdhf14a.c:waitCmd(uint8_t iSelect)
|
||||||
function waitCmd(iSelect)
|
local function waitCmd(iSelect)
|
||||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
|
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
|
||||||
if response then
|
if response then
|
||||||
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response)
|
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response)
|
||||||
|
|
|
@ -21,6 +21,9 @@ Arguments:
|
||||||
-o <offset> : memory offset, default is 0
|
-o <offset> : memory offset, default is 0
|
||||||
-l <length> : length in bytes, default is 256
|
-l <length> : length in bytes, default is 256
|
||||||
-k <keylen> : key length in bytes <4|6|8> , default is 4
|
-k <keylen> : key length in bytes <4|6|8> , default is 4
|
||||||
|
-m : print Mifare dictionary keys
|
||||||
|
-t : print t55xx dictionary passwords
|
||||||
|
-i : print iClass dictionary keys
|
||||||
]]
|
]]
|
||||||
example =
|
example =
|
||||||
[[
|
[[
|
||||||
|
@ -67,7 +70,7 @@ local function main(args)
|
||||||
local keylength = 4
|
local keylength = 4
|
||||||
local usedkey = false
|
local usedkey = false
|
||||||
|
|
||||||
for o, a in getopt.getopt(args, 'ho:l:k:') do
|
for o, a in getopt.getopt(args, 'ho:l:k:mti') do
|
||||||
|
|
||||||
-- help
|
-- help
|
||||||
if o == "h" then return help() end
|
if o == "h" then return help() end
|
||||||
|
@ -80,6 +83,10 @@ local function main(args)
|
||||||
|
|
||||||
-- keylength
|
-- keylength
|
||||||
if o == "k" then keylength = tonumber(a); usedkey = true end
|
if o == "k" then keylength = tonumber(a); usedkey = true end
|
||||||
|
|
||||||
|
if o == "m" then keylength =6; usedkey = true; offset = 0x3F000-0x4000; end
|
||||||
|
if o == "t" then keylength =4; usedkey = true; offset = 0x3F000-0x3000; end
|
||||||
|
if o == "i" then keylength =8; usedkey = true; offset = 0x3F000-0x5000; end
|
||||||
end
|
end
|
||||||
|
|
||||||
if length < 0 or length > 256 then
|
if length < 0 or length > 256 then
|
||||||
|
|
|
@ -72,6 +72,7 @@ local function sendCmds( cmds )
|
||||||
if cmds[i] then
|
if cmds[i] then
|
||||||
print ( cmds[i] )
|
print ( cmds[i] )
|
||||||
core.console( cmds[i] )
|
core.console( cmds[i] )
|
||||||
|
core.clearCommandBuffer()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -37,13 +37,12 @@ Arguments:
|
||||||
0020 - Swapforce
|
0020 - Swapforce
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
|
||||||
-- This is only meant to be used when errors occur
|
-- This is only meant to be used when errors occur
|
||||||
function oops(err)
|
local function oops(err)
|
||||||
print("ERROR: ",err)
|
print("ERROR: ",err)
|
||||||
end
|
end
|
||||||
-- Usage help
|
-- Usage help
|
||||||
function help()
|
local function help()
|
||||||
print(desc)
|
print(desc)
|
||||||
print("Example usage")
|
print("Example usage")
|
||||||
print(example)
|
print(example)
|
||||||
|
@ -64,7 +63,7 @@ local function waitCmd()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readblock( blocknum, keyA )
|
local function readblock( blocknum, keyA )
|
||||||
-- Read block 0
|
-- Read block N
|
||||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA}
|
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA}
|
||||||
err = core.SendCommand(cmd:getBytes())
|
err = core.SendCommand(cmd:getBytes())
|
||||||
if err then return nil, err end
|
if err then return nil, err end
|
||||||
|
@ -72,8 +71,9 @@ local function readblock( blocknum, keyA )
|
||||||
if err then return nil, err end
|
if err then return nil, err end
|
||||||
return block0
|
return block0
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readmagicblock( blocknum )
|
local function readmagicblock( blocknum )
|
||||||
-- Read block 0
|
-- Read block N
|
||||||
local CSETBLOCK_SINGLE_OPERATION = 0x1F
|
local CSETBLOCK_SINGLE_OPERATION = 0x1F
|
||||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum}
|
cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum}
|
||||||
err = core.SendCommand(cmd:getBytes())
|
err = core.SendCommand(cmd:getBytes())
|
||||||
|
@ -89,11 +89,13 @@ local function main(args)
|
||||||
print( string.rep('--',20) )
|
print( string.rep('--',20) )
|
||||||
|
|
||||||
local numBlocks = 64
|
local numBlocks = 64
|
||||||
local cset = 'hf mf csetbl '
|
local cset = 'hf mf csetbl '
|
||||||
local csetuid = 'hf mf csetuid '
|
local csetuid = 'hf mf csetuid '
|
||||||
local cget = 'hf mf cgetbl '
|
local cget = 'hf mf cgetbl '
|
||||||
local empty = '00000000000000000000000000000000'
|
local empty = '00000000000000000000000000000000'
|
||||||
local AccAndKeyB = '7F078869000000000000'
|
local AccAndKeyB = '7F0F0869000000000000'
|
||||||
|
local atqa = '0F01'
|
||||||
|
local sak = '81'
|
||||||
-- Defaults to Gusto
|
-- Defaults to Gusto
|
||||||
local toytype = 'C201'
|
local toytype = 'C201'
|
||||||
local subtype = '0030'
|
local subtype = '0030'
|
||||||
|
@ -107,42 +109,43 @@ local function main(args)
|
||||||
if o == "l" then return toys.List() end
|
if o == "l" then return toys.List() end
|
||||||
end
|
end
|
||||||
|
|
||||||
if #toytype ~= 4 then return oops('Wrong size - toytype. (4hex symbols)') end
|
if #toytype ~= 4 then return oops('[!] Wrong size - toytype. (4hex symbols)') end
|
||||||
if #subtype ~= 4 then return oops('Wrong size - subtype. (4hex symbols)') end
|
if #subtype ~= 4 then return oops('[!] Wrong size - subtype. (4hex symbols)') end
|
||||||
|
|
||||||
-- look up type, find & validate types
|
-- look up type, find & validate types
|
||||||
local item = toys.Find( toytype, subtype)
|
local item = toys.Find( toytype, subtype)
|
||||||
if item then
|
if item then
|
||||||
print( (' Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) )
|
print( ('[+] Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) )
|
||||||
else
|
else
|
||||||
print('Didn\'t find item type. If you are sure about it, report it in')
|
print('[-] Didn\'t find item type. If you are sure about it, post on forum')
|
||||||
end
|
end
|
||||||
--15,16
|
--15,16
|
||||||
--13-14
|
--13-14
|
||||||
|
|
||||||
|
|
||||||
-- find tag
|
-- find tag
|
||||||
result, err = lib14a.read(false, true)
|
result, err = lib14a.read(false, true)
|
||||||
if not result then return oops(err) end
|
if not result then return oops(err) end
|
||||||
|
|
||||||
-- load keys
|
-- load keys
|
||||||
local akeys = pre.GetAll(result.uid)
|
local akeys = pre.GetAll(result.uid)
|
||||||
local keyA = akeys:sub(1, 12 )
|
local keyA = akeys:sub(1, 12 )
|
||||||
|
|
||||||
local b0 = readblock(0,keyA)
|
local b0 = readblock(0, keyA)
|
||||||
if not b0 then
|
if not b0 then
|
||||||
print('failed reading block with factorydefault key. Trying chinese magic read.')
|
print('[-] failed reading block with factorydefault key. Trying chinese magic read.')
|
||||||
b0, err = readmagicblock(0)
|
b0, err = readmagicblock(0)
|
||||||
if not b0 then
|
if not b0 then
|
||||||
oops(err)
|
oops('[!] '..err)
|
||||||
return oops('failed reading block with chinese magic command. quitting...')
|
return oops('[!] failed reading block with chinese magic command. Quitting...')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
core.clearCommandBuffer()
|
||||||
-- wipe card.
|
|
||||||
local cmd = (csetuid..'%s 0004 08 w'):format(result.uid)
|
|
||||||
core.console(cmd)
|
|
||||||
|
|
||||||
|
-- wipe card.
|
||||||
|
local cmd = (csetuid..'%s %s %s w'):format(result.uid, atqa, sak)
|
||||||
|
core.console(cmd)
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
local b1 = toytype..string.rep('00',10)..subtype
|
local b1 = toytype..string.rep('00',10)..subtype
|
||||||
|
|
||||||
local calc = utils.Crc16(b0..b1)
|
local calc = utils.Crc16(b0..b1)
|
||||||
|
@ -150,6 +153,7 @@ local function main(args)
|
||||||
|
|
||||||
local cmd = (cset..'1 %s%04x'):format( b1, calcEndian)
|
local cmd = (cset..'1 %s%04x'):format( b1, calcEndian)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
local pos, key
|
local pos, key
|
||||||
for blockNo = 2, numBlocks-1, 1 do
|
for blockNo = 2, numBlocks-1, 1 do
|
||||||
|
@ -161,5 +165,10 @@ local function main(args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
||||||
|
-- Set sector trailer S0, since it has different access rights
|
||||||
|
cmd = ('%s 3 %s0f0f0f69000000000000'):format(cset, keyA)
|
||||||
|
core.console(cmd)
|
||||||
|
core.clearCommandBuffer()
|
||||||
end
|
end
|
||||||
main(args)
|
main(args)
|
||||||
|
|
|
@ -105,7 +105,7 @@ CborError _cbor_value_dup_string(const CborValue *value, void **buffer, size_t *
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
++*buflen;
|
++*buflen;
|
||||||
*buffer = malloc(*buflen);
|
*buffer = calloc(*buflen, sizeof(uint8_t));
|
||||||
if (!*buffer) {
|
if (!*buffer) {
|
||||||
/* out of memory */
|
/* out of memory */
|
||||||
return CborErrorOutOfMemory;
|
return CborErrorOutOfMemory;
|
||||||
|
|
|
@ -178,7 +178,7 @@ static CborError dump_bytestring_base16(char **result, CborValue *it)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* a Base16 (hex) output is twice as big as our buffer */
|
/* a Base16 (hex) output is twice as big as our buffer */
|
||||||
buffer = (uint8_t *)malloc(n * 2 + 1);
|
buffer = (uint8_t *)calloc(n * 2 + 1, sizeof(uint8_t));
|
||||||
*result = (char *)buffer;
|
*result = (char *)buffer;
|
||||||
|
|
||||||
/* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */
|
/* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */
|
||||||
|
@ -204,7 +204,7 @@ static CborError generic_dump_base64(char **result, CborValue *it, const char al
|
||||||
|
|
||||||
/* a Base64 output (untruncated) has 4 bytes for every 3 in the input */
|
/* a Base64 output (untruncated) has 4 bytes for every 3 in the input */
|
||||||
size_t len = (n + 5) / 3 * 4;
|
size_t len = (n + 5) / 3 * 4;
|
||||||
out = buffer = (uint8_t *)malloc(len + 1);
|
out = buffer = (uint8_t *)calloc(len + 1, sizeof(uint8_t));
|
||||||
*result = (char *)buffer;
|
*result = (char *)buffer;
|
||||||
|
|
||||||
/* we read our byte string at the tail end of the buffer
|
/* we read our byte string at the tail end of the buffer
|
||||||
|
|
|
@ -90,7 +90,7 @@ static int close_buffer(void *cookie)
|
||||||
|
|
||||||
FILE *open_memstream(char **bufptr, size_t *lenptr)
|
FILE *open_memstream(char **bufptr, size_t *lenptr)
|
||||||
{
|
{
|
||||||
struct Buffer *b = (struct Buffer *)malloc(sizeof(struct Buffer));
|
struct Buffer *b = (struct Buffer *)calloc(sizeof(struct Buffer), sizeof(uint8_t));
|
||||||
if (b == NULL)
|
if (b == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
b->alloc = 0;
|
b->alloc = 0;
|
||||||
|
|
|
@ -196,7 +196,7 @@ void SetFlushAfterWrite(bool value) {
|
||||||
|
|
||||||
int i,j;
|
int i,j;
|
||||||
|
|
||||||
int * output = (int* ) malloc(sizeof(int) * len);
|
int * output = (int* ) calloc(sizeof(int) * len, sizeof(uint8_t));
|
||||||
if ( !output ) return;
|
if ( !output ) return;
|
||||||
|
|
||||||
// clear mem
|
// clear mem
|
||||||
|
|
|
@ -280,7 +280,7 @@ void sprint_bin_break_ex(uint8_t *src, size_t srclen, char *dest , uint8_t break
|
||||||
printf("(sprint_bin_break) rowlen %d\n", rowlen);
|
printf("(sprint_bin_break) rowlen %d\n", rowlen);
|
||||||
|
|
||||||
// 3072 + end of line characters if broken at 8 bits
|
// 3072 + end of line characters if broken at 8 bits
|
||||||
dest = (char *)malloc(MAX_BIN_BREAK_LENGTH);
|
dest = (char *)calloc(MAX_BIN_BREAK_LENGTH, sizeof(uint8_t));
|
||||||
if (dest == NULL) return;
|
if (dest == NULL) return;
|
||||||
|
|
||||||
//clear memory
|
//clear memory
|
||||||
|
@ -884,8 +884,8 @@ extern void strcreplace(char *buf, size_t len, char from, char to) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern char *strmcopy(char *buf) {
|
extern char *strmcopy(char *buf) {
|
||||||
char* str = NULL;
|
char* str = (char*) calloc(strlen(buf) + 1, sizeof(uint8_t));
|
||||||
if ((str = (char*) malloc(strlen(buf) + 1)) != NULL) {
|
if (str != NULL) {
|
||||||
memset(str, 0, strlen(buf) + 1);
|
memset(str, 0, strlen(buf) + 1);
|
||||||
strcpy(str, buf);
|
strcpy(str, buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,6 +178,14 @@
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DropFieldEx
|
||||||
|
#define DropFieldEx(x) { \
|
||||||
|
if ( (x) == ECC_CONTACTLESS) { \
|
||||||
|
DropField(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
extern uint8_t g_debugMode;
|
extern uint8_t g_debugMode;
|
||||||
|
|
||||||
extern int ukbhit(void);
|
extern int ukbhit(void);
|
||||||
|
|
|
@ -405,7 +405,7 @@ int nonce_distance(uint32_t from, uint32_t to)
|
||||||
{
|
{
|
||||||
uint16_t x, i;
|
uint16_t x, i;
|
||||||
if(!dist) {
|
if(!dist) {
|
||||||
dist = malloc(2 << 16);
|
dist = calloc(2 << 16, sizeof(uint8_t));
|
||||||
if(!dist)
|
if(!dist)
|
||||||
return -1;
|
return -1;
|
||||||
for (x = i = 1; i; ++i) {
|
for (x = i = 1; i; ++i) {
|
||||||
|
@ -443,7 +443,7 @@ static uint32_t fastfwd[2][8] = {
|
||||||
*/
|
*/
|
||||||
uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd)
|
uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd)
|
||||||
{
|
{
|
||||||
uint32_t *candidates = malloc(4 << 10);
|
uint32_t *candidates = calloc(4 << 10, sizeof(uint8_t));
|
||||||
if (!candidates) return 0;
|
if (!candidates) return 0;
|
||||||
|
|
||||||
uint32_t c, entry;
|
uint32_t c, entry;
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
// ISO15693 commons
|
//-----------------------------------------------------------------------------
|
||||||
// Adrian Dabrowski 2010 and others, GPLv2
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||||
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
// the license.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// ISO15693 other commons
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Adrian Dabrowski 2010 and otherss
|
||||||
// Christian Herrmann 2018
|
// Christian Herrmann 2018
|
||||||
|
|
||||||
#ifndef ISO15693_H__
|
#ifndef ISO15693_H__
|
||||||
|
|
|
@ -302,10 +302,10 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||||
#define ISO7816_VERIFY 0x20
|
#define ISO7816_VERIFY 0x20
|
||||||
#define ISO7816_INTERNAL_AUTHENTICATION 0x88
|
#define ISO7816_INTERNAL_AUTHENTICATION 0x88
|
||||||
#define ISO7816_EXTERNAL_AUTHENTICATION 0x82
|
#define ISO7816_EXTERNAL_AUTHENTICATION 0x82
|
||||||
#define ISO7816_GET_CHALLENGE 0xB4
|
#define ISO7816_GET_CHALLENGE 0x84
|
||||||
#define ISO7816_MANAGE_CHANNEL 0x70
|
#define ISO7816_MANAGE_CHANNEL 0x70
|
||||||
|
|
||||||
#define ISO7816_GETSTATUS 0xC0
|
#define ISO7816_GET_RESPONSE 0xC0
|
||||||
// ISO7816-4 For response APDU's
|
// ISO7816-4 For response APDU's
|
||||||
#define ISO7816_OK 0x9000
|
#define ISO7816_OK 0x9000
|
||||||
// 6x xx = ERROR
|
// 6x xx = ERROR
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
uint64_t * radixSort(uint64_t * array, uint32_t size) {
|
uint64_t * radixSort(uint64_t * array, uint32_t size) {
|
||||||
rscounts_t counts;
|
rscounts_t counts;
|
||||||
memset(&counts, 0, 256 * 8 * sizeof(uint32_t));
|
memset(&counts, 0, 256 * 8 * sizeof(uint32_t));
|
||||||
uint64_t * cpy = (uint64_t *)malloc(size * sizeof(uint64_t));
|
uint64_t * cpy = (uint64_t *)calloc(size * sizeof(uint64_t), sizeof(uint8_t));
|
||||||
uint32_t o8=0, o7=0, o6=0, o5=0, o4=0, o3=0, o2=0, o1=0;
|
uint32_t o8=0, o7=0, o6=0, o5=0, o4=0, o3=0, o2=0, o1=0;
|
||||||
uint32_t t8, t7, t6, t5, t4, t3, t2, t1;
|
uint32_t t8, t7, t6, t5, t4, t3, t2, t1;
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
|
|
|
@ -35,7 +35,8 @@ typedef enum ISO14A_COMMAND {
|
||||||
ISO14A_SET_TIMEOUT = (1 << 6),
|
ISO14A_SET_TIMEOUT = (1 << 6),
|
||||||
ISO14A_NO_SELECT = (1 << 7),
|
ISO14A_NO_SELECT = (1 << 7),
|
||||||
ISO14A_TOPAZMODE = (1 << 8),
|
ISO14A_TOPAZMODE = (1 << 8),
|
||||||
ISO14A_NO_RATS = (1 << 9)
|
ISO14A_NO_RATS = (1 << 9),
|
||||||
|
ISO14A_SEND_CHAINING = (1 << 10)
|
||||||
} iso14a_command_t;
|
} iso14a_command_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -140,6 +140,8 @@ typedef struct{
|
||||||
#define CMD_COTAG 0x0225
|
#define CMD_COTAG 0x0225
|
||||||
#define CMD_SET_LF_T55XX_CONFIG 0x0226
|
#define CMD_SET_LF_T55XX_CONFIG 0x0226
|
||||||
|
|
||||||
|
#define CMD_T55XX_CHKPWDS 0x0230
|
||||||
|
|
||||||
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||||
|
|
||||||
// For the 13.56 MHz tags
|
// For the 13.56 MHz tags
|
||||||
|
|
|
@ -8,4 +8,12 @@ get_crapto1:
|
||||||
|
|
||||||
get_nonce_bf:
|
get_nonce_bf:
|
||||||
# git clone https://github.com/J-Run/mf_key_brute.git mf_key_brute
|
# git clone https://github.com/J-Run/mf_key_brute.git mf_key_brute
|
||||||
git clone https://github.com/iceman1001/mf_nonce_brute mf_nonce_brute
|
git clone https://github.com/iceman1001/mf_nonce_brute mf_nonce_brute
|
||||||
|
|
||||||
|
get_xorsearch:
|
||||||
|
mkdir xorsearch
|
||||||
|
wget -N https://didierstevens.com/files/software/XORSearch_V1_11_2.zip
|
||||||
|
# Mingw
|
||||||
|
# unzzip-big XORSearch_V1_11_2.zip
|
||||||
|
# linux
|
||||||
|
# gunzip XORSearch_V1_11_2.zip
|
|
@ -28,7 +28,7 @@ my $clean = 2;
|
||||||
# fatal: No names found, cannot describe anything.
|
# fatal: No names found, cannot describe anything.
|
||||||
##
|
##
|
||||||
# anyway forcing any kind of shell is at least useless, at worst fatal.
|
# anyway forcing any kind of shell is at least useless, at worst fatal.
|
||||||
my $commandGIT = "env -S which git";
|
my $commandGIT = "env which git";
|
||||||
|
|
||||||
if ( defined($commandGIT) ) {
|
if ( defined($commandGIT) ) {
|
||||||
|
|
||||||
|
|
|
@ -68,14 +68,14 @@ typedef struct {
|
||||||
} serial_port_unix;
|
} serial_port_unix;
|
||||||
|
|
||||||
// Set time-out on 30 miliseconds
|
// Set time-out on 30 miliseconds
|
||||||
const struct timeval timeout = {
|
struct timeval timeout = {
|
||||||
.tv_sec = 0, // 0 second
|
.tv_sec = 0, // 0 second
|
||||||
.tv_usec = 300000 // 300 000 micro seconds
|
.tv_usec = 30000 // 30000 micro seconds
|
||||||
};
|
};
|
||||||
|
|
||||||
serial_port uart_open(const char* pcPortName)
|
serial_port uart_open(const char* pcPortName)
|
||||||
{
|
{
|
||||||
serial_port_unix* sp = malloc(sizeof(serial_port_unix));
|
serial_port_unix* sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t));
|
||||||
if (sp == 0) return INVALID_SERIAL_PORT;
|
if (sp == 0) return INVALID_SERIAL_PORT;
|
||||||
|
|
||||||
if (memcmp(pcPortName, "tcp:", 4) == 0) {
|
if (memcmp(pcPortName, "tcp:", 4) == 0) {
|
||||||
|
@ -89,6 +89,10 @@ serial_port uart_open(const char* pcPortName)
|
||||||
|
|
||||||
char *colon = strrchr(addrstr, ':');
|
char *colon = strrchr(addrstr, ':');
|
||||||
char *portstr;
|
char *portstr;
|
||||||
|
|
||||||
|
// Set time-out to 300 miliseconds only for TCP port
|
||||||
|
timeout.tv_usec = 300000;
|
||||||
|
|
||||||
if (colon) {
|
if (colon) {
|
||||||
portstr = colon + 1;
|
portstr = colon + 1;
|
||||||
*colon = '\0';
|
*colon = '\0';
|
||||||
|
|
|
@ -50,7 +50,7 @@ typedef struct {
|
||||||
|
|
||||||
serial_port uart_open(const char* pcPortName) {
|
serial_port uart_open(const char* pcPortName) {
|
||||||
char acPortName[255];
|
char acPortName[255];
|
||||||
serial_port_windows* sp = malloc(sizeof(serial_port_windows));
|
serial_port_windows* sp = calloc(sizeof(serial_port_windows), sizeof(uint8_t));
|
||||||
|
|
||||||
if (sp == 0) {
|
if (sp == 0) {
|
||||||
printf("[!] UART failed to allocate memory\n");
|
printf("[!] UART failed to allocate memory\n");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue