mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-02-13 02:34:48 +08:00
Merge branch 'master' of https://github.com/RfidResearchGroup/proxmark3
This commit is contained in:
commit
37423ed2ad
18 changed files with 1562 additions and 1562 deletions
|
@ -28,20 +28,20 @@ from the client to view the stored quadlets.
|
|||
#define MAX_PWDS_PER_SESSION 64
|
||||
|
||||
uint8_t FindOffsetInFlash() {
|
||||
uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
uint8_t memcnt = 0;
|
||||
uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
uint8_t memcnt = 0;
|
||||
|
||||
while (memcnt < 0xFF)
|
||||
{
|
||||
Flash_ReadData(memcnt, mem, 4);
|
||||
if (memcmp(mem, eom, 4) == 0) {
|
||||
return memcnt;
|
||||
}
|
||||
memcnt += 4;
|
||||
}
|
||||
while (memcnt < 0xFF)
|
||||
{
|
||||
Flash_ReadData(memcnt, mem, 4);
|
||||
if (memcmp(mem, eom, 4) == 0) {
|
||||
return memcnt;
|
||||
}
|
||||
memcnt += 4;
|
||||
}
|
||||
|
||||
return 0; // wrap-around
|
||||
return 0; // wrap-around
|
||||
}
|
||||
|
||||
void EraseMemory() {
|
||||
|
@ -55,247 +55,247 @@ void EraseMemory() {
|
|||
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Erased flash!");
|
||||
FlashStop();
|
||||
SpinDelay(100);
|
||||
SpinDelay(100);
|
||||
}
|
||||
|
||||
// This is actually copied from SniffIso14443a
|
||||
void RAMFUNC SniffAndStore(uint8_t param) {
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
|
||||
|
||||
// Allocate memory from BigBuf for some buffers
|
||||
// free all previous allocations first
|
||||
BigBuf_free(); BigBuf_Clear_ext(false);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
// Allocate memory from BigBuf for some buffers
|
||||
// free all previous allocations first
|
||||
BigBuf_free(); BigBuf_Clear_ext(false);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
// Array to store the authpwds
|
||||
uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION);
|
||||
// Array to store the authpwds
|
||||
uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION);
|
||||
|
||||
// The command (reader -> tag) that we're receiving.
|
||||
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
// The command (reader -> tag) that we're receiving.
|
||||
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
|
||||
// The response (tag -> reader) that we're receiving.
|
||||
uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
// The response (tag -> reader) that we're receiving.
|
||||
uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
|
||||
// The DMA buffer, used to stream samples from the FPGA
|
||||
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
|
||||
uint8_t *data = dmaBuf;
|
||||
// The DMA buffer, used to stream samples from the FPGA
|
||||
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
|
||||
uint8_t *data = dmaBuf;
|
||||
|
||||
uint8_t previous_data = 0;
|
||||
int dataLen = 0;
|
||||
bool TagIsActive = false;
|
||||
bool ReaderIsActive = false;
|
||||
uint8_t previous_data = 0;
|
||||
int dataLen = 0;
|
||||
bool TagIsActive = false;
|
||||
bool ReaderIsActive = false;
|
||||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
DemodInit(receivedResp, receivedRespPar);
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
DemodInit(receivedResp, receivedRespPar);
|
||||
|
||||
// Set up the demodulator for the reader -> tag commands
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
// Set up the demodulator for the reader -> tag commands
|
||||
UartInit(receivedCmd, receivedCmdPar);
|
||||
|
||||
// Setup and start DMA.
|
||||
if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
|
||||
return;
|
||||
}
|
||||
// Setup and start DMA.
|
||||
if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
tUart* uart = GetUart();
|
||||
tDemod* demod = GetDemod();
|
||||
tUart* uart = GetUart();
|
||||
tDemod* demod = GetDemod();
|
||||
|
||||
// We won't start recording the frames that we acquire until we trigger;
|
||||
// a good trigger condition to get started is probably when we see a
|
||||
// response from the tag.
|
||||
// triggered == false -- to wait first for card
|
||||
bool triggered = !(param & 0x03);
|
||||
// We won't start recording the frames that we acquire until we trigger;
|
||||
// a good trigger condition to get started is probably when we see a
|
||||
// response from the tag.
|
||||
// triggered == false -- to wait first for card
|
||||
bool triggered = !(param & 0x03);
|
||||
|
||||
uint32_t rsamples = 0;
|
||||
uint32_t rsamples = 0;
|
||||
|
||||
// Current captured passwords counter
|
||||
uint8_t auth_attempts = 0;
|
||||
// Current captured passwords counter
|
||||
uint8_t auth_attempts = 0;
|
||||
|
||||
SpinDelay(50);
|
||||
SpinDelay(50);
|
||||
|
||||
// loop and listen
|
||||
while (!BUTTON_PRESS()) {
|
||||
// loop and listen
|
||||
while (!BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
LED_A_ON();
|
||||
|
||||
int register readBufDataP = data - dmaBuf;
|
||||
int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
|
||||
if (readBufDataP <= dmaBufDataP)
|
||||
dataLen = dmaBufDataP - readBufDataP;
|
||||
else
|
||||
dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP;
|
||||
int register readBufDataP = data - dmaBuf;
|
||||
int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
|
||||
if (readBufDataP <= dmaBufDataP)
|
||||
dataLen = dmaBufDataP - readBufDataP;
|
||||
else
|
||||
dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP;
|
||||
|
||||
// test for length of buffer
|
||||
if (dataLen > DMA_BUFFER_SIZE) { // TODO: Check if this works properly
|
||||
Dbprintf("[!] blew circular buffer! | datalen %u", dataLen);
|
||||
break;
|
||||
}
|
||||
if (dataLen < 1) continue;
|
||||
// test for length of buffer
|
||||
if (dataLen > DMA_BUFFER_SIZE) { // TODO: Check if this works properly
|
||||
Dbprintf("[!] blew circular buffer! | datalen %u", dataLen);
|
||||
break;
|
||||
}
|
||||
if (dataLen < 1) continue;
|
||||
|
||||
// primary buffer was stopped( <-- we lost data!
|
||||
if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
|
||||
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
|
||||
//Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
|
||||
}
|
||||
// secondary buffer sets as primary, secondary buffer was stopped
|
||||
if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
|
||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
|
||||
}
|
||||
// primary buffer was stopped( <-- we lost data!
|
||||
if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
|
||||
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
|
||||
//Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
|
||||
}
|
||||
// secondary buffer sets as primary, secondary buffer was stopped
|
||||
if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
|
||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
LED_A_OFF();
|
||||
LED_A_OFF();
|
||||
|
||||
// Need two samples to feed Miller and Manchester-Decoder
|
||||
if (rsamples & 0x01) {
|
||||
// Need two samples to feed Miller and Manchester-Decoder
|
||||
if (rsamples & 0x01) {
|
||||
|
||||
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
|
||||
uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
|
||||
if (MillerDecoding(readerdata, (rsamples-1)*4)) {
|
||||
LED_C_ON();
|
||||
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
|
||||
uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
|
||||
if (MillerDecoding(readerdata, (rsamples-1)*4)) {
|
||||
LED_C_ON();
|
||||
|
||||
// check - if there is a short 7bit request from reader
|
||||
if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7)) triggered = true;
|
||||
// check - if there is a short 7bit request from reader
|
||||
if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7)) triggered = true;
|
||||
|
||||
if (triggered) {
|
||||
if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) {
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]);
|
||||
if (triggered) {
|
||||
if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) {
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]);
|
||||
|
||||
// temporarily save the captured pwd in our array
|
||||
memcpy(&capturedPwds[4 * auth_attempts], receivedCmd+1, 4);
|
||||
auth_attempts++;
|
||||
}
|
||||
// temporarily save the captured pwd in our array
|
||||
memcpy(&capturedPwds[4 * auth_attempts], receivedCmd+1, 4);
|
||||
auth_attempts++;
|
||||
}
|
||||
|
||||
if (!LogTrace(receivedCmd,
|
||||
uart->len,
|
||||
uart->startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
uart->endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
uart->parity,
|
||||
true)) break;
|
||||
}
|
||||
/* ready to receive another command. */
|
||||
UartReset();
|
||||
/* reset the demod code, which might have been */
|
||||
/* false-triggered by the commands from the reader. */
|
||||
DemodReset();
|
||||
LED_B_OFF();
|
||||
}
|
||||
ReaderIsActive = (uart->state != STATE_UNSYNCD);
|
||||
}
|
||||
if (!LogTrace(receivedCmd,
|
||||
uart->len,
|
||||
uart->startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
uart->endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
|
||||
uart->parity,
|
||||
true)) break;
|
||||
}
|
||||
/* ready to receive another command. */
|
||||
UartReset();
|
||||
/* reset the demod code, which might have been */
|
||||
/* false-triggered by the commands from the reader. */
|
||||
DemodReset();
|
||||
LED_B_OFF();
|
||||
}
|
||||
ReaderIsActive = (uart->state != STATE_UNSYNCD);
|
||||
}
|
||||
|
||||
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
||||
if (!ReaderIsActive) {
|
||||
uint8_t tagdata = (previous_data << 4) | (*data & 0x0F);
|
||||
if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) {
|
||||
LED_B_ON();
|
||||
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
||||
if (!ReaderIsActive) {
|
||||
uint8_t tagdata = (previous_data << 4) | (*data & 0x0F);
|
||||
if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) {
|
||||
LED_B_ON();
|
||||
|
||||
if (!LogTrace(receivedResp,
|
||||
demod->len,
|
||||
demod->startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
demod->endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
demod->parity,
|
||||
false)) break;
|
||||
if (!LogTrace(receivedResp,
|
||||
demod->len,
|
||||
demod->startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
demod->endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
|
||||
demod->parity,
|
||||
false)) break;
|
||||
|
||||
if ((!triggered) && (param & 0x01)) triggered = true;
|
||||
if ((!triggered) && (param & 0x01)) triggered = true;
|
||||
|
||||
// ready to receive another response.
|
||||
DemodReset();
|
||||
// reset the Miller decoder including its (now outdated) input buffer
|
||||
UartReset();
|
||||
//UartInit(receivedCmd, receivedCmdPar);
|
||||
LED_C_OFF();
|
||||
}
|
||||
TagIsActive = (demod->state != DEMOD_UNSYNCD);
|
||||
}
|
||||
}
|
||||
// ready to receive another response.
|
||||
DemodReset();
|
||||
// reset the Miller decoder including its (now outdated) input buffer
|
||||
UartReset();
|
||||
//UartInit(receivedCmd, receivedCmdPar);
|
||||
LED_C_OFF();
|
||||
}
|
||||
TagIsActive = (demod->state != DEMOD_UNSYNCD);
|
||||
}
|
||||
}
|
||||
|
||||
previous_data = *data;
|
||||
rsamples++;
|
||||
data++;
|
||||
if (data == dmaBuf + DMA_BUFFER_SIZE) {
|
||||
data = dmaBuf;
|
||||
}
|
||||
} // end main loop
|
||||
previous_data = *data;
|
||||
rsamples++;
|
||||
data++;
|
||||
if (data == dmaBuf + DMA_BUFFER_SIZE) {
|
||||
data = dmaBuf;
|
||||
}
|
||||
} // end main loop
|
||||
|
||||
FpgaDisableSscDma();
|
||||
set_tracing(false);
|
||||
FpgaDisableSscDma();
|
||||
set_tracing(false);
|
||||
|
||||
Dbprintf("Stopped sniffing");
|
||||
Dbprintf("Stopped sniffing");
|
||||
|
||||
SpinDelay(200);
|
||||
SpinDelay(200);
|
||||
|
||||
// Write stuff to flash
|
||||
if (auth_attempts > 0) {
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Authentication attempts = %u", auth_attempts);
|
||||
// Write stuff to flash
|
||||
if (auth_attempts > 0) {
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Authentication attempts = %u", auth_attempts);
|
||||
|
||||
// Setting the SPI Baudrate to 48MHz to avoid the bit-flip issue (https://github.com/RfidResearchGroup/proxmark3/issues/34)
|
||||
FlashmemSetSpiBaudrate(48000000);
|
||||
// Setting the SPI Baudrate to 48MHz to avoid the bit-flip issue (https://github.com/RfidResearchGroup/proxmark3/issues/34)
|
||||
FlashmemSetSpiBaudrate(48000000);
|
||||
|
||||
// Find the offset in flash mem to continue writing the auth attempts
|
||||
uint8_t memoffset = FindOffsetInFlash();
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset);
|
||||
// Find the offset in flash mem to continue writing the auth attempts
|
||||
uint8_t memoffset = FindOffsetInFlash();
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset);
|
||||
|
||||
if ((memoffset + 4 * auth_attempts) > 0xFF)
|
||||
{
|
||||
// We opt to keep the new data only
|
||||
memoffset = 0;
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data.");
|
||||
}
|
||||
if ((memoffset + 4 * auth_attempts) > 0xFF)
|
||||
{
|
||||
// We opt to keep the new data only
|
||||
memoffset = 0;
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data.");
|
||||
}
|
||||
|
||||
// Get previous data from flash mem
|
||||
uint8_t *previousdata = BigBuf_malloc(memoffset);
|
||||
if (memoffset > 0)
|
||||
{
|
||||
uint16_t readlen = Flash_ReadData(0, previousdata, memoffset);
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen);
|
||||
}
|
||||
// Get previous data from flash mem
|
||||
uint8_t *previousdata = BigBuf_malloc(memoffset);
|
||||
if (memoffset > 0)
|
||||
{
|
||||
uint16_t readlen = Flash_ReadData(0, previousdata, memoffset);
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen);
|
||||
}
|
||||
|
||||
// create new bigbuf to hold all data
|
||||
size_t total_size = memoffset + 4 * auth_attempts;
|
||||
uint8_t *total_data = BigBuf_malloc(total_size);
|
||||
// create new bigbuf to hold all data
|
||||
size_t total_size = memoffset + 4 * auth_attempts;
|
||||
uint8_t *total_data = BigBuf_malloc(total_size);
|
||||
|
||||
// Add the previousdata array into total_data array
|
||||
memcpy(total_data, previousdata, memoffset);
|
||||
// Add the previousdata array into total_data array
|
||||
memcpy(total_data, previousdata, memoffset);
|
||||
|
||||
// Copy bytes of capturedPwds immediately following bytes of previousdata
|
||||
memcpy(total_data + memoffset, capturedPwds, 4 * auth_attempts);
|
||||
// Copy bytes of capturedPwds immediately following bytes of previousdata
|
||||
memcpy(total_data + memoffset, capturedPwds, 4 * auth_attempts);
|
||||
|
||||
// Erase first page of flash mem
|
||||
EraseMemory();
|
||||
// Erase first page of flash mem
|
||||
EraseMemory();
|
||||
|
||||
// Write total data to flash mem
|
||||
uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts);
|
||||
if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen);
|
||||
// Write total data to flash mem
|
||||
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 pwd saved successfully, blink led A three times
|
||||
if (writelen > 0) {
|
||||
SpinErr(0, 200, 5); // blink led A
|
||||
}
|
||||
if (writelen > 0) {
|
||||
SpinErr(0, 200, 5); // blink led A
|
||||
}
|
||||
|
||||
SpinDelay(100);
|
||||
SpinDelay(100);
|
||||
|
||||
// Reset the SPI Baudrate to the default value (24MHz)
|
||||
FlashmemSetSpiBaudrate(24000000);
|
||||
}
|
||||
// Reset the SPI Baudrate to the default value (24MHz)
|
||||
FlashmemSetSpiBaudrate(24000000);
|
||||
}
|
||||
}
|
||||
|
||||
void RunMod() {
|
||||
|
||||
StandAloneMode();
|
||||
StandAloneMode();
|
||||
|
||||
Dbprintf(">> Bogiton 14a Sniff UL/UL-EV1/NTAG a.k.a BogitoRun Started <<");
|
||||
Dbprintf("Starting to sniff");
|
||||
Dbprintf(">> Bogiton 14a Sniff UL/UL-EV1/NTAG a.k.a BogitoRun Started <<");
|
||||
Dbprintf("Starting to sniff");
|
||||
|
||||
// param:
|
||||
// bit 0 - trigger from first card answer
|
||||
// bit 1 - trigger from first reader 7-bit request
|
||||
SniffAndStore(0);
|
||||
LEDsoff();
|
||||
SpinDelay(300);
|
||||
Dbprintf("- [ End ] -> You can take shell back ...");
|
||||
Dbprintf("- [ ! ] -> use 'script run read_pwd_mem' to print passwords");
|
||||
// param:
|
||||
// bit 0 - trigger from first card answer
|
||||
// bit 1 - trigger from first reader 7-bit request
|
||||
SniffAndStore(0);
|
||||
LEDsoff();
|
||||
SpinDelay(300);
|
||||
Dbprintf("- [ End ] -> You can take shell back ...");
|
||||
Dbprintf("- [ ! ] -> use 'script run read_pwd_mem' to print passwords");
|
||||
}
|
||||
|
|
|
@ -171,8 +171,8 @@ void WriteTagToFlash(uint8_t index, size_t size)
|
|||
|
||||
while (bytes_remaining > 0)
|
||||
{
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
|
||||
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
|
||||
|
||||
|
@ -210,7 +210,7 @@ void WriteTagToFlash(uint8_t index, size_t size)
|
|||
|
||||
void RunMod()
|
||||
{
|
||||
StandAloneMode();
|
||||
StandAloneMode();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
currline = 20;
|
||||
|
@ -323,12 +323,12 @@ ACCBITS : 796788[00]+VALUE
|
|||
{
|
||||
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++)
|
||||
{
|
||||
foundKey[t][sectorNo][0] = 0xFF;
|
||||
foundKey[t][sectorNo][1] = 0xFF;
|
||||
foundKey[t][sectorNo][2] = 0xFF;
|
||||
foundKey[t][sectorNo][3] = 0xFF;
|
||||
foundKey[t][sectorNo][4] = 0xFF;
|
||||
foundKey[t][sectorNo][5] = 0xFF;
|
||||
foundKey[t][sectorNo][0] = 0xFF;
|
||||
foundKey[t][sectorNo][1] = 0xFF;
|
||||
foundKey[t][sectorNo][2] = 0xFF;
|
||||
foundKey[t][sectorNo][3] = 0xFF;
|
||||
foundKey[t][sectorNo][4] = 0xFF;
|
||||
foundKey[t][sectorNo][5] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -215,244 +215,244 @@ static int saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui
|
|||
|
||||
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<");
|
||||
StandAloneMode();
|
||||
Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
/*
|
||||
It will check if the keys from the attacked tag are a subset from
|
||||
the hardcoded set of keys inside of the ARM. If this is the case
|
||||
then it will load the keys into the emulator memory and also the
|
||||
content of the victim tag, to finally simulate it.
|
||||
/*
|
||||
It will check if the keys from the attacked tag are a subset from
|
||||
the hardcoded set of keys inside of the ARM. If this is the case
|
||||
then it will load the keys into the emulator memory and also the
|
||||
content of the victim tag, to finally simulate it.
|
||||
|
||||
Alternatively, it can be dumped into a blank card.
|
||||
Alternatively, it can be dumped into a blank card.
|
||||
|
||||
This source code has been tested only in Mifare 1k.
|
||||
This source code has been tested only in Mifare 1k.
|
||||
|
||||
If you're using the proxmark connected to a device that has an OS, and you're not using the proxmark3 client to see the debug
|
||||
messages, you MUST uncomment usb_disable().
|
||||
*/
|
||||
If you're using the proxmark connected to a device that has an OS, and you're not using the proxmark3 client to see the debug
|
||||
messages, you MUST uncomment usb_disable().
|
||||
*/
|
||||
|
||||
// Comment this line below if you want to see debug messages.
|
||||
// Comment this line below if you want to see debug messages.
|
||||
// usb_disable();
|
||||
|
||||
/*
|
||||
Pseudo-configuration block.
|
||||
Pseudo-configuration block.
|
||||
*/
|
||||
bool printKeys = false; // Prints keys
|
||||
bool transferToEml = true; // Transfer keys to emulator memory
|
||||
bool ecfill = true; // Fill emulator memory with cards content.
|
||||
bool simulation = true; // Simulates an exact copy of the target tag
|
||||
bool fillFromEmulator = false; // Dump emulator memory.
|
||||
bool printKeys = false; // Prints keys
|
||||
bool transferToEml = true; // Transfer keys to emulator memory
|
||||
bool ecfill = true; // Fill emulator memory with cards content.
|
||||
bool simulation = true; // Simulates an exact copy of the target tag
|
||||
bool fillFromEmulator = false; // Dump emulator memory.
|
||||
|
||||
|
||||
uint16_t mifare_size = 1024; // Mifare 1k (only 1k supported for now)
|
||||
uint8_t sectorSize = 64; // 1k's sector size is 64 bytes.
|
||||
uint8_t blockNo = 3; // Security block is number 3 for each sector.
|
||||
uint8_t sectorsCnt = (mifare_size/sectorSize);
|
||||
uint8_t keyType = 2; // Keytype buffer
|
||||
uint64_t key64; // Defines current key
|
||||
uint8_t *keyBlock = NULL; // Where the keys will be held in memory.
|
||||
uint8_t stKeyBlock = 20; // Set the quantity of keys in the block.
|
||||
uint8_t filled = 0; // Used to check if the memory was filled with success.
|
||||
bool keyFound = false;
|
||||
uint16_t mifare_size = 1024; // Mifare 1k (only 1k supported for now)
|
||||
uint8_t sectorSize = 64; // 1k's sector size is 64 bytes.
|
||||
uint8_t blockNo = 3; // Security block is number 3 for each sector.
|
||||
uint8_t sectorsCnt = (mifare_size/sectorSize);
|
||||
uint8_t keyType = 2; // Keytype buffer
|
||||
uint64_t key64; // Defines current key
|
||||
uint8_t *keyBlock = NULL; // Where the keys will be held in memory.
|
||||
uint8_t stKeyBlock = 20; // Set the quantity of keys in the block.
|
||||
uint8_t filled = 0; // Used to check if the memory was filled with success.
|
||||
bool keyFound = false;
|
||||
|
||||
/*
|
||||
Set of keys to be used.
|
||||
*/
|
||||
uint64_t mfKeys[] = {
|
||||
0xffffffffffff, // Default key
|
||||
0x000000000000, // Blank key
|
||||
0xa0a1a2a3a4a5, // NFCForum MAD key
|
||||
0xb0b1b2b3b4b5,
|
||||
0xaabbccddeeff,
|
||||
0x4d3a99c351dd,
|
||||
0x1a982c7e459a,
|
||||
0xd3f7d3f7d3f7,
|
||||
0x714c5c886e97,
|
||||
0x587ee5f9350f,
|
||||
0xa0478cc39091,
|
||||
0x533cb6c723f6,
|
||||
0x8fd0a4f256e9,
|
||||
};
|
||||
/*
|
||||
Set of keys to be used.
|
||||
*/
|
||||
uint64_t mfKeys[] = {
|
||||
0xffffffffffff, // Default key
|
||||
0x000000000000, // Blank key
|
||||
0xa0a1a2a3a4a5, // NFCForum MAD key
|
||||
0xb0b1b2b3b4b5,
|
||||
0xaabbccddeeff,
|
||||
0x4d3a99c351dd,
|
||||
0x1a982c7e459a,
|
||||
0xd3f7d3f7d3f7,
|
||||
0x714c5c886e97,
|
||||
0x587ee5f9350f,
|
||||
0xa0478cc39091,
|
||||
0x533cb6c723f6,
|
||||
0x8fd0a4f256e9,
|
||||
};
|
||||
|
||||
/*
|
||||
This part allocates the byte representation of the
|
||||
keys in keyBlock's memory space .
|
||||
*/
|
||||
keyBlock = BigBuf_malloc(stKeyBlock * 6);
|
||||
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
|
||||
/*
|
||||
This part allocates the byte representation of the
|
||||
keys in keyBlock's memory space .
|
||||
*/
|
||||
keyBlock = BigBuf_malloc(stKeyBlock * 6);
|
||||
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
|
||||
|
||||
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
|
||||
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t*)(keyBlock + mfKeyCounter * 6));
|
||||
}
|
||||
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
|
||||
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t*)(keyBlock + mfKeyCounter * 6));
|
||||
}
|
||||
|
||||
/*
|
||||
Pretty print of the keys to be checked.
|
||||
*/
|
||||
if (printKeys) {
|
||||
Dbprintf("[+] Printing mf keys");
|
||||
for (uint8_t keycnt = 0; keycnt < mfKeysCnt; keycnt++)
|
||||
Dbprintf("[-] chk mf key[%2d] %02x%02x%02x%02x%02x%02x", keycnt,
|
||||
(keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],
|
||||
(keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6);
|
||||
DbpString("--------------------------------------------------------");
|
||||
}
|
||||
/*
|
||||
Pretty print of the keys to be checked.
|
||||
*/
|
||||
if (printKeys) {
|
||||
Dbprintf("[+] Printing mf keys");
|
||||
for (uint8_t keycnt = 0; keycnt < mfKeysCnt; keycnt++)
|
||||
Dbprintf("[-] chk mf key[%2d] %02x%02x%02x%02x%02x%02x", keycnt,
|
||||
(keyBlock + 6*keycnt)[0], (keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],
|
||||
(keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6);
|
||||
DbpString("--------------------------------------------------------");
|
||||
}
|
||||
|
||||
/*
|
||||
Initialization of validKeys and foundKeys storages.
|
||||
- validKey will store whether the sector has a valid A/B key.
|
||||
- foundKey will store the found A/B key for each sector.
|
||||
*/
|
||||
bool validKey[2][40];
|
||||
uint8_t foundKey[2][40][6];
|
||||
for (uint16_t t = 0; t < 2; t++) {
|
||||
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
|
||||
validKey[t][sectorNo] = false;
|
||||
for (uint16_t i = 0; i < 6; i++) {
|
||||
foundKey[t][sectorNo][i] = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Initialization of validKeys and foundKeys storages.
|
||||
- validKey will store whether the sector has a valid A/B key.
|
||||
- foundKey will store the found A/B key for each sector.
|
||||
*/
|
||||
bool validKey[2][40];
|
||||
uint8_t foundKey[2][40][6];
|
||||
for (uint16_t t = 0; t < 2; t++) {
|
||||
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
|
||||
validKey[t][sectorNo] = false;
|
||||
for (uint16_t i = 0; i < 6; i++) {
|
||||
foundKey[t][sectorNo][i] = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Iterates through each sector checking if there is a correct key.
|
||||
*/
|
||||
int key = -1;
|
||||
int block = 0;
|
||||
bool err = 0;
|
||||
bool allKeysFound = true;
|
||||
uint32_t size = mfKeysCnt;
|
||||
/*
|
||||
Iterates through each sector checking if there is a correct key.
|
||||
*/
|
||||
int key = -1;
|
||||
int block = 0;
|
||||
bool err = 0;
|
||||
bool allKeysFound = true;
|
||||
uint32_t size = mfKeysCnt;
|
||||
|
||||
for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) {
|
||||
block = blockNo;
|
||||
for (int sec = 0; sec < sectorsCnt && !err; ++sec) {
|
||||
Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B':'A', mfKeysCnt);
|
||||
key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64);
|
||||
if (key == -1) {
|
||||
LED(LED_RED, 50); //red
|
||||
Dbprintf("\t✕ Key not found for this sector!");
|
||||
allKeysFound = false;
|
||||
// break;
|
||||
} else if (key == -2) {
|
||||
err = 1; // Can't select card.
|
||||
break;
|
||||
} else {
|
||||
num_to_bytes(key64, 6, foundKey[type][sec]);
|
||||
validKey[type][sec] = true;
|
||||
keyFound = true;
|
||||
Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n",
|
||||
(keyBlock + 6*key)[0], (keyBlock + 6*key)[1], (keyBlock + 6*key)[2],
|
||||
(keyBlock + 6*key)[3], (keyBlock + 6*key)[4], (keyBlock + 6*key)[5]
|
||||
);
|
||||
}
|
||||
for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) {
|
||||
block = blockNo;
|
||||
for (int sec = 0; sec < sectorsCnt && !err; ++sec) {
|
||||
Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B':'A', mfKeysCnt);
|
||||
key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64);
|
||||
if (key == -1) {
|
||||
LED(LED_RED, 50); //red
|
||||
Dbprintf("\t✕ Key not found for this sector!");
|
||||
allKeysFound = false;
|
||||
// break;
|
||||
} else if (key == -2) {
|
||||
err = 1; // Can't select card.
|
||||
break;
|
||||
} else {
|
||||
num_to_bytes(key64, 6, foundKey[type][sec]);
|
||||
validKey[type][sec] = true;
|
||||
keyFound = true;
|
||||
Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n",
|
||||
(keyBlock + 6*key)[0], (keyBlock + 6*key)[1], (keyBlock + 6*key)[2],
|
||||
(keyBlock + 6*key)[3], (keyBlock + 6*key)[4], (keyBlock + 6*key)[5]
|
||||
);
|
||||
}
|
||||
|
||||
block < 127 ? (block += 4) : (block += 16);
|
||||
}
|
||||
}
|
||||
block < 127 ? (block += 4) : (block += 16);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO:
|
||||
- Get UID from tag and set accordingly in emulator memory and call mifare1ksim with right flags (iceman)
|
||||
*/
|
||||
if (!allKeysFound && keyFound) {
|
||||
Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!");
|
||||
LED_C_ON(); //red
|
||||
LED_A_ON(); //yellow
|
||||
// no room to run nested attack on device (iceman)
|
||||
// Do nested attack, set allKeysFound = true;
|
||||
// allKeysFound = true;
|
||||
} else {
|
||||
Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!");
|
||||
LED_C_ON(); //red
|
||||
}
|
||||
/*
|
||||
TODO:
|
||||
- Get UID from tag and set accordingly in emulator memory and call mifare1ksim with right flags (iceman)
|
||||
*/
|
||||
if (!allKeysFound && keyFound) {
|
||||
Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!");
|
||||
LED_C_ON(); //red
|
||||
LED_A_ON(); //yellow
|
||||
// no room to run nested attack on device (iceman)
|
||||
// Do nested attack, set allKeysFound = true;
|
||||
// allKeysFound = true;
|
||||
} else {
|
||||
Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!");
|
||||
LED_C_ON(); //red
|
||||
}
|
||||
|
||||
/*
|
||||
If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned.
|
||||
*/
|
||||
if ((transferToEml) && (allKeysFound)) {
|
||||
/*
|
||||
If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned.
|
||||
*/
|
||||
if ((transferToEml) && (allKeysFound)) {
|
||||
|
||||
emlClearMem();
|
||||
emlClearMem();
|
||||
|
||||
uint8_t mblock[16];
|
||||
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
|
||||
if (validKey[0][sectorNo] || validKey[1][sectorNo]) {
|
||||
emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); // data, block num, blocks count (max 4)
|
||||
for (uint16_t t = 0; t < 2; t++) {
|
||||
if (validKey[t][sectorNo]) {
|
||||
memcpy(mblock + t*10, foundKey[t][sectorNo], 6);
|
||||
}
|
||||
}
|
||||
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
|
||||
}
|
||||
}
|
||||
Dbprintf("\t✓ Found keys have been transferred to the emulator memory.");
|
||||
if (ecfill) {
|
||||
uint8_t mblock[16];
|
||||
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
|
||||
if (validKey[0][sectorNo] || validKey[1][sectorNo]) {
|
||||
emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); // data, block num, blocks count (max 4)
|
||||
for (uint16_t t = 0; t < 2; t++) {
|
||||
if (validKey[t][sectorNo]) {
|
||||
memcpy(mblock + t*10, foundKey[t][sectorNo], 6);
|
||||
}
|
||||
}
|
||||
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
|
||||
}
|
||||
}
|
||||
Dbprintf("\t✓ Found keys have been transferred to the emulator memory.");
|
||||
if (ecfill) {
|
||||
|
||||
Dbprintf("\tFilling in with key A.");
|
||||
MifareECardLoad(sectorsCnt, 0, 0, &filled);
|
||||
if (filled != 1) {
|
||||
Dbprintf("\t✕ Failed filling with A.");
|
||||
}
|
||||
Dbprintf("\tFilling in with key A.");
|
||||
MifareECardLoad(sectorsCnt, 0, 0, &filled);
|
||||
if (filled != 1) {
|
||||
Dbprintf("\t✕ Failed filling with A.");
|
||||
}
|
||||
|
||||
Dbprintf("\tFilling in with key B.");
|
||||
MifareECardLoad(sectorsCnt, 1, 0, &filled);
|
||||
if (filled != 1) {
|
||||
Dbprintf("\t✕ Failed filling with B.");
|
||||
}
|
||||
Dbprintf("\tFilling in with key B.");
|
||||
MifareECardLoad(sectorsCnt, 1, 0, &filled);
|
||||
if (filled != 1) {
|
||||
Dbprintf("\t✕ Failed filling with B.");
|
||||
}
|
||||
|
||||
if ((filled == 1) && simulation) {
|
||||
Dbprintf("\t✓ Filled, simulation started.");
|
||||
if ((filled == 1) && simulation) {
|
||||
Dbprintf("\t✓ Filled, simulation started.");
|
||||
|
||||
// This will tell the fpga to emulate using previous keys and current target tag content.
|
||||
Dbprintf("\t Press button to abort simulation at anytime.");
|
||||
// This will tell the fpga to emulate using previous keys and current target tag content.
|
||||
Dbprintf("\t Press button to abort simulation at anytime.");
|
||||
|
||||
LED_B_ON(); // green
|
||||
// assuming arg0==0, use hardcoded uid 0xdeadbeaf
|
||||
Mifare1ksim( FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL, 0, 0, uid);
|
||||
LED_B_OFF();
|
||||
LED_B_ON(); // green
|
||||
// assuming arg0==0, use hardcoded uid 0xdeadbeaf
|
||||
Mifare1ksim( FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL, 0, 0, uid);
|
||||
LED_B_OFF();
|
||||
|
||||
/*
|
||||
Needs further testing.
|
||||
*/
|
||||
if (fillFromEmulator) {
|
||||
uint8_t retry = 5, cnt;
|
||||
Dbprintf("\t Trying to dump into blank card.");
|
||||
int flags = 0;
|
||||
LED_A_ON(); //yellow
|
||||
for (int blockNum = 0; blockNum < 16 * 4; blockNum += 1) {
|
||||
cnt = 0;
|
||||
emlGetMem(mblock, blockNum, 1);
|
||||
// switch on field and send magic sequence
|
||||
if (blockNum == 0) flags = 0x08 + 0x02;
|
||||
/*
|
||||
Needs further testing.
|
||||
*/
|
||||
if (fillFromEmulator) {
|
||||
uint8_t retry = 5, cnt;
|
||||
Dbprintf("\t Trying to dump into blank card.");
|
||||
int flags = 0;
|
||||
LED_A_ON(); //yellow
|
||||
for (int blockNum = 0; blockNum < 16 * 4; blockNum += 1) {
|
||||
cnt = 0;
|
||||
emlGetMem(mblock, blockNum, 1);
|
||||
// switch on field and send magic sequence
|
||||
if (blockNum == 0) flags = 0x08 + 0x02;
|
||||
|
||||
// just write
|
||||
if (blockNum == 1) flags = 0;
|
||||
// just write
|
||||
if (blockNum == 1) flags = 0;
|
||||
|
||||
// Done. Magic Halt and switch off field.
|
||||
if (blockNum == 16 * 4 - 1) flags = 0x04 + 0x10;
|
||||
// Done. Magic Halt and switch off field.
|
||||
if (blockNum == 16 * 4 - 1) flags = 0x04 + 0x10;
|
||||
|
||||
while (!saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock) && cnt <= retry) {
|
||||
cnt++;
|
||||
Dbprintf("\t! Could not write block. Retrying.");
|
||||
}
|
||||
if (cnt == retry) {
|
||||
Dbprintf("\t✕ Retries failed. Aborting.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock) && cnt <= retry) {
|
||||
cnt++;
|
||||
Dbprintf("\t! Could not write block. Retrying.");
|
||||
}
|
||||
if (cnt == retry) {
|
||||
Dbprintf("\t✕ Retries failed. Aborting.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
LED_B_ON();
|
||||
} else {
|
||||
LED_C_ON();
|
||||
}
|
||||
if (!err) {
|
||||
LED_B_ON();
|
||||
} else {
|
||||
LED_C_ON();
|
||||
}
|
||||
|
||||
}
|
||||
} else if (filled != 1) {
|
||||
Dbprintf("\t✕ Memory could not be filled due to errors.");
|
||||
LED_C_ON();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (filled != 1) {
|
||||
Dbprintf("\t✕ Memory could not be filled due to errors.");
|
||||
LED_C_ON();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
//#include <stdbool.h> // for bool
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include "apps.h" // debugstatements, lfops?
|
||||
#include "usb_cmd.h" // mifare1ksim flags
|
||||
#include "apps.h" // debugstatements, lfops?
|
||||
#include "usb_cmd.h" // mifare1ksim flags
|
||||
#include "mifareutil.h"
|
||||
|
||||
#define OPTS 2
|
||||
|
|
|
@ -11,252 +11,252 @@
|
|||
#include "hf_young.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t uid[10];
|
||||
uint8_t uidlen;
|
||||
uint8_t atqa[2];
|
||||
uint8_t sak;
|
||||
uint8_t uid[10];
|
||||
uint8_t uidlen;
|
||||
uint8_t atqa[2];
|
||||
uint8_t sak;
|
||||
} __attribute__((__packed__)) card_clone_t;
|
||||
|
||||
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
Dbprintf(">> Craig Young Mifare sniff UID/clone uid 2 magic/sim a.k.a YoungRun Started <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
StandAloneMode();
|
||||
Dbprintf(">> Craig Young Mifare sniff UID/clone uid 2 magic/sim a.k.a YoungRun Started <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
int selected = 0, playing = 0, iGotoRecord = 0, iGotoClone = 0;
|
||||
int cardRead[OPTS] = {0};
|
||||
int selected = 0, playing = 0, iGotoRecord = 0, iGotoClone = 0;
|
||||
int cardRead[OPTS] = {0};
|
||||
|
||||
card_clone_t uids[OPTS];
|
||||
iso14a_card_select_t card[OPTS];
|
||||
uint8_t params = (MAGIC_SINGLE | MAGIC_DATAIN);
|
||||
card_clone_t uids[OPTS];
|
||||
iso14a_card_select_t card[OPTS];
|
||||
uint8_t params = (MAGIC_SINGLE | MAGIC_DATAIN);
|
||||
|
||||
LED(selected + 1, 0);
|
||||
LED(selected + 1, 0);
|
||||
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
// exit from Standalone Mode, send a usbcommand.
|
||||
if (usb_poll_validate_length()) return;
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
// exit from Standalone Mode, send a usbcommand.
|
||||
if (usb_poll_validate_length()) return;
|
||||
|
||||
SpinDelay(300);
|
||||
SpinDelay(300);
|
||||
|
||||
if (iGotoRecord == 1 || cardRead[selected] == 0) {
|
||||
iGotoRecord = 0;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_RED2, 0);
|
||||
if (iGotoRecord == 1 || cardRead[selected] == 0) {
|
||||
iGotoRecord = 0;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_RED2, 0);
|
||||
|
||||
// record
|
||||
Dbprintf("Enabling iso14443a reader mode for [Bank: %d]...", selected);
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||
// record
|
||||
Dbprintf("Enabling iso14443a reader mode for [Bank: %d]...", selected);
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||
|
||||
for (;;) {
|
||||
// exit from Standalone Mode, send a usbcommand.
|
||||
if (usb_poll_validate_length()) return;
|
||||
for (;;) {
|
||||
// exit from Standalone Mode, send a usbcommand.
|
||||
if (usb_poll_validate_length()) return;
|
||||
|
||||
if (BUTTON_PRESS()) {
|
||||
if (cardRead[selected]) {
|
||||
Dbprintf("Button press detected -- replaying card in bank[%d]", selected);
|
||||
break;
|
||||
} else if (cardRead[(selected+1) % OPTS]) {
|
||||
Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS);
|
||||
selected = (selected+1) % OPTS;
|
||||
break; // playing = 1;
|
||||
} else {
|
||||
Dbprintf("Button press detected but no stored tag to play. (Ignoring button)");
|
||||
SpinDelay(300);
|
||||
}
|
||||
}
|
||||
if (BUTTON_PRESS()) {
|
||||
if (cardRead[selected]) {
|
||||
Dbprintf("Button press detected -- replaying card in bank[%d]", selected);
|
||||
break;
|
||||
} else if (cardRead[(selected+1) % OPTS]) {
|
||||
Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS);
|
||||
selected = (selected+1) % OPTS;
|
||||
break; // playing = 1;
|
||||
} else {
|
||||
Dbprintf("Button press detected but no stored tag to play. (Ignoring button)");
|
||||
SpinDelay(300);
|
||||
}
|
||||
}
|
||||
|
||||
if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true)) {
|
||||
continue;
|
||||
} else {
|
||||
Dbprintf("Read UID:");
|
||||
Dbhexdump(card[selected].uidlen, card[selected].uid, 0);
|
||||
if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true)) {
|
||||
continue;
|
||||
} else {
|
||||
Dbprintf("Read UID:");
|
||||
Dbhexdump(card[selected].uidlen, card[selected].uid, 0);
|
||||
|
||||
if (memcmp(uids[(selected+1)%OPTS].uid, card[selected].uid, card[selected].uidlen ) == 0 ) {
|
||||
Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping.");
|
||||
} else {
|
||||
uids[selected].sak = card[selected].sak;
|
||||
uids[selected].uidlen = card[selected].uidlen;
|
||||
memcpy(uids[selected].uid , card[selected].uid, uids[selected].uidlen);
|
||||
memcpy(uids[selected].atqa, card[selected].atqa, 2);
|
||||
if (memcmp(uids[(selected+1)%OPTS].uid, card[selected].uid, card[selected].uidlen ) == 0 ) {
|
||||
Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping.");
|
||||
} else {
|
||||
uids[selected].sak = card[selected].sak;
|
||||
uids[selected].uidlen = card[selected].uidlen;
|
||||
memcpy(uids[selected].uid , card[selected].uid, uids[selected].uidlen);
|
||||
memcpy(uids[selected].atqa, card[selected].atqa, 2);
|
||||
|
||||
if (uids[selected].uidlen > 4)
|
||||
Dbprintf("Bank[%d] received a 7-byte UID", selected);
|
||||
else
|
||||
Dbprintf("Bank[%d] received a 4-byte UID", selected);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uids[selected].uidlen > 4)
|
||||
Dbprintf("Bank[%d] received a 7-byte UID", selected);
|
||||
else
|
||||
Dbprintf("Bank[%d] received a 4-byte UID", selected);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]);
|
||||
Dbprintf("SAK = %02X", uids[selected].sak);
|
||||
LEDsoff();
|
||||
LED(LED_GREEN, 200);
|
||||
LED(LED_ORANGE, 200);
|
||||
LED(LED_GREEN, 200);
|
||||
LED(LED_ORANGE, 200);
|
||||
Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]);
|
||||
Dbprintf("SAK = %02X", uids[selected].sak);
|
||||
LEDsoff();
|
||||
LED(LED_GREEN, 200);
|
||||
LED(LED_ORANGE, 200);
|
||||
LED(LED_GREEN, 200);
|
||||
LED(LED_ORANGE, 200);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
|
||||
// Next state is replay:
|
||||
playing = 1;
|
||||
// Next state is replay:
|
||||
playing = 1;
|
||||
|
||||
cardRead[selected] = 1;
|
||||
}
|
||||
cardRead[selected] = 1;
|
||||
}
|
||||
|
||||
/* MF Classic UID clone */
|
||||
else if (iGotoClone==1) {
|
||||
iGotoClone=0;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_ORANGE, 250);
|
||||
/* MF Classic UID clone */
|
||||
else if (iGotoClone==1) {
|
||||
iGotoClone=0;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_ORANGE, 250);
|
||||
|
||||
// magiccards holds 4bytes uid. *usually*
|
||||
uint32_t tmpuid = bytes_to_num(uids[selected].uid, 4);
|
||||
// magiccards holds 4bytes uid. *usually*
|
||||
uint32_t tmpuid = bytes_to_num(uids[selected].uid, 4);
|
||||
|
||||
// record
|
||||
Dbprintf("Preparing to Clone card [Bank: %d]; uid: %08x", selected, tmpuid);
|
||||
// record
|
||||
Dbprintf("Preparing to Clone card [Bank: %d]; uid: %08x", selected, tmpuid);
|
||||
|
||||
// wait for button to be released
|
||||
// Delay cloning until card is in place
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// wait for button to be released
|
||||
// Delay cloning until card is in place
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
Dbprintf("Starting clone. [Bank: %d]", selected);
|
||||
// need this delay to prevent catching some weird data
|
||||
SpinDelay(500);
|
||||
// Begin clone function here:
|
||||
/* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards:
|
||||
UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0}};
|
||||
memcpy(c.d.asBytes, data, 16);
|
||||
SendCommand(&c);
|
||||
Dbprintf("Starting clone. [Bank: %d]", selected);
|
||||
// need this delay to prevent catching some weird data
|
||||
SpinDelay(500);
|
||||
// Begin clone function here:
|
||||
/* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards:
|
||||
UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0}};
|
||||
memcpy(c.d.asBytes, data, 16);
|
||||
SendCommand(&c);
|
||||
|
||||
Block read is similar:
|
||||
UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}};
|
||||
We need to imitate that call with blockNo 0 to set a uid.
|
||||
Block read is similar:
|
||||
UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}};
|
||||
We need to imitate that call with blockNo 0 to set a uid.
|
||||
|
||||
The get and set commands are handled in this file:
|
||||
// Work with "magic Chinese" card
|
||||
case CMD_MIFARE_CSETBLOCK:
|
||||
MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_CGETBLOCK:
|
||||
MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
The get and set commands are handled in this file:
|
||||
// Work with "magic Chinese" card
|
||||
case CMD_MIFARE_CSETBLOCK:
|
||||
MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_CGETBLOCK:
|
||||
MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
|
||||
mfCSetUID provides example logic for UID set workflow:
|
||||
-Read block0 from card in field with MifareCGetBlock()
|
||||
-Configure new values without replacing reserved bytes
|
||||
memcpy(block0, uid, 4); // Copy UID bytes from byte array
|
||||
// Mifare UID BCC
|
||||
block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5
|
||||
Bytes 5-7 are reserved SAK and ATQA for mifare classic
|
||||
-Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it
|
||||
*/
|
||||
uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0};
|
||||
// arg0 = Flags, arg1=blockNo
|
||||
MifareCGetBlock(params, 0, oldBlock0);
|
||||
if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) {
|
||||
Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected);
|
||||
playing = 1;
|
||||
} else {
|
||||
Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0], oldBlock0[1], oldBlock0[2], oldBlock0[3]);
|
||||
memcpy(newBlock0, oldBlock0, 16);
|
||||
mfCSetUID provides example logic for UID set workflow:
|
||||
-Read block0 from card in field with MifareCGetBlock()
|
||||
-Configure new values without replacing reserved bytes
|
||||
memcpy(block0, uid, 4); // Copy UID bytes from byte array
|
||||
// Mifare UID BCC
|
||||
block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5
|
||||
Bytes 5-7 are reserved SAK and ATQA for mifare classic
|
||||
-Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it
|
||||
*/
|
||||
uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0};
|
||||
// arg0 = Flags, arg1=blockNo
|
||||
MifareCGetBlock(params, 0, oldBlock0);
|
||||
if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) {
|
||||
Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected);
|
||||
playing = 1;
|
||||
} else {
|
||||
Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0], oldBlock0[1], oldBlock0[2], oldBlock0[3]);
|
||||
memcpy(newBlock0, oldBlock0, 16);
|
||||
|
||||
// Copy uid for bank (2nd is for longer UIDs not supported if classic)
|
||||
memcpy(newBlock0, uids[selected].uid, 4);
|
||||
newBlock0[4] = newBlock0[0] ^ newBlock0[1] ^ newBlock0[2] ^ newBlock0[3];
|
||||
// Copy uid for bank (2nd is for longer UIDs not supported if classic)
|
||||
memcpy(newBlock0, uids[selected].uid, 4);
|
||||
newBlock0[4] = newBlock0[0] ^ newBlock0[1] ^ newBlock0[2] ^ newBlock0[3];
|
||||
|
||||
// arg0 = workFlags, arg1 = blockNo, datain
|
||||
MifareCSetBlock(params, 0, newBlock0);
|
||||
MifareCGetBlock(params, 0, testBlock0);
|
||||
// arg0 = workFlags, arg1 = blockNo, datain
|
||||
MifareCSetBlock(params, 0, newBlock0);
|
||||
MifareCGetBlock(params, 0, testBlock0);
|
||||
|
||||
if (memcmp(testBlock0, newBlock0, 16)==0) {
|
||||
DbpString("Cloned successfull!");
|
||||
cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it
|
||||
playing = 0;
|
||||
iGotoRecord = 1;
|
||||
selected = (selected + 1) % OPTS;
|
||||
} else {
|
||||
Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected);
|
||||
playing = 1;
|
||||
}
|
||||
}
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
}
|
||||
if (memcmp(testBlock0, newBlock0, 16)==0) {
|
||||
DbpString("Cloned successfull!");
|
||||
cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it
|
||||
playing = 0;
|
||||
iGotoRecord = 1;
|
||||
selected = (selected + 1) % OPTS;
|
||||
} else {
|
||||
Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected);
|
||||
playing = 1;
|
||||
}
|
||||
}
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
}
|
||||
|
||||
// Change where to record (or begin playing)
|
||||
// button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected])
|
||||
else if (playing==1) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Change where to record (or begin playing)
|
||||
// button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected])
|
||||
else if (playing==1) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
|
||||
// Begin transmitting
|
||||
LED(LED_GREEN, 0);
|
||||
DbpString("Playing");
|
||||
for ( ; ; ) {
|
||||
// exit from Standalone Mode, send a usbcommand.
|
||||
if (usb_poll_validate_length()) return;
|
||||
// Begin transmitting
|
||||
LED(LED_GREEN, 0);
|
||||
DbpString("Playing");
|
||||
for ( ; ; ) {
|
||||
// exit from Standalone Mode, send a usbcommand.
|
||||
if (usb_poll_validate_length()) return;
|
||||
|
||||
int button_action = BUTTON_HELD(1000);
|
||||
if ( button_action == 0) { // No button action, proceed with sim
|
||||
int button_action = BUTTON_HELD(1000);
|
||||
if ( button_action == 0) { // No button action, proceed with sim
|
||||
|
||||
uint8_t flags = FLAG_4B_UID_IN_DATA;
|
||||
uint8_t data[USB_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break
|
||||
uint8_t flags = FLAG_4B_UID_IN_DATA;
|
||||
uint8_t data[USB_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break
|
||||
|
||||
memcpy(data, uids[selected].uid, uids[selected].uidlen);
|
||||
memcpy(data, uids[selected].uid, uids[selected].uidlen);
|
||||
|
||||
uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen);
|
||||
uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen);
|
||||
|
||||
if ( uids[selected].uidlen == 7 ) {
|
||||
flags = FLAG_7B_UID_IN_DATA;
|
||||
Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected);
|
||||
} else {
|
||||
Dbprintf("Simulating ISO14443a tag with uid: %08" PRIx64 " [Bank: %d]", tmpuid, selected);
|
||||
}
|
||||
if ( uids[selected].uidlen == 7 ) {
|
||||
flags = FLAG_7B_UID_IN_DATA;
|
||||
Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected);
|
||||
} else {
|
||||
Dbprintf("Simulating ISO14443a tag with uid: %08" PRIx64 " [Bank: %d]", tmpuid, selected);
|
||||
}
|
||||
|
||||
if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) {
|
||||
DbpString("Mifare Classic 1k");
|
||||
SimulateIso14443aTag(1, flags, data);
|
||||
} else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) {
|
||||
DbpString("Mifare Classic 4k (4b uid)");
|
||||
SimulateIso14443aTag(8, flags, data);
|
||||
} else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) {
|
||||
DbpString("Mifare Classic 4k (7b uid)");
|
||||
SimulateIso14443aTag(8, flags, data);
|
||||
} else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) {
|
||||
DbpString("Mifare Ultralight");
|
||||
SimulateIso14443aTag(2, flags, data);
|
||||
} else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) {
|
||||
DbpString("Mifare DESFire");
|
||||
SimulateIso14443aTag(3, flags, data);
|
||||
} else {
|
||||
Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation");
|
||||
SimulateIso14443aTag(1, flags, data);
|
||||
}
|
||||
if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) {
|
||||
DbpString("Mifare Classic 1k");
|
||||
SimulateIso14443aTag(1, flags, data);
|
||||
} else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) {
|
||||
DbpString("Mifare Classic 4k (4b uid)");
|
||||
SimulateIso14443aTag(8, flags, data);
|
||||
} else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) {
|
||||
DbpString("Mifare Classic 4k (7b uid)");
|
||||
SimulateIso14443aTag(8, flags, data);
|
||||
} else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) {
|
||||
DbpString("Mifare Ultralight");
|
||||
SimulateIso14443aTag(2, flags, data);
|
||||
} else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) {
|
||||
DbpString("Mifare DESFire");
|
||||
SimulateIso14443aTag(3, flags, data);
|
||||
} else {
|
||||
Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation");
|
||||
SimulateIso14443aTag(1, flags, data);
|
||||
}
|
||||
|
||||
} else if (button_action == BUTTON_SINGLE_CLICK) {
|
||||
selected = (selected + 1) % OPTS;
|
||||
Dbprintf("Done playing. Switching to record mode on bank %d", selected);
|
||||
iGotoRecord = 1;
|
||||
break;
|
||||
} else if (button_action == BUTTON_HOLD) {
|
||||
Dbprintf("Playtime over. Begin cloning...");
|
||||
iGotoClone = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (button_action == BUTTON_SINGLE_CLICK) {
|
||||
selected = (selected + 1) % OPTS;
|
||||
Dbprintf("Done playing. Switching to record mode on bank %d", selected);
|
||||
iGotoRecord = 1;
|
||||
break;
|
||||
} else if (button_action == BUTTON_HOLD) {
|
||||
Dbprintf("Playtime over. Begin cloning...");
|
||||
iGotoClone = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
}
|
||||
}
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,296 +28,296 @@
|
|||
|
||||
// samy's sniff and repeat routine for LF
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
Dbprintf(">> LF HID corporate bruteforce a.k.a CorporateBrute Started <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
StandAloneMode();
|
||||
Dbprintf(">> LF HID corporate bruteforce a.k.a CorporateBrute Started <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
uint32_t high[OPTS], low[OPTS];
|
||||
int selected = 0;
|
||||
int playing = 0;
|
||||
int cardRead = 0;
|
||||
uint32_t high[OPTS], low[OPTS];
|
||||
int selected = 0;
|
||||
int playing = 0;
|
||||
int cardRead = 0;
|
||||
|
||||
// Turn on selected LED
|
||||
LED(selected + 1, 0);
|
||||
// Turn on selected LED
|
||||
LED(selected + 1, 0);
|
||||
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
// exit from SamyRun, send a usbcommand.
|
||||
if (usb_poll_validate_length()) break;
|
||||
// exit from SamyRun, send a usbcommand.
|
||||
if (usb_poll_validate_length()) break;
|
||||
|
||||
// Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
SpinDelay(300);
|
||||
// Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
SpinDelay(300);
|
||||
|
||||
// Button was held for a second, begin recording
|
||||
if (button_pressed > 0 && cardRead == 0) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_RED2, 0);
|
||||
// Button was held for a second, begin recording
|
||||
if (button_pressed > 0 && cardRead == 0) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_RED2, 0);
|
||||
|
||||
// record
|
||||
DbpString("[=] starting recording");
|
||||
// record
|
||||
DbpString("[=] starting recording");
|
||||
|
||||
// wait for button to be released
|
||||
while(BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// wait for button to be released
|
||||
while(BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
|
||||
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
|
||||
Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]);
|
||||
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
|
||||
Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 1;
|
||||
}
|
||||
else if (button_pressed > 0 && cardRead == 1) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_ORANGE, 0);
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 1;
|
||||
}
|
||||
else if (button_pressed > 0 && cardRead == 1) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_ORANGE, 0);
|
||||
|
||||
// record
|
||||
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
|
||||
// record
|
||||
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
// wait for button to be released
|
||||
while(BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// wait for button to be released
|
||||
while(BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
|
||||
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
|
||||
Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]);
|
||||
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
|
||||
Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 0;
|
||||
}
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 0;
|
||||
}
|
||||
|
||||
// Change where to record (or begin playing)
|
||||
else if (button_pressed) {
|
||||
// Next option if we were previously playing
|
||||
if (playing)
|
||||
selected = (selected + 1) % OPTS;
|
||||
// Change where to record (or begin playing)
|
||||
else if (button_pressed) {
|
||||
// Next option if we were previously playing
|
||||
if (playing)
|
||||
selected = (selected + 1) % OPTS;
|
||||
|
||||
playing = !playing;
|
||||
playing = !playing;
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
|
||||
// Begin transmitting
|
||||
if (playing && selected != 2) {
|
||||
// Begin transmitting
|
||||
if (playing && selected != 2) {
|
||||
|
||||
LED(LED_GREEN, 0);
|
||||
DbpString("[=] playing");
|
||||
LED(LED_GREEN, 0);
|
||||
DbpString("[=] playing");
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]);
|
||||
CmdHIDsimTAG(high[selected], low[selected], 0);
|
||||
DbpString("[=] done playing");
|
||||
Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]);
|
||||
CmdHIDsimTAG(high[selected], low[selected], 0);
|
||||
DbpString("[=] done playing");
|
||||
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
goto out;
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
goto out;
|
||||
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
|
||||
// when done, we're done playing, move to next option
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
}
|
||||
else if (playing && selected == 2)
|
||||
{
|
||||
// Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID.
|
||||
// It is necessary only to calculate the correct parity.
|
||||
// when done, we're done playing, move to next option
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
}
|
||||
else if (playing && selected == 2)
|
||||
{
|
||||
// Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID.
|
||||
// It is necessary only to calculate the correct parity.
|
||||
|
||||
// Brute force code
|
||||
// Check if the badge is an HID Corporate 1000
|
||||
if( (high[selected] & 0xFFFFFFF8) != 0x28 ) {
|
||||
DbpString("[-] Card is not a HID Corporate 1000. Skipping bruteforce.");
|
||||
continue;
|
||||
}
|
||||
// Brute force code
|
||||
// Check if the badge is an HID Corporate 1000
|
||||
if( (high[selected] & 0xFFFFFFF8) != 0x28 ) {
|
||||
DbpString("[-] Card is not a HID Corporate 1000. Skipping bruteforce.");
|
||||
continue;
|
||||
}
|
||||
|
||||
LED(LED_GREEN, 0);
|
||||
DbpString("[=] entering bruteforce mode");
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
LED(LED_GREEN, 0);
|
||||
DbpString("[=] entering bruteforce mode");
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
// Calculate Facility Code and Card Number from high and low
|
||||
uint32_t cardnum = (low[selected] >> 1) & 0xFFFFF;
|
||||
uint32_t fc = ((high[selected] & 1 ) << 11 ) | (low[selected] >> 21);
|
||||
uint32_t original_cardnum = cardnum;
|
||||
// Calculate Facility Code and Card Number from high and low
|
||||
uint32_t cardnum = (low[selected] >> 1) & 0xFFFFF;
|
||||
uint32_t fc = ((high[selected] & 1 ) << 11 ) | (low[selected] >> 21);
|
||||
uint32_t original_cardnum = cardnum;
|
||||
|
||||
Dbprintf("[=] Proxbrute - starting decrementing card number");
|
||||
Dbprintf("[=] Proxbrute - starting decrementing card number");
|
||||
|
||||
while (cardnum >= 0) {
|
||||
while (cardnum >= 0) {
|
||||
|
||||
// Needed for exiting from proxbrute when button is pressed
|
||||
if (BUTTON_PRESS()) {
|
||||
if (BUTTON_HELD(1000) > 0) {
|
||||
goto out;
|
||||
} else {
|
||||
while (BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Needed for exiting from proxbrute when button is pressed
|
||||
if (BUTTON_PRESS()) {
|
||||
if (BUTTON_HELD(1000) > 0) {
|
||||
goto out;
|
||||
} else {
|
||||
while (BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Decrement Card Number
|
||||
cardnum--;
|
||||
// Decrement Card Number
|
||||
cardnum--;
|
||||
|
||||
// Calculate checksum of HID Corporate 1000 and set card number and facility code in high and low variables
|
||||
hid_corporate_1000_calculate_checksum_and_set(&high[selected], &low[selected], cardnum, fc);
|
||||
// Calculate checksum of HID Corporate 1000 and set card number and facility code in high and low variables
|
||||
hid_corporate_1000_calculate_checksum_and_set(&high[selected], &low[selected], cardnum, fc);
|
||||
|
||||
// Print actual code to brute
|
||||
Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum);
|
||||
// Print actual code to brute
|
||||
Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum);
|
||||
|
||||
CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000);
|
||||
}
|
||||
CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000);
|
||||
}
|
||||
|
||||
cardnum = original_cardnum;
|
||||
cardnum = original_cardnum;
|
||||
|
||||
Dbprintf("[=] Proxbrute - starting incrementing card number");
|
||||
Dbprintf("[=] Proxbrute - starting incrementing card number");
|
||||
|
||||
while (cardnum <= 0xFFFFF) {
|
||||
while (cardnum <= 0xFFFFF) {
|
||||
|
||||
// Needed for exiting from proxbrute when button is pressed
|
||||
if (BUTTON_PRESS()) {
|
||||
if (BUTTON_HELD(1000) > 0) {
|
||||
goto out;
|
||||
} else {
|
||||
while (BUTTON_PRESS()) { WDT_HIT(); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Needed for exiting from proxbrute when button is pressed
|
||||
if (BUTTON_PRESS()) {
|
||||
if (BUTTON_HELD(1000) > 0) {
|
||||
goto out;
|
||||
} else {
|
||||
while (BUTTON_PRESS()) { WDT_HIT(); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Decrement Card Number
|
||||
cardnum++;
|
||||
// Decrement Card Number
|
||||
cardnum++;
|
||||
|
||||
// Calculate checksum of HID Corporate 1000 and set card number and facility code in high and low variables
|
||||
hid_corporate_1000_calculate_checksum_and_set(&high[selected], &low[selected], cardnum, fc);
|
||||
// Calculate checksum of HID Corporate 1000 and set card number and facility code in high and low variables
|
||||
hid_corporate_1000_calculate_checksum_and_set(&high[selected], &low[selected], cardnum, fc);
|
||||
|
||||
// Print actual code to brute
|
||||
Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum);
|
||||
// Print actual code to brute
|
||||
Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum);
|
||||
|
||||
CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000);
|
||||
}
|
||||
CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000);
|
||||
}
|
||||
|
||||
DbpString("[=] done bruteforcing");
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
goto out;
|
||||
DbpString("[=] done bruteforcing");
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
goto out;
|
||||
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
|
||||
// when done, we're done playing, move to next option
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// when done, we're done playing, move to next option
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
|
||||
} else {
|
||||
while(BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while(BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
DbpString("[=] exiting");
|
||||
LEDsoff();
|
||||
DbpString("[=] exiting");
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
// Function that calculate next value for the brutforce of HID corporate 1000
|
||||
void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc) {
|
||||
|
||||
uint32_t new_high = 0;
|
||||
uint32_t new_low = 0;
|
||||
uint32_t new_high = 0;
|
||||
uint32_t new_low = 0;
|
||||
|
||||
// Calculate new high and low base value from card number and facility code, without parity
|
||||
new_low = (fc << 21) | (cardnum << 1);
|
||||
new_high = 0x28 | ((fc >> 11) & 1); // 0x28 is 101000
|
||||
// Calculate new high and low base value from card number and facility code, without parity
|
||||
new_low = (fc << 21) | (cardnum << 1);
|
||||
new_high = 0x28 | ((fc >> 11) & 1); // 0x28 is 101000
|
||||
|
||||
int n_ones;
|
||||
uint32_t i;
|
||||
int n_ones;
|
||||
uint32_t i;
|
||||
|
||||
// Calculating and setting parity bit 34
|
||||
// Select only bit used for parity bit 34 in low number (10110110110110110110110110110110)
|
||||
uint32_t parity_bit_34_low = new_low & 0xB6DB6DB6;
|
||||
n_ones = 0;
|
||||
// Calculate number of ones in low number
|
||||
for ( i = 1; i != 0; i <<= 1) {
|
||||
if( parity_bit_34_low & i )
|
||||
n_ones++;
|
||||
}
|
||||
// Calculate number of ones in high number
|
||||
if (new_high & 1)
|
||||
n_ones++;
|
||||
// Calculating and setting parity bit 34
|
||||
// Select only bit used for parity bit 34 in low number (10110110110110110110110110110110)
|
||||
uint32_t parity_bit_34_low = new_low & 0xB6DB6DB6;
|
||||
n_ones = 0;
|
||||
// Calculate number of ones in low number
|
||||
for ( i = 1; i != 0; i <<= 1) {
|
||||
if( parity_bit_34_low & i )
|
||||
n_ones++;
|
||||
}
|
||||
// Calculate number of ones in high number
|
||||
if (new_high & 1)
|
||||
n_ones++;
|
||||
|
||||
// Set parity bit (Even parity)
|
||||
if (n_ones % 2)
|
||||
new_high = new_high | 0x2;
|
||||
// Set parity bit (Even parity)
|
||||
if (n_ones % 2)
|
||||
new_high = new_high | 0x2;
|
||||
|
||||
// Calculating and setting parity bit 1
|
||||
// Select only bit used for parity bit 1 in low number (01101101101101101101101101101100)
|
||||
uint32_t parity_bit_1_low = new_low & 0x6DB6DB6C;
|
||||
n_ones = 0;
|
||||
// Calculating and setting parity bit 1
|
||||
// Select only bit used for parity bit 1 in low number (01101101101101101101101101101100)
|
||||
uint32_t parity_bit_1_low = new_low & 0x6DB6DB6C;
|
||||
n_ones = 0;
|
||||
|
||||
// Calculate number of ones in low number
|
||||
for ( i=1; i != 0; i <<= 1) {
|
||||
if( parity_bit_1_low & i )
|
||||
n_ones++;
|
||||
}
|
||||
// Calculate number of ones in high number
|
||||
if ( new_high & 0x1)
|
||||
n_ones++;
|
||||
// Calculate number of ones in low number
|
||||
for ( i=1; i != 0; i <<= 1) {
|
||||
if( parity_bit_1_low & i )
|
||||
n_ones++;
|
||||
}
|
||||
// Calculate number of ones in high number
|
||||
if ( new_high & 0x1)
|
||||
n_ones++;
|
||||
|
||||
if ( new_high & 0x2)
|
||||
n_ones++;
|
||||
if ( new_high & 0x2)
|
||||
n_ones++;
|
||||
|
||||
// Set parity bit (Odd parity)
|
||||
if (!(n_ones % 2))
|
||||
new_low = new_low | 0x1;
|
||||
// Set parity bit (Odd parity)
|
||||
if (!(n_ones % 2))
|
||||
new_low = new_low | 0x1;
|
||||
|
||||
// Calculating and setting parity bit 35
|
||||
n_ones = 0;
|
||||
// Calculate number of ones in low number (all bit of low, bitmask unnecessary)
|
||||
for (i = 1; i != 0; i <<= 1) {
|
||||
if ( new_low & i )
|
||||
n_ones++;
|
||||
}
|
||||
// Calculate number of ones in high number
|
||||
if ( new_high & 0x1)
|
||||
n_ones++;
|
||||
// Calculating and setting parity bit 35
|
||||
n_ones = 0;
|
||||
// Calculate number of ones in low number (all bit of low, bitmask unnecessary)
|
||||
for (i = 1; i != 0; i <<= 1) {
|
||||
if ( new_low & i )
|
||||
n_ones++;
|
||||
}
|
||||
// Calculate number of ones in high number
|
||||
if ( new_high & 0x1)
|
||||
n_ones++;
|
||||
|
||||
if ( new_high & 0x2)
|
||||
n_ones++;
|
||||
if ( new_high & 0x2)
|
||||
n_ones++;
|
||||
|
||||
// Set parity bit (Odd parity)
|
||||
if (!(n_ones % 2))
|
||||
new_high = new_high | 0x4;
|
||||
// Set parity bit (Odd parity)
|
||||
if (!(n_ones % 2))
|
||||
new_high = new_high | 0x4;
|
||||
|
||||
// Setting new calculated values
|
||||
*low = new_low;
|
||||
*high = new_high;
|
||||
// Setting new calculated values
|
||||
*low = new_low;
|
||||
*high = new_high;
|
||||
}
|
||||
|
||||
// prepare a waveform pattern in the buffer based on the ID given then
|
||||
|
|
|
@ -13,157 +13,157 @@
|
|||
|
||||
// samy's sniff and repeat routine for LF
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
StandAloneMode();
|
||||
Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
uint32_t high[OPTS], low[OPTS];
|
||||
int selected = 0;
|
||||
int playing = 0;
|
||||
int cardRead = 0;
|
||||
uint32_t high[OPTS], low[OPTS];
|
||||
int selected = 0;
|
||||
int playing = 0;
|
||||
int cardRead = 0;
|
||||
|
||||
// Turn on selected LED
|
||||
LED(selected + 1, 0);
|
||||
// Turn on selected LED
|
||||
LED(selected + 1, 0);
|
||||
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
// exit from SamyRun, send a usbcommand.
|
||||
if (usb_poll_validate_length()) break;
|
||||
// exit from SamyRun, send a usbcommand.
|
||||
if (usb_poll_validate_length()) break;
|
||||
|
||||
// Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
SpinDelay(300);
|
||||
// Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
SpinDelay(300);
|
||||
|
||||
// Button was held for a second, begin recording
|
||||
if (button_pressed > 0 && cardRead == 0) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_RED2, 0);
|
||||
// Button was held for a second, begin recording
|
||||
if (button_pressed > 0 && cardRead == 0) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_RED2, 0);
|
||||
|
||||
// record
|
||||
DbpString("[=] starting recording");
|
||||
// record
|
||||
DbpString("[=] starting recording");
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
|
||||
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
|
||||
Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]);
|
||||
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
|
||||
Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 1;
|
||||
}
|
||||
else if (button_pressed > 0 && cardRead == 1) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_ORANGE, 0);
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 1;
|
||||
}
|
||||
else if (button_pressed > 0 && cardRead == 1) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_ORANGE, 0);
|
||||
|
||||
// record
|
||||
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
|
||||
// record
|
||||
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
|
||||
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
|
||||
Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]);
|
||||
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
|
||||
Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 0;
|
||||
}
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 0;
|
||||
}
|
||||
|
||||
// Change where to record (or begin playing)
|
||||
else if (button_pressed) {
|
||||
// Next option if we were previously playing
|
||||
if (playing)
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
// Change where to record (or begin playing)
|
||||
else if (button_pressed) {
|
||||
// Next option if we were previously playing
|
||||
if (playing)
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
|
||||
// Begin transmitting
|
||||
if (playing) {
|
||||
LED(LED_GREEN, 0);
|
||||
DbpString("[=] playing");
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// Begin transmitting
|
||||
if (playing) {
|
||||
LED(LED_GREEN, 0);
|
||||
DbpString("[=] playing");
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* START PROXBRUTE */
|
||||
/* START PROXBRUTE */
|
||||
|
||||
/*
|
||||
ProxBrute - brad a. - foundstone
|
||||
/*
|
||||
ProxBrute - brad a. - foundstone
|
||||
|
||||
Following code is a trivial brute forcer once you read a valid tag
|
||||
the idea is you get a valid tag, then just try and brute force to
|
||||
another priv level. The problem is that it has no idea if the code
|
||||
worked or not, so its a crap shoot. One option is to time how long
|
||||
it takes to get a valid ID then start from scratch every time.
|
||||
*/
|
||||
if ( selected == 1 ) {
|
||||
DbpString("[=] entering ProxBrute Mode");
|
||||
Dbprintf("[=] current Tag: Selected = %x Facility = %08x ID = %08x", selected, high[selected], low[selected]);
|
||||
LED(LED_ORANGE, 0);
|
||||
LED(LED_RED, 0);
|
||||
for (uint16_t i = low[selected]-1; i > 0; i--) {
|
||||
if (BUTTON_PRESS()) {
|
||||
DbpString("[-] told to stop");
|
||||
break;
|
||||
}
|
||||
Following code is a trivial brute forcer once you read a valid tag
|
||||
the idea is you get a valid tag, then just try and brute force to
|
||||
another priv level. The problem is that it has no idea if the code
|
||||
worked or not, so its a crap shoot. One option is to time how long
|
||||
it takes to get a valid ID then start from scratch every time.
|
||||
*/
|
||||
if ( selected == 1 ) {
|
||||
DbpString("[=] entering ProxBrute Mode");
|
||||
Dbprintf("[=] current Tag: Selected = %x Facility = %08x ID = %08x", selected, high[selected], low[selected]);
|
||||
LED(LED_ORANGE, 0);
|
||||
LED(LED_RED, 0);
|
||||
for (uint16_t i = low[selected]-1; i > 0; i--) {
|
||||
if (BUTTON_PRESS()) {
|
||||
DbpString("[-] told to stop");
|
||||
break;
|
||||
}
|
||||
|
||||
Dbprintf("[=] trying Facility = %08x ID %08x", high[selected], i);
|
||||
CmdHIDsimTAGEx(high[selected], i, 0, 20000);
|
||||
SpinDelay(500);
|
||||
}
|
||||
Dbprintf("[=] trying Facility = %08x ID %08x", high[selected], i);
|
||||
CmdHIDsimTAGEx(high[selected], i, 0, 20000);
|
||||
SpinDelay(500);
|
||||
}
|
||||
|
||||
} else {
|
||||
DbpString("[=] RED is lit, not entering ProxBrute Mode");
|
||||
Dbprintf("[=] %x %x %x", selected, high[selected], low[selected]);
|
||||
CmdHIDsimTAGEx(high[selected], low[selected], 0, 20000);
|
||||
DbpString("[=] done playing");
|
||||
}
|
||||
} else {
|
||||
DbpString("[=] RED is lit, not entering ProxBrute Mode");
|
||||
Dbprintf("[=] %x %x %x", selected, high[selected], low[selected]);
|
||||
CmdHIDsimTAGEx(high[selected], low[selected], 0, 20000);
|
||||
DbpString("[=] done playing");
|
||||
}
|
||||
|
||||
/* END PROXBRUTE */
|
||||
/* END PROXBRUTE */
|
||||
|
||||
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
goto out;
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
goto out;
|
||||
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
|
||||
// when done, we're done playing, move to next option
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
}
|
||||
else {
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
}
|
||||
// when done, we're done playing, move to next option
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
}
|
||||
else {
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
DbpString("[=] exiting");
|
||||
LEDsoff();
|
||||
DbpString("[=] exiting");
|
||||
LEDsoff();
|
||||
}
|
|
@ -12,132 +12,132 @@
|
|||
|
||||
// samy's sniff and repeat routine for LF
|
||||
void RunMod() {
|
||||
StandAloneMode();
|
||||
Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
StandAloneMode();
|
||||
Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
uint32_t high[OPTS], low[OPTS];
|
||||
int selected = 0;
|
||||
int playing = 0;
|
||||
int cardRead = 0;
|
||||
bool gotCard;
|
||||
// Turn on selected LED
|
||||
LED(selected + 1, 0);
|
||||
uint32_t high[OPTS], low[OPTS];
|
||||
int selected = 0;
|
||||
int playing = 0;
|
||||
int cardRead = 0;
|
||||
bool gotCard;
|
||||
// Turn on selected LED
|
||||
LED(selected + 1, 0);
|
||||
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
// exit from SamyRun, send a usbcommand.
|
||||
if (usb_poll_validate_length()) break;
|
||||
// exit from SamyRun, send a usbcommand.
|
||||
if (usb_poll_validate_length()) break;
|
||||
|
||||
// Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
// Was our button held down or pressed?
|
||||
int button_pressed = BUTTON_HELD(1000);
|
||||
|
||||
Dbprintf("button %d", button_pressed);
|
||||
SpinDelay(300);
|
||||
Dbprintf("button %d", button_pressed);
|
||||
SpinDelay(300);
|
||||
|
||||
// Button was held for a second, begin recording
|
||||
if (button_pressed > 0 && cardRead == 0) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_RED2, 0);
|
||||
// Button was held for a second, begin recording
|
||||
if (button_pressed > 0 && cardRead == 0) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_RED2, 0);
|
||||
|
||||
// record
|
||||
DbpString("[=] starting recording");
|
||||
// record
|
||||
DbpString("[=] starting recording");
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
|
||||
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
|
||||
Dbprintf("[=] recorded bank %x | %x %08x", selected, high[selected], low[selected]);
|
||||
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
|
||||
Dbprintf("[=] recorded bank %x | %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 1;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 1;
|
||||
|
||||
gotCard = true;
|
||||
}
|
||||
else if (button_pressed > 0 && cardRead == 1) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_ORANGE, 0);
|
||||
gotCard = true;
|
||||
}
|
||||
else if (button_pressed > 0 && cardRead == 1) {
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LED(LED_ORANGE, 0);
|
||||
|
||||
// record
|
||||
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
|
||||
// record
|
||||
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
/* need this delay to prevent catching some weird data */
|
||||
SpinDelay(500);
|
||||
|
||||
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
|
||||
Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]);
|
||||
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
|
||||
Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]);
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
// Finished recording
|
||||
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 0;
|
||||
}
|
||||
// If we were previously playing, set playing off
|
||||
// so next button push begins playing what we recorded
|
||||
playing = 0;
|
||||
cardRead = 0;
|
||||
}
|
||||
|
||||
// Change where to record (or begin playing)
|
||||
else if (button_pressed && gotCard) {
|
||||
// Next option if we were previously playing
|
||||
if (playing)
|
||||
selected = (selected + 1) % OPTS;
|
||||
// Change where to record (or begin playing)
|
||||
else if (button_pressed && gotCard) {
|
||||
// Next option if we were previously playing
|
||||
if (playing)
|
||||
selected = (selected + 1) % OPTS;
|
||||
|
||||
playing = !playing;
|
||||
playing = !playing;
|
||||
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
|
||||
// Begin transmitting
|
||||
if (playing) {
|
||||
// Begin transmitting
|
||||
if (playing) {
|
||||
|
||||
LED(LED_GREEN, 0);
|
||||
DbpString("[=] playing");
|
||||
LED(LED_GREEN, 0);
|
||||
DbpString("[=] playing");
|
||||
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
// wait for button to be released
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
|
||||
Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]);
|
||||
CmdHIDsimTAG(high[selected], low[selected], false);
|
||||
DbpString("[=] done playing");
|
||||
Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]);
|
||||
CmdHIDsimTAG(high[selected], low[selected], false);
|
||||
DbpString("[=] done playing");
|
||||
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
goto out;
|
||||
if (BUTTON_HELD(1000) > 0)
|
||||
goto out;
|
||||
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
/* We pressed a button so ignore it here with a delay */
|
||||
SpinDelay(300);
|
||||
|
||||
// when done, we're done playing, move to next option
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
}
|
||||
else {
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
}
|
||||
// when done, we're done playing, move to next option
|
||||
selected = (selected + 1) % OPTS;
|
||||
playing = !playing;
|
||||
LEDsoff();
|
||||
LED(selected + 1, 0);
|
||||
}
|
||||
else {
|
||||
while (BUTTON_PRESS())
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
DbpString("[=] exiting");
|
||||
LEDsoff();
|
||||
DbpString("[=] exiting");
|
||||
LEDsoff();
|
||||
}
|
|
@ -11,19 +11,19 @@ Each standalone mod needs to have its own compiler flag to be added in `armsrc\m
|
|||
The RunMod function is your "main" function when running. You need to check for Usb commands, in order to let the pm3 client break the standalone mode. See this basic skeleton of main function RunMod().
|
||||
````
|
||||
void RunMod() {
|
||||
// led show
|
||||
StandAloneMode();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
// led show
|
||||
StandAloneMode();
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
// main loop
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
// exit from standalone mode, just send a usbcommand
|
||||
if (usb_poll_validate_length()) break;
|
||||
|
||||
// do your standalone stuff..
|
||||
}
|
||||
// main loop
|
||||
for (;;) {
|
||||
WDT_HIT();
|
||||
|
||||
// exit from standalone mode, just send a usbcommand
|
||||
if (usb_poll_validate_length()) break;
|
||||
|
||||
// do your standalone stuff..
|
||||
}
|
||||
````
|
||||
|
||||
As it is now, you can only have one standalone mode installed at the time.
|
||||
|
@ -47,9 +47,9 @@ Add your source code file like the following sample in the `armsrc\makefile`
|
|||
```
|
||||
# WITH_HF_COLIN
|
||||
ifneq (,$(findstring WITH_HF_COLIN,$(APP_CFLAGS)))
|
||||
SRC_STANDALONE = hf_colin.c vtsend.c
|
||||
SRC_STANDALONE = hf_colin.c vtsend.c
|
||||
else
|
||||
SRC_STANDALONE =
|
||||
SRC_STANDALONE =
|
||||
endif
|
||||
```
|
||||
|
||||
|
@ -67,36 +67,36 @@ Once all this is done, you and others can now easily compile different standalon
|
|||
````
|
||||
#remove one of the following defines and comment out the relevant line
|
||||
#in the next section to remove that particular feature from compilation.
|
||||
# NO space,TABs after the "\" sign.
|
||||
# NO space,TABs after the "\" sign.
|
||||
APP_CFLAGS = -DWITH_CRC \
|
||||
-DON_DEVICE \
|
||||
-DWITH_LF \
|
||||
-DWITH_HITAG \
|
||||
-DWITH_ISO15693 \
|
||||
-DWITH_LEGICRF \
|
||||
-DWITH_ISO14443b \
|
||||
-DWITH_ISO14443a \
|
||||
-DWITH_ICLASS \
|
||||
-DWITH_FELICA \
|
||||
-DWITH_FLASH \
|
||||
-DWITH_SMARTCARD \
|
||||
-DWITH_HFSNOOP \
|
||||
-DWITH_HF_COLIN\
|
||||
-DWITH_FPC \
|
||||
-fno-strict-aliasing -ffunction-sections -fdata-sections
|
||||
-DON_DEVICE \
|
||||
-DWITH_LF \
|
||||
-DWITH_HITAG \
|
||||
-DWITH_ISO15693 \
|
||||
-DWITH_LEGICRF \
|
||||
-DWITH_ISO14443b \
|
||||
-DWITH_ISO14443a \
|
||||
-DWITH_ICLASS \
|
||||
-DWITH_FELICA \
|
||||
-DWITH_FLASH \
|
||||
-DWITH_SMARTCARD \
|
||||
-DWITH_HFSNOOP \
|
||||
-DWITH_HF_COLIN\
|
||||
-DWITH_FPC \
|
||||
-fno-strict-aliasing -ffunction-sections -fdata-sections
|
||||
|
||||
### IMPORTANT - move the commented variable below this line
|
||||
# -DWITH_LCD \
|
||||
# -DWITH_EMV \
|
||||
# -DWITH_FPC \
|
||||
# -DWITH_LCD \
|
||||
# -DWITH_EMV \
|
||||
# -DWITH_FPC \
|
||||
#
|
||||
# Standalone Mods
|
||||
#-------------------------------------------------------
|
||||
# -DWITH_LF_ICERUN
|
||||
# -DWITH_LF_SAMYRUN
|
||||
# -DWITH_LF_PROXBRUTE
|
||||
# -DWITH_LF_HIDBRUTE
|
||||
# -DWITH_HF_YOUNG
|
||||
# -DWITH_HF_MATTYRUN
|
||||
# -DWITH_HF_COLIN
|
||||
# -DWITH_LF_ICERUN
|
||||
# -DWITH_LF_SAMYRUN
|
||||
# -DWITH_LF_PROXBRUTE
|
||||
# -DWITH_LF_HIDBRUTE
|
||||
# -DWITH_HF_YOUNG
|
||||
# -DWITH_HF_MATTYRUN
|
||||
# -DWITH_HF_COLIN
|
||||
````
|
||||
|
|
|
@ -11,8 +11,8 @@ import matplotlib.pyplot as plt
|
|||
import sys
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print "Usage: %s <basename>" % sys.argv[0]
|
||||
sys.exit(1)
|
||||
print "Usage: %s <basename>" % sys.argv[0]
|
||||
sys.exit(1)
|
||||
|
||||
BASENAME = sys.argv[1]
|
||||
|
||||
|
|
34
proxmark3.sh
34
proxmark3.sh
|
@ -1,26 +1,26 @@
|
|||
#!/bin/bash
|
||||
|
||||
function wait4proxmark_Linux {
|
||||
echo >&2 "Waiting for Proxmark to appear..."
|
||||
while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do
|
||||
sleep .1
|
||||
done
|
||||
local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1`
|
||||
echo >&2 -e "Found proxmark on ${PM3}\n"
|
||||
echo $PM3
|
||||
echo >&2 "Waiting for Proxmark to appear..."
|
||||
while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do
|
||||
sleep .1
|
||||
done
|
||||
local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1`
|
||||
echo >&2 -e "Found proxmark on ${PM3}\n"
|
||||
echo $PM3
|
||||
}
|
||||
|
||||
function wait4proxmark_macOS {
|
||||
echo >&2 "Waiting for Proxmark to appear..."
|
||||
while true; do
|
||||
PM3=$(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)
|
||||
if [[ $PM3 != "" ]]; then
|
||||
#echo >&2 -e "Found proxmark on $(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)\n"
|
||||
break
|
||||
fi
|
||||
sleep .1
|
||||
done
|
||||
echo $PM3
|
||||
echo >&2 "Waiting for Proxmark to appear..."
|
||||
while true; do
|
||||
PM3=$(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)
|
||||
if [[ $PM3 != "" ]]; then
|
||||
#echo >&2 -e "Found proxmark on $(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)\n"
|
||||
break
|
||||
fi
|
||||
sleep .1
|
||||
done
|
||||
echo $PM3
|
||||
}
|
||||
|
||||
# start proxmark with first detected interface
|
||||
|
|
|
@ -44,11 +44,11 @@
|
|||
|
||||
|
||||
#if defined (_WIN32)
|
||||
#define SERIAL_PORT_H "com3"
|
||||
#define SERIAL_PORT_H "com3"
|
||||
#elif defined(__APPLE__)
|
||||
#define SERIAL_PORT_H "/dev/cu.usbmodem"
|
||||
#else
|
||||
#define SERIAL_PORT_H "/dev/ttyACM0"
|
||||
#define SERIAL_PORT_H "/dev/ttyACM0"
|
||||
#endif
|
||||
|
||||
/* serial_port is declared as a void*, which you should cast to whatever type
|
||||
|
|
|
@ -62,363 +62,363 @@
|
|||
|
||||
typedef struct termios term_info;
|
||||
typedef struct {
|
||||
int fd; // Serial port file descriptor
|
||||
term_info tiOld; // Terminal info before using the port
|
||||
term_info tiNew; // Terminal info during the transaction
|
||||
int fd; // Serial port file descriptor
|
||||
term_info tiOld; // Terminal info before using the port
|
||||
term_info tiNew; // Terminal info during the transaction
|
||||
} serial_port_unix;
|
||||
|
||||
// Set time-out on 30 miliseconds
|
||||
struct timeval timeout = {
|
||||
.tv_sec = 0, // 0 second
|
||||
.tv_usec = 30000 // 30 000 micro seconds
|
||||
.tv_sec = 0, // 0 second
|
||||
.tv_usec = 30000 // 30 000 micro seconds
|
||||
};
|
||||
|
||||
serial_port uart_open(const char* pcPortName) {
|
||||
serial_port_unix* sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t));
|
||||
if (sp == 0) return INVALID_SERIAL_PORT;
|
||||
serial_port_unix* sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t));
|
||||
if (sp == 0) return INVALID_SERIAL_PORT;
|
||||
|
||||
if (memcmp(pcPortName, "tcp:", 4) == 0) {
|
||||
struct addrinfo *addr, *rp;
|
||||
char *addrstr = strdup(pcPortName + 4);
|
||||
if (memcmp(pcPortName, "tcp:", 4) == 0) {
|
||||
struct addrinfo *addr, *rp;
|
||||
char *addrstr = strdup(pcPortName + 4);
|
||||
|
||||
if (addrstr == NULL) {
|
||||
printf("Error: strdup\n");
|
||||
free(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
if (addrstr == NULL) {
|
||||
printf("Error: strdup\n");
|
||||
free(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
timeout.tv_usec = 300000; // 300 000 micro seconds
|
||||
timeout.tv_usec = 300000; // 300 000 micro seconds
|
||||
|
||||
char *colon = strrchr(addrstr, ':');
|
||||
char *portstr;
|
||||
if (colon) {
|
||||
portstr = colon + 1;
|
||||
*colon = '\0';
|
||||
} else {
|
||||
portstr = "7901";
|
||||
}
|
||||
char *colon = strrchr(addrstr, ':');
|
||||
char *portstr;
|
||||
if (colon) {
|
||||
portstr = colon + 1;
|
||||
*colon = '\0';
|
||||
} else {
|
||||
portstr = "7901";
|
||||
}
|
||||
|
||||
int s = getaddrinfo(addrstr, portstr, NULL, &addr);
|
||||
if (s != 0) {
|
||||
printf("Error: getaddrinfo: %s\n", gai_strerror(s));
|
||||
freeaddrinfo(addr);
|
||||
free(addrstr);
|
||||
free(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
int s = getaddrinfo(addrstr, portstr, NULL, &addr);
|
||||
if (s != 0) {
|
||||
printf("Error: getaddrinfo: %s\n", gai_strerror(s));
|
||||
freeaddrinfo(addr);
|
||||
free(addrstr);
|
||||
free(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
int sfd;
|
||||
for (rp = addr; rp != NULL; rp = rp->ai_next) {
|
||||
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||
int sfd;
|
||||
for (rp = addr; rp != NULL; rp = rp->ai_next) {
|
||||
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||
|
||||
if (sfd == -1)
|
||||
continue;
|
||||
if (sfd == -1)
|
||||
continue;
|
||||
|
||||
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
|
||||
break;
|
||||
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
|
||||
break;
|
||||
|
||||
close(sfd);
|
||||
}
|
||||
close(sfd);
|
||||
}
|
||||
|
||||
if (rp == NULL) { /* No address succeeded */
|
||||
printf("Error: Could not connect\n");
|
||||
freeaddrinfo(addr);
|
||||
free(addrstr);
|
||||
free(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
if (rp == NULL) { /* No address succeeded */
|
||||
printf("Error: Could not connect\n");
|
||||
freeaddrinfo(addr);
|
||||
free(addrstr);
|
||||
free(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
freeaddrinfo(addr);
|
||||
free(addrstr);
|
||||
freeaddrinfo(addr);
|
||||
free(addrstr);
|
||||
|
||||
sp->fd = sfd;
|
||||
sp->fd = sfd;
|
||||
|
||||
int one = 1;
|
||||
int res = setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
|
||||
if ( res != 0) {
|
||||
free(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
int one = 1;
|
||||
int res = setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
|
||||
if ( res != 0) {
|
||||
free(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
|
||||
sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
|
||||
if (sp->fd == -1) {
|
||||
uart_close(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
|
||||
if (sp->fd == -1) {
|
||||
uart_close(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
// Finally figured out a way to claim a serial port interface under unix
|
||||
// We just try to set a (advisory) lock on the file descriptor
|
||||
struct flock fl;
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = getpid();
|
||||
// Finally figured out a way to claim a serial port interface under unix
|
||||
// We just try to set a (advisory) lock on the file descriptor
|
||||
struct flock fl;
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = getpid();
|
||||
|
||||
// Does the system allows us to place a lock on this file descriptor
|
||||
if (fcntl(sp->fd, F_SETLK, &fl) == -1) {
|
||||
// A conflicting lock is held by another process
|
||||
free(sp);
|
||||
return CLAIMED_SERIAL_PORT;
|
||||
}
|
||||
// Does the system allows us to place a lock on this file descriptor
|
||||
if (fcntl(sp->fd, F_SETLK, &fl) == -1) {
|
||||
// A conflicting lock is held by another process
|
||||
free(sp);
|
||||
return CLAIMED_SERIAL_PORT;
|
||||
}
|
||||
|
||||
// Try to retrieve the old (current) terminal info struct
|
||||
if (tcgetattr(sp->fd,&sp->tiOld) == -1) {
|
||||
uart_close(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
// Try to retrieve the old (current) terminal info struct
|
||||
if (tcgetattr(sp->fd,&sp->tiOld) == -1) {
|
||||
uart_close(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
// Duplicate the (old) terminal info struct
|
||||
sp->tiNew = sp->tiOld;
|
||||
// Duplicate the (old) terminal info struct
|
||||
sp->tiNew = sp->tiOld;
|
||||
|
||||
// Configure the serial port
|
||||
sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD;
|
||||
sp->tiNew.c_iflag = IGNPAR;
|
||||
sp->tiNew.c_oflag = 0;
|
||||
sp->tiNew.c_lflag = 0;
|
||||
// Configure the serial port
|
||||
sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD;
|
||||
sp->tiNew.c_iflag = IGNPAR;
|
||||
sp->tiNew.c_oflag = 0;
|
||||
sp->tiNew.c_lflag = 0;
|
||||
|
||||
// Block until n bytes are received
|
||||
sp->tiNew.c_cc[VMIN] = 0;
|
||||
// Block until a timer expires (n * 100 mSec.)
|
||||
sp->tiNew.c_cc[VTIME] = 0;
|
||||
// Block until n bytes are received
|
||||
sp->tiNew.c_cc[VMIN] = 0;
|
||||
// Block until a timer expires (n * 100 mSec.)
|
||||
sp->tiNew.c_cc[VTIME] = 0;
|
||||
|
||||
// Try to set the new terminal info struct
|
||||
if (tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) {
|
||||
uart_close(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
// Try to set the new terminal info struct
|
||||
if (tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) {
|
||||
uart_close(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
// Flush all lingering data that may exist
|
||||
tcflush(sp->fd, TCIOFLUSH);
|
||||
|
||||
#ifdef WITH_FPC
|
||||
if ( uart_set_speed(sp, 115200) ) {
|
||||
printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n");
|
||||
} else {
|
||||
uart_set_speed(sp, 9600);
|
||||
printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n");
|
||||
}
|
||||
if ( uart_set_speed(sp, 115200) ) {
|
||||
printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n");
|
||||
} else {
|
||||
uart_set_speed(sp, 9600);
|
||||
printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n");
|
||||
}
|
||||
#else
|
||||
// set speed, works for UBUNTU 14.04
|
||||
bool success = uart_set_speed(sp, 460800);
|
||||
if (success) {
|
||||
printf("[=] UART Setting serial baudrate 460800\n");
|
||||
} else {
|
||||
uart_set_speed(sp, 115200);
|
||||
printf("[=] UART Setting serial baudrate 115200\n");
|
||||
}
|
||||
// set speed, works for UBUNTU 14.04
|
||||
bool success = uart_set_speed(sp, 460800);
|
||||
if (success) {
|
||||
printf("[=] UART Setting serial baudrate 460800\n");
|
||||
} else {
|
||||
uart_set_speed(sp, 115200);
|
||||
printf("[=] UART Setting serial baudrate 115200\n");
|
||||
}
|
||||
#endif
|
||||
return sp;
|
||||
return sp;
|
||||
}
|
||||
|
||||
void uart_close(const serial_port sp) {
|
||||
serial_port_unix* spu = (serial_port_unix*)sp;
|
||||
tcflush(spu->fd, TCIOFLUSH);
|
||||
tcsetattr(spu->fd, TCSANOW, &(spu->tiOld));
|
||||
struct flock fl;
|
||||
fl.l_type = F_UNLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = getpid();
|
||||
serial_port_unix* spu = (serial_port_unix*)sp;
|
||||
tcflush(spu->fd, TCIOFLUSH);
|
||||
tcsetattr(spu->fd, TCSANOW, &(spu->tiOld));
|
||||
struct flock fl;
|
||||
fl.l_type = F_UNLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = getpid();
|
||||
|
||||
// Does the system allows us to place a lock on this file descriptor
|
||||
int err = fcntl(spu->fd, F_SETLK, &fl);
|
||||
if ( err == -1) {
|
||||
//perror("fcntl");
|
||||
}
|
||||
close(spu->fd);
|
||||
free(sp);
|
||||
// Does the system allows us to place a lock on this file descriptor
|
||||
int err = fcntl(spu->fd, F_SETLK, &fl);
|
||||
if ( err == -1) {
|
||||
//perror("fcntl");
|
||||
}
|
||||
close(spu->fd);
|
||||
free(sp);
|
||||
}
|
||||
|
||||
bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) {
|
||||
int res;
|
||||
int byteCount;
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
int res;
|
||||
int byteCount;
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
|
||||
// Reset the output count
|
||||
*pszRxLen = 0;
|
||||
// Reset the output count
|
||||
*pszRxLen = 0;
|
||||
|
||||
do {
|
||||
// Reset file descriptor
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(((serial_port_unix*)sp)->fd, &rfds);
|
||||
tv = timeout;
|
||||
res = select(((serial_port_unix*)sp)->fd + 1, &rfds, NULL, NULL, &tv);
|
||||
do {
|
||||
// Reset file descriptor
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(((serial_port_unix*)sp)->fd, &rfds);
|
||||
tv = timeout;
|
||||
res = select(((serial_port_unix*)sp)->fd + 1, &rfds, NULL, NULL, &tv);
|
||||
|
||||
// Read error
|
||||
if (res < 0) {
|
||||
return false;
|
||||
}
|
||||
// Read error
|
||||
if (res < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read time-out
|
||||
if (res == 0) {
|
||||
if (*pszRxLen == 0) {
|
||||
// Error, we received no data
|
||||
return false;
|
||||
} else {
|
||||
// We received some data, but nothing more is available
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Read time-out
|
||||
if (res == 0) {
|
||||
if (*pszRxLen == 0) {
|
||||
// Error, we received no data
|
||||
return false;
|
||||
} else {
|
||||
// We received some data, but nothing more is available
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the count of the incoming bytes
|
||||
res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount);
|
||||
if (res < 0) return false;
|
||||
// Retrieve the count of the incoming bytes
|
||||
res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount);
|
||||
if (res < 0) return false;
|
||||
|
||||
// Cap the number of bytes, so we don't overrun the buffer
|
||||
if (pszMaxRxLen - (*pszRxLen) < byteCount) {
|
||||
byteCount = pszMaxRxLen - (*pszRxLen);
|
||||
}
|
||||
// Cap the number of bytes, so we don't overrun the buffer
|
||||
if (pszMaxRxLen - (*pszRxLen) < byteCount) {
|
||||
byteCount = pszMaxRxLen - (*pszRxLen);
|
||||
}
|
||||
|
||||
// There is something available, read the data
|
||||
res = read(((serial_port_unix*)sp)->fd, pbtRx + (*pszRxLen), byteCount);
|
||||
// There is something available, read the data
|
||||
res = read(((serial_port_unix*)sp)->fd, pbtRx + (*pszRxLen), byteCount);
|
||||
|
||||
// Stop if the OS has some troubles reading the data
|
||||
if (res <= 0) return false;
|
||||
// Stop if the OS has some troubles reading the data
|
||||
if (res <= 0) return false;
|
||||
|
||||
*pszRxLen += res;
|
||||
*pszRxLen += res;
|
||||
|
||||
if (*pszRxLen == pszMaxRxLen) {
|
||||
// We have all the data we wanted.
|
||||
return true;
|
||||
}
|
||||
if (*pszRxLen == pszMaxRxLen) {
|
||||
// We have all the data we wanted.
|
||||
return true;
|
||||
}
|
||||
|
||||
} while (byteCount);
|
||||
} while (byteCount);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t len) {
|
||||
int32_t res;
|
||||
size_t pos = 0;
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
int32_t res;
|
||||
size_t pos = 0;
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
|
||||
while (pos < len) {
|
||||
// Reset file descriptor
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(((serial_port_unix*)sp)->fd, &rfds);
|
||||
tv = timeout;
|
||||
res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv);
|
||||
while (pos < len) {
|
||||
// Reset file descriptor
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(((serial_port_unix*)sp)->fd, &rfds);
|
||||
tv = timeout;
|
||||
res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv);
|
||||
|
||||
// Write error
|
||||
if (res < 0) {
|
||||
printf("UART:: write error (%d)\n", res);
|
||||
return false;
|
||||
}
|
||||
// Write error
|
||||
if (res < 0) {
|
||||
printf("UART:: write error (%d)\n", res);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write time-out
|
||||
if (res == 0) {
|
||||
printf("UART:: write time-out\n");
|
||||
return false;
|
||||
}
|
||||
// Write time-out
|
||||
if (res == 0) {
|
||||
printf("UART:: write time-out\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send away the bytes
|
||||
res = write(((serial_port_unix*)sp)->fd, pbtTx + pos, len - pos);
|
||||
// Send away the bytes
|
||||
res = write(((serial_port_unix*)sp)->fd, pbtTx + pos, len - pos);
|
||||
|
||||
// Stop if the OS has some troubles sending the data
|
||||
if (res <= 0) return false;
|
||||
// Stop if the OS has some troubles sending the data
|
||||
if (res <= 0) return false;
|
||||
|
||||
pos += res;
|
||||
}
|
||||
return true;
|
||||
pos += res;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {
|
||||
const serial_port_unix* spu = (serial_port_unix*)sp;
|
||||
speed_t stPortSpeed;
|
||||
switch (uiPortSpeed) {
|
||||
case 0: stPortSpeed = B0; break;
|
||||
case 50: stPortSpeed = B50; break;
|
||||
case 75: stPortSpeed = B75; break;
|
||||
case 110: stPortSpeed = B110; break;
|
||||
case 134: stPortSpeed = B134; break;
|
||||
case 150: stPortSpeed = B150; break;
|
||||
case 300: stPortSpeed = B300; break;
|
||||
case 600: stPortSpeed = B600; break;
|
||||
case 1200: stPortSpeed = B1200; break;
|
||||
case 1800: stPortSpeed = B1800; break;
|
||||
case 2400: stPortSpeed = B2400; break;
|
||||
case 4800: stPortSpeed = B4800; break;
|
||||
case 9600: stPortSpeed = B9600; break;
|
||||
case 19200: stPortSpeed = B19200; break;
|
||||
case 38400: stPortSpeed = B38400; break;
|
||||
const serial_port_unix* spu = (serial_port_unix*)sp;
|
||||
speed_t stPortSpeed;
|
||||
switch (uiPortSpeed) {
|
||||
case 0: stPortSpeed = B0; break;
|
||||
case 50: stPortSpeed = B50; break;
|
||||
case 75: stPortSpeed = B75; break;
|
||||
case 110: stPortSpeed = B110; break;
|
||||
case 134: stPortSpeed = B134; break;
|
||||
case 150: stPortSpeed = B150; break;
|
||||
case 300: stPortSpeed = B300; break;
|
||||
case 600: stPortSpeed = B600; break;
|
||||
case 1200: stPortSpeed = B1200; break;
|
||||
case 1800: stPortSpeed = B1800; break;
|
||||
case 2400: stPortSpeed = B2400; break;
|
||||
case 4800: stPortSpeed = B4800; break;
|
||||
case 9600: stPortSpeed = B9600; break;
|
||||
case 19200: stPortSpeed = B19200; break;
|
||||
case 38400: stPortSpeed = B38400; break;
|
||||
# ifdef B57600
|
||||
case 57600: stPortSpeed = B57600; break;
|
||||
case 57600: stPortSpeed = B57600; break;
|
||||
# endif
|
||||
# ifdef B115200
|
||||
case 115200: stPortSpeed = B115200; break;
|
||||
case 115200: stPortSpeed = B115200; break;
|
||||
# endif
|
||||
# ifdef B230400
|
||||
case 230400: stPortSpeed = B230400; break;
|
||||
case 230400: stPortSpeed = B230400; break;
|
||||
# endif
|
||||
# ifdef B460800
|
||||
case 460800: stPortSpeed = B460800; break;
|
||||
case 460800: stPortSpeed = B460800; break;
|
||||
# endif
|
||||
# ifdef B921600
|
||||
case 921600: stPortSpeed = B921600; break;
|
||||
case 921600: stPortSpeed = B921600; break;
|
||||
# endif
|
||||
default: return false;
|
||||
};
|
||||
default: return false;
|
||||
};
|
||||
|
||||
struct termios ti;
|
||||
if (tcgetattr(spu->fd,&ti) == -1)
|
||||
return false;
|
||||
struct termios ti;
|
||||
if (tcgetattr(spu->fd,&ti) == -1)
|
||||
return false;
|
||||
|
||||
// Set port speed (Input and Output)
|
||||
cfsetispeed(&ti, stPortSpeed);
|
||||
cfsetospeed(&ti, stPortSpeed);
|
||||
return (tcsetattr(spu->fd, TCSANOW, &ti) != -1);
|
||||
// Set port speed (Input and Output)
|
||||
cfsetispeed(&ti, stPortSpeed);
|
||||
cfsetospeed(&ti, stPortSpeed);
|
||||
return (tcsetattr(spu->fd, TCSANOW, &ti) != -1);
|
||||
}
|
||||
|
||||
uint32_t uart_get_speed(const serial_port sp) {
|
||||
struct termios ti;
|
||||
uint32_t uiPortSpeed;
|
||||
const serial_port_unix* spu = (serial_port_unix*)sp;
|
||||
struct termios ti;
|
||||
uint32_t uiPortSpeed;
|
||||
const serial_port_unix* spu = (serial_port_unix*)sp;
|
||||
|
||||
if (tcgetattr(spu->fd, &ti) == -1)
|
||||
return 0;
|
||||
if (tcgetattr(spu->fd, &ti) == -1)
|
||||
return 0;
|
||||
|
||||
// Set port speed (Input)
|
||||
speed_t stPortSpeed = cfgetispeed(&ti);
|
||||
switch (stPortSpeed) {
|
||||
case B0: uiPortSpeed = 0; break;
|
||||
case B50: uiPortSpeed = 50; break;
|
||||
case B75: uiPortSpeed = 75; break;
|
||||
case B110: uiPortSpeed = 110; break;
|
||||
case B134: uiPortSpeed = 134; break;
|
||||
case B150: uiPortSpeed = 150; break;
|
||||
case B300: uiPortSpeed = 300; break;
|
||||
case B600: uiPortSpeed = 600; break;
|
||||
case B1200: uiPortSpeed = 1200; break;
|
||||
case B1800: uiPortSpeed = 1800; break;
|
||||
case B2400: uiPortSpeed = 2400; break;
|
||||
case B4800: uiPortSpeed = 4800; break;
|
||||
case B9600: uiPortSpeed = 9600; break;
|
||||
case B19200: uiPortSpeed = 19200; break;
|
||||
case B38400: uiPortSpeed = 38400; break;
|
||||
// Set port speed (Input)
|
||||
speed_t stPortSpeed = cfgetispeed(&ti);
|
||||
switch (stPortSpeed) {
|
||||
case B0: uiPortSpeed = 0; break;
|
||||
case B50: uiPortSpeed = 50; break;
|
||||
case B75: uiPortSpeed = 75; break;
|
||||
case B110: uiPortSpeed = 110; break;
|
||||
case B134: uiPortSpeed = 134; break;
|
||||
case B150: uiPortSpeed = 150; break;
|
||||
case B300: uiPortSpeed = 300; break;
|
||||
case B600: uiPortSpeed = 600; break;
|
||||
case B1200: uiPortSpeed = 1200; break;
|
||||
case B1800: uiPortSpeed = 1800; break;
|
||||
case B2400: uiPortSpeed = 2400; break;
|
||||
case B4800: uiPortSpeed = 4800; break;
|
||||
case B9600: uiPortSpeed = 9600; break;
|
||||
case B19200: uiPortSpeed = 19200; break;
|
||||
case B38400: uiPortSpeed = 38400; break;
|
||||
# ifdef B57600
|
||||
case B57600: uiPortSpeed = 57600; break;
|
||||
case B57600: uiPortSpeed = 57600; break;
|
||||
# endif
|
||||
# ifdef B115200
|
||||
case B115200: uiPortSpeed = 115200; break;
|
||||
case B115200: uiPortSpeed = 115200; break;
|
||||
# endif
|
||||
# ifdef B230400
|
||||
case B230400: uiPortSpeed = 230400; break;
|
||||
case B230400: uiPortSpeed = 230400; break;
|
||||
# endif
|
||||
# ifdef B460800
|
||||
case B460800: uiPortSpeed = 460800; break;
|
||||
case B460800: uiPortSpeed = 460800; break;
|
||||
# endif
|
||||
# ifdef B921600
|
||||
case B921600: uiPortSpeed = 921600; break;
|
||||
case B921600: uiPortSpeed = 921600; break;
|
||||
# endif
|
||||
default: return 0;
|
||||
};
|
||||
return uiPortSpeed;
|
||||
default: return 0;
|
||||
};
|
||||
return uiPortSpeed;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -49,129 +49,129 @@ typedef struct {
|
|||
} serial_port_windows;
|
||||
|
||||
serial_port uart_open(const char* pcPortName) {
|
||||
char acPortName[255];
|
||||
serial_port_windows* sp = calloc(sizeof(serial_port_windows), sizeof(uint8_t));
|
||||
char acPortName[255];
|
||||
serial_port_windows* sp = calloc(sizeof(serial_port_windows), sizeof(uint8_t));
|
||||
|
||||
if (sp == 0) {
|
||||
printf("[!] UART failed to allocate memory\n");
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
// Copy the input "com?" to "\\.\COM?" format
|
||||
sprintf(acPortName,"\\\\.\\%s", pcPortName);
|
||||
_strupr(acPortName);
|
||||
if (sp == 0) {
|
||||
printf("[!] UART failed to allocate memory\n");
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
// Copy the input "com?" to "\\.\COM?" format
|
||||
sprintf(acPortName,"\\\\.\\%s", pcPortName);
|
||||
_strupr(acPortName);
|
||||
|
||||
// Try to open the serial port
|
||||
// r/w, none-share comport, no security, existing, no overlapping, no templates
|
||||
sp->hPort = CreateFileA(acPortName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (sp->hPort == INVALID_HANDLE_VALUE) {
|
||||
uart_close(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
// Try to open the serial port
|
||||
// r/w, none-share comport, no security, existing, no overlapping, no templates
|
||||
sp->hPort = CreateFileA(acPortName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (sp->hPort == INVALID_HANDLE_VALUE) {
|
||||
uart_close(sp);
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
// Prepare the device control
|
||||
// doesn't matter since PM3 device ignors this CDC command: set_line_coding in usb_cdc.c
|
||||
memset(&sp->dcb, 0, sizeof(DCB));
|
||||
sp->dcb.DCBlength = sizeof(DCB);
|
||||
if (!BuildCommDCBA("baud=115200 parity=N data=8 stop=1", &sp->dcb)) {
|
||||
uart_close(sp);
|
||||
printf("[!] UART error cdc setup\n");
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
// Prepare the device control
|
||||
// doesn't matter since PM3 device ignors this CDC command: set_line_coding in usb_cdc.c
|
||||
memset(&sp->dcb, 0, sizeof(DCB));
|
||||
sp->dcb.DCBlength = sizeof(DCB);
|
||||
if (!BuildCommDCBA("baud=115200 parity=N data=8 stop=1", &sp->dcb)) {
|
||||
uart_close(sp);
|
||||
printf("[!] UART error cdc setup\n");
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
// Update the active serial port
|
||||
if (!SetCommState(sp->hPort, &sp->dcb)) {
|
||||
uart_close(sp);
|
||||
printf("[!] UART error while setting com state\n");
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
// all zero's configure: no timeout for read/write used.
|
||||
// took settings from libnfc/buses/uart.c
|
||||
// Update the active serial port
|
||||
if (!SetCommState(sp->hPort, &sp->dcb)) {
|
||||
uart_close(sp);
|
||||
printf("[!] UART error while setting com state\n");
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
// all zero's configure: no timeout for read/write used.
|
||||
// took settings from libnfc/buses/uart.c
|
||||
#ifdef WITH_FPC
|
||||
sp->ct.ReadIntervalTimeout = 1000;
|
||||
sp->ct.ReadTotalTimeoutMultiplier = 0;
|
||||
sp->ct.ReadTotalTimeoutConstant = 1500;
|
||||
sp->ct.WriteTotalTimeoutMultiplier = 1000;
|
||||
sp->ct.WriteTotalTimeoutConstant = 0;
|
||||
sp->ct.ReadIntervalTimeout = 1000;
|
||||
sp->ct.ReadTotalTimeoutMultiplier = 0;
|
||||
sp->ct.ReadTotalTimeoutConstant = 1500;
|
||||
sp->ct.WriteTotalTimeoutMultiplier = 1000;
|
||||
sp->ct.WriteTotalTimeoutConstant = 0;
|
||||
#else
|
||||
sp->ct.ReadIntervalTimeout = 30;
|
||||
sp->ct.ReadTotalTimeoutMultiplier = 0;
|
||||
sp->ct.ReadTotalTimeoutConstant = 30;
|
||||
sp->ct.WriteTotalTimeoutMultiplier = 30;
|
||||
sp->ct.WriteTotalTimeoutConstant = 0;
|
||||
sp->ct.ReadIntervalTimeout = 30;
|
||||
sp->ct.ReadTotalTimeoutMultiplier = 0;
|
||||
sp->ct.ReadTotalTimeoutConstant = 30;
|
||||
sp->ct.WriteTotalTimeoutMultiplier = 30;
|
||||
sp->ct.WriteTotalTimeoutConstant = 0;
|
||||
#endif
|
||||
|
||||
if (!SetCommTimeouts(sp->hPort, &sp->ct)) {
|
||||
uart_close(sp);
|
||||
printf("[!] UART error while setting comm time outs\n");
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
if (!SetCommTimeouts(sp->hPort, &sp->ct)) {
|
||||
uart_close(sp);
|
||||
printf("[!] UART error while setting comm time outs\n");
|
||||
return INVALID_SERIAL_PORT;
|
||||
}
|
||||
|
||||
PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
||||
PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
||||
|
||||
#ifdef WITH_FPC
|
||||
if ( uart_set_speed(sp, 115200) ) {
|
||||
printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n");
|
||||
} else {
|
||||
uart_set_speed(sp, 9600);
|
||||
printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n");
|
||||
}
|
||||
if ( uart_set_speed(sp, 115200) ) {
|
||||
printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n");
|
||||
} else {
|
||||
uart_set_speed(sp, 9600);
|
||||
printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n");
|
||||
}
|
||||
#else
|
||||
bool success = uart_set_speed(sp, 460800);
|
||||
if (success) {
|
||||
printf("[=] UART Setting serial baudrate 460800\n");
|
||||
} else {
|
||||
uart_set_speed(sp, 115200);
|
||||
printf("[=] UART Setting serial baudrate 115200\n");
|
||||
}
|
||||
bool success = uart_set_speed(sp, 460800);
|
||||
if (success) {
|
||||
printf("[=] UART Setting serial baudrate 460800\n");
|
||||
} else {
|
||||
uart_set_speed(sp, 115200);
|
||||
printf("[=] UART Setting serial baudrate 115200\n");
|
||||
}
|
||||
#endif
|
||||
return sp;
|
||||
return sp;
|
||||
}
|
||||
|
||||
void uart_close(const serial_port sp) {
|
||||
if (((serial_port_windows*)sp)->hPort != INVALID_HANDLE_VALUE )
|
||||
CloseHandle(((serial_port_windows*)sp)->hPort);
|
||||
free(sp);
|
||||
if (((serial_port_windows*)sp)->hPort != INVALID_HANDLE_VALUE )
|
||||
CloseHandle(((serial_port_windows*)sp)->hPort);
|
||||
free(sp);
|
||||
}
|
||||
|
||||
bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {
|
||||
serial_port_windows* spw;
|
||||
serial_port_windows* spw;
|
||||
|
||||
// Set port speed (Input and Output)
|
||||
switch (uiPortSpeed) {
|
||||
case 9600:
|
||||
case 19200:
|
||||
case 38400:
|
||||
case 57600:
|
||||
case 115200:
|
||||
case 230400:
|
||||
case 460800:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
// Set port speed (Input and Output)
|
||||
switch (uiPortSpeed) {
|
||||
case 9600:
|
||||
case 19200:
|
||||
case 38400:
|
||||
case 57600:
|
||||
case 115200:
|
||||
case 230400:
|
||||
case 460800:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
|
||||
spw = (serial_port_windows*)sp;
|
||||
spw->dcb.BaudRate = uiPortSpeed;
|
||||
bool result = SetCommState(spw->hPort, &spw->dcb);
|
||||
PurgeComm(spw->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
||||
return result;
|
||||
spw = (serial_port_windows*)sp;
|
||||
spw->dcb.BaudRate = uiPortSpeed;
|
||||
bool result = SetCommState(spw->hPort, &spw->dcb);
|
||||
PurgeComm(spw->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t uart_get_speed(const serial_port sp) {
|
||||
const serial_port_windows* spw = (serial_port_windows*)sp;
|
||||
if (!GetCommState(spw->hPort, (serial_port) & spw->dcb))
|
||||
return spw->dcb.BaudRate;
|
||||
const serial_port_windows* spw = (serial_port_windows*)sp;
|
||||
if (!GetCommState(spw->hPort, (serial_port) & spw->dcb))
|
||||
return spw->dcb.BaudRate;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool uart_receive(const serial_port sp, uint8_t* p_rx, size_t pszMaxRxLen, size_t* len) {
|
||||
return ReadFile(((serial_port_windows*)sp)->hPort, p_rx, pszMaxRxLen, (LPDWORD)len, NULL);
|
||||
return ReadFile(((serial_port_windows*)sp)->hPort, p_rx, pszMaxRxLen, (LPDWORD)len, NULL);
|
||||
}
|
||||
|
||||
bool uart_send(const serial_port sp, const uint8_t* p_tx, const size_t len) {
|
||||
DWORD txlen = 0;
|
||||
return WriteFile(((serial_port_windows*)sp)->hPort, p_tx, len, &txlen, NULL);
|
||||
DWORD txlen = 0;
|
||||
return WriteFile(((serial_port_windows*)sp)->hPort, p_tx, len, &txlen, NULL);
|
||||
}
|
||||
|
||||
#endif
|
34
update.sh
34
update.sh
|
@ -1,26 +1,26 @@
|
|||
#!/bin/bash
|
||||
|
||||
function wait4proxmark_Linux {
|
||||
echo >&2 "Waiting for Proxmark to appear..."
|
||||
while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do
|
||||
sleep .1
|
||||
done
|
||||
local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1`
|
||||
echo >&2 -e "Found proxmark on ${PM3}\n"
|
||||
echo $PM3
|
||||
echo >&2 "Waiting for Proxmark to appear..."
|
||||
while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do
|
||||
sleep .1
|
||||
done
|
||||
local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1`
|
||||
echo >&2 -e "Found proxmark on ${PM3}\n"
|
||||
echo $PM3
|
||||
}
|
||||
|
||||
function wait4proxmark_macOS {
|
||||
echo >&2 "Waiting for Proxmark to appear..."
|
||||
while true; do
|
||||
PM3=$(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)
|
||||
if [[ $PM3 != "" ]]; then
|
||||
#echo >&2 -e "Found proxmark on $(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)\n"
|
||||
break
|
||||
fi
|
||||
sleep .1
|
||||
done
|
||||
echo $PM3
|
||||
echo >&2 "Waiting for Proxmark to appear..."
|
||||
while true; do
|
||||
PM3=$(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)
|
||||
if [[ $PM3 != "" ]]; then
|
||||
#echo >&2 -e "Found proxmark on $(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)\n"
|
||||
break
|
||||
fi
|
||||
sleep .1
|
||||
done
|
||||
echo $PM3
|
||||
}
|
||||
|
||||
# Detect OS and flash bootroom & system image
|
||||
|
|
132
zlib/deflate.c
132
zlib/deflate.c
|
@ -1160,10 +1160,10 @@ local uInt longest_match(s, cur_match)
|
|||
{
|
||||
unsigned chain_length = s->max_chain_length;/* max hash chain length */
|
||||
register Bytef *scan = s->window + s->strstart; /* current string */
|
||||
register Bytef *match; /* matched string */
|
||||
register Bytef *match; /* matched string */
|
||||
register int len; /* length of current match */
|
||||
#ifdef ZLIB_PM3_TUNED
|
||||
int best_len = MIN_MATCH-1; // lift the restriction on prev-length
|
||||
int best_len = MIN_MATCH-1; /* lift the restriction on prev-length */
|
||||
#else
|
||||
int best_len = s->prev_length; /* best match length so far */
|
||||
#endif
|
||||
|
@ -1737,73 +1737,73 @@ local block_state deflate_fast(s, flush)
|
|||
|
||||
#ifdef ZLIB_PM3_TUNED
|
||||
local uInt try_harder(s, strstart, lookahead, hash_head)
|
||||
deflate_state *s;
|
||||
uInt strstart;
|
||||
uInt lookahead;
|
||||
IPos hash_head;
|
||||
deflate_state *s;
|
||||
uInt strstart;
|
||||
uInt lookahead;
|
||||
IPos hash_head;
|
||||
{
|
||||
uInt strstart_save = s->strstart;
|
||||
s->strstart = strstart;
|
||||
uInt lookahead_save = s->lookahead;
|
||||
s->lookahead = lookahead;
|
||||
uInt ins_h_save = s->ins_h;
|
||||
uInt combined_gain;
|
||||
uInt best_combined_gain = 0;
|
||||
uInt match_length;
|
||||
uInt prev_length = s->prev_length < MIN_MATCH ? 1 : s->prev_length;
|
||||
uInt best_prev_length = prev_length;
|
||||
uInt current_match_start = s->match_start;
|
||||
uInt current_match_length = s->match_length;
|
||||
uInt strstart_save = s->strstart;
|
||||
s->strstart = strstart;
|
||||
uInt lookahead_save = s->lookahead;
|
||||
s->lookahead = lookahead;
|
||||
uInt ins_h_save = s->ins_h;
|
||||
uInt combined_gain;
|
||||
uInt best_combined_gain = 0;
|
||||
uInt match_length;
|
||||
uInt prev_length = s->prev_length < MIN_MATCH ? 1 : s->prev_length;
|
||||
uInt best_prev_length = prev_length;
|
||||
uInt current_match_start = s->match_start;
|
||||
uInt current_match_length = s->match_length;
|
||||
|
||||
do {
|
||||
do {
|
||||
if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
|
||||
match_length = longest_match (s, hash_head);
|
||||
/* longest_match() sets match_start */
|
||||
} else {
|
||||
match_length = MIN_MATCH - 1;
|
||||
}
|
||||
match_length = longest_match (s, hash_head);
|
||||
/* longest_match() sets match_start */
|
||||
} else {
|
||||
match_length = MIN_MATCH - 1;
|
||||
}
|
||||
#if TOO_FAR <= 32767
|
||||
if (match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) {
|
||||
match_length = MIN_MATCH-1;
|
||||
}
|
||||
if (match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) {
|
||||
match_length = MIN_MATCH-1;
|
||||
}
|
||||
#endif
|
||||
if (s->strstart == strstart) { // store match at current position
|
||||
current_match_length = match_length;
|
||||
current_match_start = s->match_start;
|
||||
}
|
||||
if (s->strstart - strstart + 1 < MIN_MATCH) { // previous match reduced to one or two literals
|
||||
combined_gain = 0; // need one literal per byte: no gain (assuming 8 bits per literal)
|
||||
} else {
|
||||
combined_gain = s->strstart - strstart + 1 - MIN_MATCH; // (possibly truncated) previous_length - 3 literals
|
||||
}
|
||||
if (match_length < MIN_MATCH) {
|
||||
combined_gain += 0; // no gain
|
||||
} else {
|
||||
combined_gain += match_length - MIN_MATCH; // match_length bytes are coded as three literals
|
||||
}
|
||||
if (combined_gain >= best_combined_gain) { // in case of a tie we prefer the longer prev_length
|
||||
best_combined_gain = combined_gain;
|
||||
best_prev_length = s->strstart - strstart + 1;
|
||||
}
|
||||
s->strstart++;
|
||||
s->lookahead--;
|
||||
UPDATE_HASH(s, s->ins_h, s->window[(s->strstart) + (MIN_MATCH-1)]);
|
||||
hash_head = s->head[s->ins_h];
|
||||
} while (s->strstart <= strstart-1 + prev_length // try to truncate the previous match to 1, 3, ... prev_length
|
||||
&& s->strstart <= s->window_size - MIN_LOOKAHEAD); // watch out for the end of the input
|
||||
if (s->strstart == strstart) { // store match at current position
|
||||
current_match_length = match_length;
|
||||
current_match_start = s->match_start;
|
||||
}
|
||||
if (s->strstart - strstart + 1 < MIN_MATCH) { // previous match reduced to one or two literals
|
||||
combined_gain = 0; // need one literal per byte: no gain (assuming 8 bits per literal)
|
||||
} else {
|
||||
combined_gain = s->strstart - strstart + 1 - MIN_MATCH; // (possibly truncated) previous_length - 3 literals
|
||||
}
|
||||
if (match_length < MIN_MATCH) {
|
||||
combined_gain += 0; // no gain
|
||||
} else {
|
||||
combined_gain += match_length - MIN_MATCH; // match_length bytes are coded as three literals
|
||||
}
|
||||
if (combined_gain >= best_combined_gain) { // in case of a tie we prefer the longer prev_length
|
||||
best_combined_gain = combined_gain;
|
||||
best_prev_length = s->strstart - strstart + 1;
|
||||
}
|
||||
s->strstart++;
|
||||
s->lookahead--;
|
||||
UPDATE_HASH(s, s->ins_h, s->window[(s->strstart) + (MIN_MATCH-1)]);
|
||||
hash_head = s->head[s->ins_h];
|
||||
} while (s->strstart <= strstart-1 + prev_length // try to truncate the previous match to 1, 3, ... prev_length
|
||||
&& s->strstart <= s->window_size - MIN_LOOKAHEAD); // watch out for the end of the input
|
||||
|
||||
s->strstart = strstart_save;
|
||||
s->lookahead = lookahead_save;
|
||||
s->ins_h = ins_h_save;
|
||||
s->match_length = current_match_length;
|
||||
s->match_start = current_match_start;
|
||||
if (best_prev_length >= MIN_MATCH) {
|
||||
s->prev_length = best_prev_length;
|
||||
s->match_length = MIN_MATCH - 1;
|
||||
} else {
|
||||
s->prev_length = MIN_MATCH - 1;
|
||||
}
|
||||
return best_combined_gain;
|
||||
s->strstart = strstart_save;
|
||||
s->lookahead = lookahead_save;
|
||||
s->ins_h = ins_h_save;
|
||||
s->match_length = current_match_length;
|
||||
s->match_start = current_match_start;
|
||||
if (best_prev_length >= MIN_MATCH) {
|
||||
s->prev_length = best_prev_length;
|
||||
s->match_length = MIN_MATCH - 1;
|
||||
} else {
|
||||
s->prev_length = MIN_MATCH - 1;
|
||||
}
|
||||
return best_combined_gain;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1850,9 +1850,9 @@ local block_state deflate_slow(s, flush)
|
|||
s->match_length = MIN_MATCH-1;
|
||||
|
||||
#ifdef ZLIB_PM3_TUNED
|
||||
if (s->prev_length < s->max_lazy_match) {
|
||||
try_harder(s, s->strstart, s->lookahead, hash_head);
|
||||
}
|
||||
if (s->prev_length < s->max_lazy_match) {
|
||||
try_harder(s, s->strstart, s->lookahead, hash_head);
|
||||
}
|
||||
|
||||
#else
|
||||
if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
|
||||
|
|
|
@ -857,7 +857,7 @@ int flush;
|
|||
case 1: /* fixed block */
|
||||
#ifdef ZLIB_PM3_TUNED
|
||||
strm->msg = (char *)"fixed block coding not supported";
|
||||
state->mode = BAD;
|
||||
state->mode = BAD;
|
||||
#else
|
||||
fixedtables(state);
|
||||
Tracev((stderr, "inflate: fixed codes block%s\n",
|
||||
|
|
|
@ -989,7 +989,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
|
|||
#endif
|
||||
} else {
|
||||
#endif /* !ZLIB_PM3_TUNED */
|
||||
send_bits(s, (DYN_TREES<<1)+last, 3);
|
||||
send_bits(s, (DYN_TREES<<1)+last, 3);
|
||||
send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
|
||||
max_blindex+1);
|
||||
compress_block(s, (const ct_data *)s->dyn_ltree,
|
||||
|
|
Loading…
Reference in a new issue