From d7c3cc8028b304fd9f2f06af86274aae5bce05cf Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 16 Feb 2020 20:48:53 +1100 Subject: [PATCH 001/298] Update cmdlfkeri.c --- client/cmdlfkeri.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index aadc8676d..1d49117d1 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -53,6 +53,57 @@ static int usage_lf_keri_sim(void) { PrintAndLogEx(NORMAL, " lf keri sim 112233"); return PM3_SUCCESS; } +static int CmdKeriMSDescramble (uint32_t *FC, uint32_t *ID, uint32_t CardID) +{ + uint8_t CardToID [] = { 0xff,0xff,0xff,0xff,0x0d,0x0c,0x11,0x05,0xff,0x06,0xff,0x12,0x08,0xff,0x00,0x07, + 0x0a,0xff,0xff,0x0b,0x04,0x01,0xff,0x13,0xff,0x14,0x02,0xff,0x03,0x09,0xff,0xff }; + uint8_t CardToFC [] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0xff }; + uint8_t CardIdx; // 0 - 31 + bool BitState; + int idx; + + char IDDecodeState[33] = {0x00}; + char FCDecodeState[33] = {0x00}; + + memset (IDDecodeState,'-',32); + memset (FCDecodeState,'-',32); + + + + *FC = 0; + *ID = 0; + + for (CardIdx = 0; CardIdx < 32; CardIdx++) { + // Get Bit State + BitState = (CardID >> CardIdx) & 1; + //if (BitState) { // its a 1 + idx = CardToID[CardIdx]; + if ((idx >= 0) && (idx <= 32)) { + if (BitState) + *ID = *ID | (1 << idx); + IDDecodeState[idx] = '0'+BitState; + } + //else + // IDDecodeState[CardIdx] = '-'; + + idx = CardToFC[CardIdx]; + if ((idx >= 0) && (idx <= 32)) { + if (BitState) + *FC = *FC | (1 << idx); + FCDecodeState[idx] = '0'+BitState; + } + //else + // IDDecodeState[CardIdx] = '-'; + + // } + } + + PrintAndLogEx(SUCCESS, "BitState ID : %s",IDDecodeState); + PrintAndLogEx(SUCCESS, "BitState FC : %s",FCDecodeState); + + return PM3_SUCCESS; +} static int CmdKeriDemod(const char *Cmd) { (void)Cmd; // Cmd is not used so far @@ -103,6 +154,18 @@ static int CmdKeriDemod(const char *Cmd) { PrintAndLogEx(SUCCESS, "KERI Tag Found -- Internal ID: %u", ID); PrintAndLogEx(SUCCESS, "Raw: %08X%08X", raw1, raw2); +/* + Descramble Data. +*/ + uint32_t fc = 0; + uint32_t imprintID = 0; + + // Just need to the low 32 bits without the 111 trailer + CmdKeriMSDescramble (&fc,&imprintID,raw2); + + PrintAndLogEx (SUCCESS,"Descrambled MS : FC %d - imprint id %d\n",fc,imprintID); + +// End Descramble test if (invert) { PrintAndLogEx(INFO, "Had to Invert - probably KERI"); From c6ceeed6d563760305a3ebf91ecb2d4739d7b504 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Mon, 17 Feb 2020 21:49:43 +1100 Subject: [PATCH 002/298] Update cmdlfkeri.c --- client/cmdlfkeri.c | 131 ++++++++++++++++++++++++++++++++------------- 1 file changed, 95 insertions(+), 36 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 1d49117d1..d10063edb 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -53,55 +53,112 @@ static int usage_lf_keri_sim(void) { PrintAndLogEx(NORMAL, " lf keri sim 112233"); return PM3_SUCCESS; } -static int CmdKeriMSDescramble (uint32_t *FC, uint32_t *ID, uint32_t CardID) + +typedef enum {Scramble = 0,Descramble = 1} KeriMSScramble_t; + +static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *ID, uint32_t *CardID) { uint8_t CardToID [] = { 0xff,0xff,0xff,0xff,0x0d,0x0c,0x11,0x05,0xff,0x06,0xff,0x12,0x08,0xff,0x00,0x07, 0x0a,0xff,0xff,0x0b,0x04,0x01,0xff,0x13,0xff,0x14,0x02,0xff,0x03,0x09,0xff,0xff }; uint8_t CardToFC [] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0xff }; + + uint8_t IDToCard [] = { 0x0e,0x15,0x1a,0x1c,0x14,0x07,0x09,0x0f,0x0c,0x1d,0x10,0x13,0x05,0x04,0xff,0xff, + 0xff,0x06,0x0b,0x17,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; + uint8_t FCToCard [] = { 0xff,0x1e,0x12,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; + uint8_t CardIdx; // 0 - 31 bool BitState; int idx; - char IDDecodeState[33] = {0x00}; - char FCDecodeState[33] = {0x00}; - - memset (IDDecodeState,'-',32); - memset (FCDecodeState,'-',32); - - + if (Action == Descramble) { + char IDDecodeState[33] = {0x00}; + char FCDecodeState[33] = {0x00}; - *FC = 0; - *ID = 0; + memset (IDDecodeState,'-',32); + memset (FCDecodeState,'-',32); - for (CardIdx = 0; CardIdx < 32; CardIdx++) { - // Get Bit State - BitState = (CardID >> CardIdx) & 1; - //if (BitState) { // its a 1 - idx = CardToID[CardIdx]; - if ((idx >= 0) && (idx <= 32)) { - if (BitState) - *ID = *ID | (1 << idx); - IDDecodeState[idx] = '0'+BitState; + *FC = 0; + *ID = 0; + + for (CardIdx = 0; CardIdx < 32; CardIdx++) { + // Get Bit State + BitState = (*CardID >> CardIdx) & 1; + //if (BitState) { // its a 1 + idx = CardToID[CardIdx]; + if ((idx >= 0) && (idx <= 32)) { + if (BitState) + *ID = *ID | (1 << idx); + IDDecodeState[31-idx] = '0'+BitState; + } + + idx = CardToFC[CardIdx]; + if ((idx >= 0) && (idx <= 32)) { + if (BitState) + *FC = *FC | (1 << idx); + FCDecodeState[31-idx] = '0'+BitState; + } } - //else - // IDDecodeState[CardIdx] = '-'; - - idx = CardToFC[CardIdx]; - if ((idx >= 0) && (idx <= 32)) { - if (BitState) - *FC = *FC | (1 << idx); - FCDecodeState[idx] = '0'+BitState; - } - //else - // IDDecodeState[CardIdx] = '-'; - // } + // Patch for bit order group unknown + // Reverse order for easy mapping for unknowns + // I know that these bit groups are a in the correct location, unknown order. + if (IDDecodeState[31-17] == '1') IDDecodeState[31-17] = '?'; + if (IDDecodeState[31-18] == '1') IDDecodeState[31-18] = '?'; + if (IDDecodeState[31-19] == '1') IDDecodeState[31-19] = '?'; + if (IDDecodeState[31-20] == '1') IDDecodeState[31-20] = '?'; + + if (FCDecodeState[31- 1] == '1') FCDecodeState[31- 1] = '?'; + if (FCDecodeState[31- 2] == '1') FCDecodeState[31- 2] = '?'; + + PrintAndLogEx(SUCCESS, "BitState ID : %s",IDDecodeState); + PrintAndLogEx(SUCCESS, "BitState FC : %s",FCDecodeState); } + if (Action == Scramble) + { + // PrintAndLogEx(SUCCESS, "Scramble FC : %d - ID %d",*FC,*ID); + *CardID = 0; // set to 0 - PrintAndLogEx(SUCCESS, "BitState ID : %s",IDDecodeState); - PrintAndLogEx(SUCCESS, "BitState FC : %s",FCDecodeState); + for (CardIdx = 0; CardIdx < 32; CardIdx++) + { + // Card ID + BitState = (*ID >> CardIdx) & 1; + if (BitState) { + idx = IDToCard[CardIdx]; + if ((idx >= 0) && (idx <= 32)) { + *CardID |= (1 << idx); + } + } + // FC + BitState = (*FC >> CardIdx) & 1; + if (BitState) { + idx = FCToCard[CardIdx]; + if ((idx >= 0) && (idx <= 32)) { + *CardID |= (1 << idx); + } + } + } + // Fixed bits + /* + Add Parity and Fixed bits + Bit 3 - Note Used/Fixed 1 + Bit 31 - 1 Fixed + Bit 0,1 - 2 Bit Parity + */ + *CardID |= (1 << 3); + // Check/Parity Bits + int Parity = 1; + for (CardIdx = 4; CardIdx <= 31; CardIdx += 2) { + Parity = Parity ^ ((*CardID >> CardIdx) & 11); + } + *CardID = *CardID | Parity; + + // Bit 31 was fixed but not in check/parity bits + *CardID |= (1 << 31); + PrintAndLogEx(SUCCESS, "Scrambled FC : %d - Card ID : %d to RAW : E0000000%08X",*FC,*ID,*CardID); + } return PM3_SUCCESS; } @@ -158,13 +215,15 @@ static int CmdKeriDemod(const char *Cmd) { Descramble Data. */ uint32_t fc = 0; - uint32_t imprintID = 0; + uint32_t cardid = 0; // Just need to the low 32 bits without the 111 trailer - CmdKeriMSDescramble (&fc,&imprintID,raw2); + CmdKeriMSScramble (Descramble,&fc,&cardid,&raw2); - PrintAndLogEx (SUCCESS,"Descrambled MS : FC %d - imprint id %d\n",fc,imprintID); + PrintAndLogEx (SUCCESS,"Descrambled MS : FC %d - Card ID %d\n",fc,cardid); + uint32_t testCard = 0; + CmdKeriMSScramble (Scramble,&fc,&cardid,&testCard); // End Descramble test if (invert) { From bf66d66114037461b0e839698bc121b945dab316 Mon Sep 17 00:00:00 2001 From: Iceman Date: Mon, 17 Feb 2020 20:19:40 +0100 Subject: [PATCH 003/298] Update Troubleshooting.md --- doc/md/Installation_Instructions/Troubleshooting.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/md/Installation_Instructions/Troubleshooting.md b/doc/md/Installation_Instructions/Troubleshooting.md index ab893d177..e727180bf 100644 --- a/doc/md/Installation_Instructions/Troubleshooting.md +++ b/doc/md/Installation_Instructions/Troubleshooting.md @@ -18,6 +18,7 @@ Always use the latest repository commits from *master* branch. There are always * [File not found](#file-not-found) * [Pixmap / pixbuf warnings](#pixmap--pixbuf-warnings) * [Usb cable](#usb-cable) + * [WSL 2 explorer.exe . doesnt work](WSL-2) ## `pm3` or `pm3-flash*` doesn't see my Proxmark @@ -164,3 +165,11 @@ If you get warnings related to pixmap or pixbuf such as *Pixbuf theme: Cannot lo It's needed to have a good USB cable to connect Proxmark3 to USB. If you have stability problems (Proxmark3 resets, firmware hangs, especially firmware hangs just after start, etc.) - check your cable with a USB tester (or try to change it). It needs to have a resistance smaller or equal to 0.3 Ohm. + +## WSL 2 +When ```explorer.exe .``` doesn't work. +Trying to access the dump files created in WSL, you will need to run ```explorer.exe .``` but sometimes this doesn't work. +[As seen here](https://github.com/microsoft/WSL/issues/4027) they suggest checking the following registry value for *P9NP* + +[](www.icedev.se/proxmark3/rdv40/wsl2_p9np.png) + From 7d157606ee0844491143969a492afe8aef882b98 Mon Sep 17 00:00:00 2001 From: Joe Harrison Date: Mon, 17 Feb 2020 23:49:29 +0000 Subject: [PATCH 004/298] Use /usr/bin/env in shebangs Stop assuming that bash is in /bin, and that perl and python are in /usr/bin, etc. Instead, use env command to find these commands in the path. --- client/gen_pm3mfsim_script.sh | 2 +- covbuild.sh | 2 +- covconfig.sh | 2 +- covsubmit.sh | 2 +- pm3 | 2 +- pm3-flash | 2 +- pm3-flash-all | 2 +- pm3-flash-bootrom | 2 +- pm3test.sh | 2 +- tools/analyzesize.py | 2 +- tools/findbits_test.py | 2 +- tools/hitag2crack/crack2/runtest.sh | 2 +- tools/jtag_openocd/openocd_flash_dump.sh | 2 +- tools/jtag_openocd/openocd_flash_recovery.sh | 2 +- tools/jtag_openocd/openocd_interactive.sh | 2 +- tools/mkversion.pl | 2 +- tools/pm3_amii_bin2eml.pl | 2 +- tools/pm3_cs8.pl | 2 +- tools/pm3_eml2lower.sh | 2 +- tools/pm3_eml2upper.sh | 2 +- tools/pm3_eml_mfd_test.py | 2 +- tools/rfidtest.pl | 2 +- tools/xorcheck.py | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) diff --git a/client/gen_pm3mfsim_script.sh b/client/gen_pm3mfsim_script.sh index 86f368673..73c7a4dd4 100644 --- a/client/gen_pm3mfsim_script.sh +++ b/client/gen_pm3mfsim_script.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Andrei Costin , 2011 # gen_pm3mfsim_script.sh diff --git a/covbuild.sh b/covbuild.sh index 1899cb8b3..2e18e677f 100755 --- a/covbuild.sh +++ b/covbuild.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e . .coverity.conf || exit 1 diff --git a/covconfig.sh b/covconfig.sh index 24815f200..b762ac6f1 100755 --- a/covconfig.sh +++ b/covconfig.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e . .coverity.conf || exit 1 diff --git a/covsubmit.sh b/covsubmit.sh index e39240954..61ca853f1 100755 --- a/covsubmit.sh +++ b/covsubmit.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e . .coverity.conf || exit 1 diff --git a/pm3 b/pm3 index d40fb0a91..e702e277f 100755 --- a/pm3 +++ b/pm3 @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Usage: run option -h to get help diff --git a/pm3-flash b/pm3-flash index e5cd5479d..c5e920c24 100755 --- a/pm3-flash +++ b/pm3-flash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash PM3PATH=$(dirname "$0") . "$PM3PATH/pm3" diff --git a/pm3-flash-all b/pm3-flash-all index e5cd5479d..c5e920c24 100755 --- a/pm3-flash-all +++ b/pm3-flash-all @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash PM3PATH=$(dirname "$0") . "$PM3PATH/pm3" diff --git a/pm3-flash-bootrom b/pm3-flash-bootrom index e5cd5479d..c5e920c24 100755 --- a/pm3-flash-bootrom +++ b/pm3-flash-bootrom @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash PM3PATH=$(dirname "$0") . "$PM3PATH/pm3" diff --git a/pm3test.sh b/pm3test.sh index de9134ba1..146650f71 100755 --- a/pm3test.sh +++ b/pm3test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash PM3PATH=$(dirname "$0") cd "$PM3PATH" || exit 1 diff --git a/tools/analyzesize.py b/tools/analyzesize.py index 889222c01..965fe3d66 100755 --- a/tools/analyzesize.py +++ b/tools/analyzesize.py @@ -1,4 +1,4 @@ -#! /usr/bin/python3 +#! /usr/bin/env python3 import json import subprocess diff --git a/tools/findbits_test.py b/tools/findbits_test.py index db8dda8fa..d52334fd4 100644 --- a/tools/findbits_test.py +++ b/tools/findbits_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python from itertools import imap import unittest, sys, findbits diff --git a/tools/hitag2crack/crack2/runtest.sh b/tools/hitag2crack/crack2/runtest.sh index bcc08727c..2d9256d94 100755 --- a/tools/hitag2crack/crack2/runtest.sh +++ b/tools/hitag2crack/crack2/runtest.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash if [ "$1" == "" ]; then echo "runtest.sh testfile" diff --git a/tools/jtag_openocd/openocd_flash_dump.sh b/tools/jtag_openocd/openocd_flash_dump.sh index 650c218f1..4791b9112 100755 --- a/tools/jtag_openocd/openocd_flash_dump.sh +++ b/tools/jtag_openocd/openocd_flash_dump.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash cd $(dirname "$0") . openocd_configuration || exit 1 diff --git a/tools/jtag_openocd/openocd_flash_recovery.sh b/tools/jtag_openocd/openocd_flash_recovery.sh index 80caa08f0..490cf4abd 100755 --- a/tools/jtag_openocd/openocd_flash_recovery.sh +++ b/tools/jtag_openocd/openocd_flash_recovery.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash cd $(dirname "$0") . openocd_configuration || exit 1 diff --git a/tools/jtag_openocd/openocd_interactive.sh b/tools/jtag_openocd/openocd_interactive.sh index ac022f3f2..995ee6913 100755 --- a/tools/jtag_openocd/openocd_interactive.sh +++ b/tools/jtag_openocd/openocd_interactive.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash cd $(dirname "$0") . openocd_configuration || exit 1 diff --git a/tools/mkversion.pl b/tools/mkversion.pl index 997c2081b..95a794697 100644 --- a/tools/mkversion.pl +++ b/tools/mkversion.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl -w # Output a version.c file that includes information about the current build # Normally a couple of lines of bash would be enough (see openpcd project, original firmware by Harald Welte and Milosch Meriac) diff --git a/tools/pm3_amii_bin2eml.pl b/tools/pm3_amii_bin2eml.pl index bb16960d4..b042e1e73 100755 --- a/tools/pm3_amii_bin2eml.pl +++ b/tools/pm3_amii_bin2eml.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # # Read Amiibo data, decrypt, and produce EML file # Convert proxmark MFU (MIFARE Ultralight) .bin to .eml format diff --git a/tools/pm3_cs8.pl b/tools/pm3_cs8.pl index f1bfaf81d..888e7c360 100755 --- a/tools/pm3_cs8.pl +++ b/tools/pm3_cs8.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # # Convert proxmark3 trace or wav files to formats to be used by Inspectrum # diff --git a/tools/pm3_eml2lower.sh b/tools/pm3_eml2lower.sh index 086439c3c..b1c8d12f2 100755 --- a/tools/pm3_eml2lower.sh +++ b/tools/pm3_eml2lower.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Andrei Costin , 2011 # pm3_eml2lower.sh diff --git a/tools/pm3_eml2upper.sh b/tools/pm3_eml2upper.sh index 73b8646b7..bac3237cc 100755 --- a/tools/pm3_eml2upper.sh +++ b/tools/pm3_eml2upper.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Andrei Costin , 2011 # pm3_eml2upper.sh diff --git a/tools/pm3_eml_mfd_test.py b/tools/pm3_eml_mfd_test.py index 171bad843..4be66e83a 100755 --- a/tools/pm3_eml_mfd_test.py +++ b/tools/pm3_eml_mfd_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python from __future__ import with_statement from tempfile import mkdtemp diff --git a/tools/rfidtest.pl b/tools/rfidtest.pl index 304f59454..861f2a20a 100644 --- a/tools/rfidtest.pl +++ b/tools/rfidtest.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # -samy kamkar, rfid@samy.pl use strict; diff --git a/tools/xorcheck.py b/tools/xorcheck.py index 091998a31..04c031cf1 100755 --- a/tools/xorcheck.py +++ b/tools/xorcheck.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # xorcheck.py - find xor values for 8-bit LRC # From 5e88faa2cf32df0456c6e327313606f5e18ef5e7 Mon Sep 17 00:00:00 2001 From: Joe Harrison Date: Wed, 19 Feb 2020 16:13:17 +0000 Subject: [PATCH 005/298] use env in shebangs in pm3-flash-fullimage and rest of tools --- pm3-flash-fullimage | 2 +- tools/findbits.py | 2 +- tools/pm3_eml2mfd.py | 2 +- tools/pm3_mfd2eml.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pm3-flash-fullimage b/pm3-flash-fullimage index e5cd5479d..c5e920c24 100755 --- a/pm3-flash-fullimage +++ b/pm3-flash-fullimage @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash PM3PATH=$(dirname "$0") . "$PM3PATH/pm3" diff --git a/tools/findbits.py b/tools/findbits.py index fb088d739..d3f4c6bcd 100755 --- a/tools/findbits.py +++ b/tools/findbits.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # findbits.py - find Binary, Octal, Decimal or Hex number in bitstream # diff --git a/tools/pm3_eml2mfd.py b/tools/pm3_eml2mfd.py index 86c6df301..4e41604f1 100755 --- a/tools/pm3_eml2mfd.py +++ b/tools/pm3_eml2mfd.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python ''' # Andrei Costin , 2011 diff --git a/tools/pm3_mfd2eml.py b/tools/pm3_mfd2eml.py index 44d60e7d6..a2d8389fa 100755 --- a/tools/pm3_mfd2eml.py +++ b/tools/pm3_mfd2eml.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python ''' # Andrei Costin , 2011 From f32efd10fedaee60c8d3613fd50eaf2c33abbd6e Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Fri, 21 Feb 2020 22:21:56 +1100 Subject: [PATCH 006/298] Update cmdlfkeri.c --- client/cmdlfkeri.c | 89 ++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 50 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index d10063edb..892dfaf5f 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -58,50 +58,42 @@ typedef enum {Scramble = 0,Descramble = 1} KeriMSScramble_t; static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *ID, uint32_t *CardID) { - uint8_t CardToID [] = { 0xff,0xff,0xff,0xff,0x0d,0x0c,0x11,0x05,0xff,0x06,0xff,0x12,0x08,0xff,0x00,0x07, - 0x0a,0xff,0xff,0x0b,0x04,0x01,0xff,0x13,0xff,0x14,0x02,0xff,0x03,0x09,0xff,0xff }; - uint8_t CardToFC [] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0xff }; - - uint8_t IDToCard [] = { 0x0e,0x15,0x1a,0x1c,0x14,0x07,0x09,0x0f,0x0c,0x1d,0x10,0x13,0x05,0x04,0xff,0xff, - 0xff,0x06,0x0b,0x17,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; - uint8_t FCToCard [] = { 0xff,0x1e,0x12,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; + // 255 = Not used/Unknown other values are the bit offset in the ID/FC values + uint8_t CardToID [] = { 255,255,255,255, 13, 12, 17, 5,255, 6,255, 18, 8,255, 0, 7, + 10,255,255, 11, 4, 1,255, 19,255, 20, 2,255, 3, 9,255,255 }; + uint8_t CardToFC [] = { 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255, 2,255,255,255,255,255,255,255,255,255,255,255, 1,255 }; uint8_t CardIdx; // 0 - 31 bool BitState; - int idx; + + // Used to track known bit states - remove when all bit maps are known + char IDDecodeState[33] = {0x00}; + char FCDecodeState[33] = {0x00}; + memset (IDDecodeState,'-',32); + memset (FCDecodeState,'-',32); if (Action == Descramble) { - char IDDecodeState[33] = {0x00}; - char FCDecodeState[33] = {0x00}; - - memset (IDDecodeState,'-',32); - memset (FCDecodeState,'-',32); - *FC = 0; *ID = 0; - for (CardIdx = 0; CardIdx < 32; CardIdx++) { // Get Bit State BitState = (*CardID >> CardIdx) & 1; - //if (BitState) { // its a 1 - idx = CardToID[CardIdx]; - if ((idx >= 0) && (idx <= 32)) { - if (BitState) - *ID = *ID | (1 << idx); - IDDecodeState[31-idx] = '0'+BitState; + // Card ID + if (CardToID[CardIdx] < 32) { + *ID = *ID | (BitState << CardToID[CardIdx]); + // Remove when all bits are known + IDDecodeState[31-CardToID[CardIdx]] = '0'+BitState; } - - idx = CardToFC[CardIdx]; - if ((idx >= 0) && (idx <= 32)) { - if (BitState) - *FC = *FC | (1 << idx); - FCDecodeState[31-idx] = '0'+BitState; + // Card FC + if (CardToFC[CardIdx] < 32) { + *FC = *FC | (BitState << CardToFC[CardIdx]); + // Remove when all bits are known + FCDecodeState[31-CardToFC[CardIdx]] = '0'+BitState; } } - // Patch for bit order group unknown + // Patch for bit order group unknown - remove when all Keri MS Bits maps are known // Reverse order for easy mapping for unknowns // I know that these bit groups are a in the correct location, unknown order. if (IDDecodeState[31-17] == '1') IDDecodeState[31-17] = '?'; @@ -115,38 +107,34 @@ static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *I PrintAndLogEx(SUCCESS, "BitState ID : %s",IDDecodeState); PrintAndLogEx(SUCCESS, "BitState FC : %s",FCDecodeState); } + if (Action == Scramble) { - // PrintAndLogEx(SUCCESS, "Scramble FC : %d - ID %d",*FC,*ID); *CardID = 0; // set to 0 for (CardIdx = 0; CardIdx < 32; CardIdx++) { // Card ID - BitState = (*ID >> CardIdx) & 1; - if (BitState) { - idx = IDToCard[CardIdx]; - if ((idx >= 0) && (idx <= 32)) { - *CardID |= (1 << idx); - } - } - // FC - BitState = (*FC >> CardIdx) & 1; - if (BitState) { - idx = FCToCard[CardIdx]; - if ((idx >= 0) && (idx <= 32)) { - *CardID |= (1 << idx); - } - } + if (CardToID[CardIdx] < 32) { + if ((*ID & (1 << CardToID[CardIdx])) > 0) + *CardID |= (1 << CardIdx); + } + // Card FC + if (CardToFC[CardIdx] < 32) { + if ((*ID & (1 << CardToFC[CardIdx])) > 0) + *CardID |= (1 << CardIdx); + } } - // Fixed bits + + // Fixed bits and parity/check bits /* Add Parity and Fixed bits - Bit 3 - Note Used/Fixed 1 - Bit 31 - 1 Fixed + Bit 3 - Note Used/Fixed 1 - TBC + Bit 31 - 1 Fixed Not in check/parity Bit 0,1 - 2 Bit Parity */ *CardID |= (1 << 3); + // Check/Parity Bits int Parity = 1; for (CardIdx = 4; CardIdx <= 31; CardIdx += 2) { @@ -156,7 +144,7 @@ static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *I // Bit 31 was fixed but not in check/parity bits *CardID |= (1 << 31); - + PrintAndLogEx(SUCCESS, "Scrambled FC : %d - Card ID : %d to RAW : E0000000%08X",*FC,*ID,*CardID); } return PM3_SUCCESS; @@ -224,6 +212,7 @@ static int CmdKeriDemod(const char *Cmd) { uint32_t testCard = 0; CmdKeriMSScramble (Scramble,&fc,&cardid,&testCard); + // End Descramble test if (invert) { From 788e8b7eccea38167caf8d6d5baab52cf9f9c872 Mon Sep 17 00:00:00 2001 From: Joe Harrison Date: Fri, 21 Feb 2020 13:37:43 +0000 Subject: [PATCH 007/298] Remove potentially undefined exit behaviour from analyzesize tool Python2.7 doc for `sys` module states that "Most systems require [the exit code] to be in the range 0-127, and produce undefined results otherwise". Currently, modern Linux-based systems will exit with code 255, while msys2-based systems such as Proxspace will exit with code 127. Instead, explicitly exit with non-zero exit code of 1. --- tools/analyzesize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/analyzesize.py b/tools/analyzesize.py index 889222c01..37024f939 100755 --- a/tools/analyzesize.py +++ b/tools/analyzesize.py @@ -17,7 +17,7 @@ except FileNotFoundError: if len(sys.argv) < 3: print("Usage: analyzesize.py ") - exit(-1) + exit(2) action, name = sys.argv[1:3] currentdata = subprocess.run(["arm-none-eabi-size","armsrc/obj/fullimage.stage1.elf"], stdout=subprocess.PIPE).stdout currentdata = currentdata.split(b"\n")[1].strip() From 15b661dbfb72333fd87fd28481a22e0e20a2c9a8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 21 Feb 2020 15:35:58 +0100 Subject: [PATCH 008/298] plot_edgedetect.py converted to python3 --- fpga/tests/plot_edgedetect.py | 36 +++++++++++------------------------ 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/fpga/tests/plot_edgedetect.py b/fpga/tests/plot_edgedetect.py index 3249de6c2..d5bb34991 100755 --- a/fpga/tests/plot_edgedetect.py +++ b/fpga/tests/plot_edgedetect.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 #----------------------------------------------------------------------------- # Copyright (C) 2014 iZsh # @@ -11,7 +11,7 @@ import matplotlib.pyplot as plt import sys if len(sys.argv) != 2: - print "Usage: %s " % sys.argv[0] + print("Usage: %s " % sys.argv[0]) sys.exit(1) BASENAME = sys.argv[1] @@ -21,29 +21,15 @@ nx = numpy.fromfile(BASENAME + ".time") def plot_time(dat1): plt.plot(nx, dat1) -sig = open(BASENAME + ".filtered").read() -sig = map(lambda x: ord(x), sig) - -min_vals = open(BASENAME + ".min").read() -min_vals = map(lambda x: ord(x), min_vals) - -max_vals = open(BASENAME + ".max").read() -max_vals = map(lambda x: ord(x), max_vals) - -states = open(BASENAME + ".state").read() -states = map(lambda x: ord(x) * 10 + 65, states) - -toggles = open(BASENAME+ ".toggle").read() -toggles = map(lambda x: ord(x) * 10 + 80, toggles) - -high = open(BASENAME + ".high").read() -high = map(lambda x: ord(x), high) -highz = open(BASENAME + ".highz").read() -highz = map(lambda x: ord(x), highz) -lowz = open(BASENAME + ".lowz").read() -lowz = map(lambda x: ord(x), lowz) -low = open(BASENAME + ".low").read() -low = map(lambda x: ord(x), low) +sig = bytearray(open(BASENAME + ".filtered", 'rb').read()) +min_vals = bytearray(open(BASENAME + ".min", 'rb').read()) +max_vals = bytearray(open(BASENAME + ".max", 'rb').read()) +states = bytearray(open(BASENAME + ".state", 'rb').read()) +toggles = bytearray(open(BASENAME+ ".toggle", 'rb').read()) +high = bytearray(open(BASENAME + ".high", 'rb').read()) +highz = bytearray(open(BASENAME + ".highz", 'rb').read()) +lowz = bytearray(open(BASENAME + ".lowz", 'rb').read()) +low = bytearray(open(BASENAME + ".low", 'rb').read()) plot_time(sig) plot_time(min_vals) From 2177211b7a310597ff34ad6ae1eb7765c151019c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 21 Feb 2020 16:06:40 +0100 Subject: [PATCH 009/298] btaddon scripts: warn for pyserial --- tools/btaddon/hc06_console_AT.py | 6 +++++- tools/btaddon/hc06_factory.py | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/btaddon/hc06_console_AT.py b/tools/btaddon/hc06_console_AT.py index 6520aa9aa..4b0d7fd96 100755 --- a/tools/btaddon/hc06_console_AT.py +++ b/tools/btaddon/hc06_console_AT.py @@ -2,7 +2,11 @@ import sys import time -import serial +try: + import serial +except ModuleNotFoundError: + print("Please install pyserial module first.") + sys.exit(1) if len(sys.argv) < 2: print('Usage: %s ' % sys.argv[0]) diff --git a/tools/btaddon/hc06_factory.py b/tools/btaddon/hc06_factory.py index f6d0f25b2..093f25322 100755 --- a/tools/btaddon/hc06_factory.py +++ b/tools/btaddon/hc06_factory.py @@ -1,7 +1,13 @@ #!/usr/bin/env python3 import time -import serial +import sys + +try: + import serial +except ModuleNotFoundError: + print("Please install pyserial module first.") + sys.exit(1) name = b'PM3_RDV4.0' pin = b'1234' From af7fb17607e9d6ff07dd3f2d1efa8fc0ce099433 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 21 Feb 2020 16:10:18 +0100 Subject: [PATCH 010/298] plotedge script: warn for numpy, matplotlib --- fpga/tests/plot_edgedetect.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fpga/tests/plot_edgedetect.py b/fpga/tests/plot_edgedetect.py index d5bb34991..63925bd99 100755 --- a/fpga/tests/plot_edgedetect.py +++ b/fpga/tests/plot_edgedetect.py @@ -6,9 +6,19 @@ # at your option, any later version. See the LICENSE.txt file for the text of # the license. #----------------------------------------------------------------------------- -import numpy -import matplotlib.pyplot as plt + import sys +try: + import numpy +except ModuleNotFoundError: + print("Please install numpy module first.") + sys.exit(1) + +try: + import matplotlib.pyplot as plt +except ModuleNotFoundError: + print("Please install matplotlib module first.") + sys.exit(1) if len(sys.argv) != 2: print("Usage: %s " % sys.argv[0]) From 5527cb2428df3bd7c31bbbd12384942b67398248 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 21 Feb 2020 16:17:56 +0100 Subject: [PATCH 011/298] pm3_mfdread.py script python3 and warn for bitstring module --- tools/pm3_mfdread.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/pm3_mfdread.py b/tools/pm3_mfdread.py index 4172f1812..7e92ea19a 100755 --- a/tools/pm3_mfdread.py +++ b/tools/pm3_mfdread.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # mfdread.py - Mifare dumps parser in human readable format @@ -18,8 +18,11 @@ import copy import sys from collections import defaultdict -from bitstring import BitArray - +try: + from bitstring import BitArray +except ModuleNotFoundError: + print("Please install bitstring module first.") + sys.exit(1) class Options: FORCE_1K = False @@ -28,7 +31,7 @@ class Options: if len(sys.argv) == 1: sys.exit(''' ------------------ -Usage: mfdread.py ./dump.mfd +Usage: pm3_mfdread.py ./dump.mfd Mifare dumps reader. ''') From aa6fc60a22f3b5cbfd0a0aa4255138c14ff07faa Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 21 Feb 2020 16:29:52 +0100 Subject: [PATCH 012/298] xorcheck script converted in python3 + test --- pm3test.sh | 1 + tools/xorcheck.py | 37 +++++++++++++++++-------------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/pm3test.sh b/pm3test.sh index 146650f71..7a623183c 100755 --- a/pm3test.sh +++ b/pm3test.sh @@ -116,6 +116,7 @@ while true; do if ! CheckExecute "mfkey64 test" "tools/mfkey/mfkey64 9c599b32 82a4166c a1e458ce 6eea41e0 5cadf439" "Found Key: \[ffffffffffff\]"; then break; fi if ! CheckExecute "mfkey64 long trace test" "tools/mfkey/./mfkey64 14579f69 ce844261 f8049ccb 0525c84f 9431cc40 7093df99 9972428ce2e8523f456b99c831e769dced09 8ca6827b ab797fd369e8b93a86776b40dae3ef686efd c3c381ba 49e2c9def4868d1777670e584c27230286f4 fbdcd7c1 4abd964b07d3563aa066ed0a2eac7f6312bf 9f9149ea" "Found Key: \[091e639cb715\]"; then break; fi if ! CheckExecute "nonce2key test" "tools/nonce2key/nonce2key e9cadd9c a8bf4a12 a020a8285858b090 050f010607060e07 5693be6c00000000" "key recovered: fc00018778f7"; then break; fi + if ! CheckExecute "xorcheck test" "tools/xorcheck.py 04 00 80 64 ba" "final LRC XOR byte value: 5A"; then break; fi printf "\n${C_GREEN}Tests [OK]${C_NC}\n\n" exit 0 done diff --git a/tools/xorcheck.py b/tools/xorcheck.py index 04c031cf1..205e41ccb 100755 --- a/tools/xorcheck.py +++ b/tools/xorcheck.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # xorcheck.py - find xor values for 8-bit LRC # @@ -24,22 +24,21 @@ import sys import os if(len(sys.argv) < 3): - print - print '\t'+sys.argv[0] + ' - Generate final byte for XOR LRC' - print - print 'Usage: ' + sys.argv[0] + ' ... ' - print - print '\tSpecifying the bytes of a UID with a known LRC will find the last byte value' - print '\tneeded to generate that LRC with a rolling XOR. All bytes should be specified in HEX.' - print - print 'Example:' - print - print '\txorcheck.py 04 00 80 64 ba' - print - print 'Should produce the output:' - print - print '\tTarget (BA) requires final LRC XOR byte value: 5A' - print + print(""" +\t{0} - Generate final byte for XOR LRC + +Usage: {0} ... + +\tSpecifying the bytes of a UID with a known LRC will find the last byte value +\tneeded to generate that LRC with a rolling XOR. All bytes should be specified in HEX. + +Example: + +\t{0} 04 00 80 64 ba + +Should produce the output: + +\tTarget (BA) requires final LRC XOR byte value: 5A\n""".format(sys.argv[0])) os._exit(True) target= int(sys.argv[len(sys.argv) - 1],16) @@ -47,6 +46,4 @@ target= int(sys.argv[len(sys.argv) - 1],16) lrc= 0x00 for i in range(len(sys.argv) - 1): lrc ^= int(sys.argv[i + 1],16) -print -print 'Target (%02X) requires final LRC XOR byte value: %02X' % (target,lrc) -print +print('\nTarget (%02X) requires final LRC XOR byte value: %02X\n' % (target,lrc)) From f28404581dce4d1f7f61e6988d6716ce1d92ea0a Mon Sep 17 00:00:00 2001 From: Joe Harrison Date: Fri, 21 Feb 2020 15:09:36 +0000 Subject: [PATCH 013/298] convert python2 mfd2eml and eml2mfd scripts to python3 --- tools/pm3_eml2mfd.py | 10 +++++----- tools/pm3_eml_mfd_test.py | 14 +++++++------- tools/pm3_mfd2eml.py | 11 +++++------ 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/tools/pm3_eml2mfd.py b/tools/pm3_eml2mfd.py index 4e41604f1..0a12f4788 100755 --- a/tools/pm3_eml2mfd.py +++ b/tools/pm3_eml2mfd.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 ''' # Andrei Costin , 2011 @@ -6,20 +6,20 @@ # Converts PM3 Mifare Classic emulator EML text file to MFD binary dump file ''' -from __future__ import with_statement + import sys import binascii def main(argv): argc = len(argv) if argc < 3: - print 'Usage:', argv[0], 'input.eml output.mfd' + print('Usage:', argv[0], 'input.eml output.mfd') sys.exit(1) - with file(argv[1], "r") as file_inp, file(argv[2], "wb") as file_out: + with open(argv[1], "r") as file_inp, open(argv[2], "wb") as file_out: for line in file_inp: line = line.rstrip('\n').rstrip('\r') - print line + print(line) data = binascii.unhexlify(line) file_out.write(data) diff --git a/tools/pm3_eml_mfd_test.py b/tools/pm3_eml_mfd_test.py index 4be66e83a..c08f0f9a1 100755 --- a/tools/pm3_eml_mfd_test.py +++ b/tools/pm3_eml_mfd_test.py @@ -1,9 +1,9 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 + -from __future__ import with_statement from tempfile import mkdtemp from shutil import rmtree -from itertools import imap + from string import hexdigits import unittest, os import pm3_eml2mfd, pm3_mfd2eml @@ -24,18 +24,18 @@ class TestEmlMfd(unittest.TestCase): def test_mfd2eml(self): self.three_argument_test(pm3_mfd2eml.main, - imap(reversed, self.EML2MFD_TESTCASES), c14n=hex_c14n) + map(reversed, self.EML2MFD_TESTCASES), c14n=hex_c14n) def three_argument_test(self, operation, cases, c14n=str): for case_input, case_output in cases: try: inp_name = os.path.join(self.tmpdir, 'input') out_name = os.path.join(self.tmpdir, 'output') - with file(inp_name, 'wb') as in_file: + with open(inp_name, 'w') as in_file: in_file.write(case_input) operation(['', inp_name, out_name]) - with file(out_name, 'rb') as out_file: - self.assertEquals(c14n(case_output), c14n(out_file.read())) + with open(out_name, 'r') as out_file: + self.assertEqual(c14n(case_output), c14n(out_file.read())) finally: for file_name in inp_name, out_name: if os.path.exists(file_name): diff --git a/tools/pm3_mfd2eml.py b/tools/pm3_mfd2eml.py index a2d8389fa..52d858df0 100755 --- a/tools/pm3_mfd2eml.py +++ b/tools/pm3_mfd2eml.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 ''' # Andrei Costin , 2011 @@ -6,24 +6,23 @@ # Converts PM3 Mifare Classic MFD binary dump file to emulator EML text file ''' -from __future__ import with_statement + import sys -import binascii READ_BLOCKSIZE = 16 def main(argv): argc = len(argv) if argc < 3: - print 'Usage:', argv[0], 'input.mfd output.eml' + print('Usage:', argv[0], 'input.mfd output.eml') sys.exit(1) - with file(argv[1], "rb") as file_inp, file(argv[2], "w") as file_out: + with open(argv[1], "rb") as file_inp, open(argv[2], "w") as file_out: while True: byte_s = file_inp.read(READ_BLOCKSIZE) if not byte_s: break - hex_char_repr = binascii.hexlify(byte_s) + hex_char_repr = byte_s.hex() file_out.write(hex_char_repr) file_out.write("\n") From ba6f58cc059fb7ebe097d749d966870a23161fa1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 21 Feb 2020 16:45:00 +0100 Subject: [PATCH 014/298] findbits converted to python3 + tests --- pm3test.sh | 2 ++ tools/findbits.py | 50 ++++++++++++++++++++---------------------- tools/findbits_test.py | 5 ++--- 3 files changed, 28 insertions(+), 29 deletions(-) mode change 100644 => 100755 tools/findbits_test.py diff --git a/pm3test.sh b/pm3test.sh index 7a623183c..cf560e74a 100755 --- a/pm3test.sh +++ b/pm3test.sh @@ -117,6 +117,8 @@ while true; do if ! CheckExecute "mfkey64 long trace test" "tools/mfkey/./mfkey64 14579f69 ce844261 f8049ccb 0525c84f 9431cc40 7093df99 9972428ce2e8523f456b99c831e769dced09 8ca6827b ab797fd369e8b93a86776b40dae3ef686efd c3c381ba 49e2c9def4868d1777670e584c27230286f4 fbdcd7c1 4abd964b07d3563aa066ed0a2eac7f6312bf 9f9149ea" "Found Key: \[091e639cb715\]"; then break; fi if ! CheckExecute "nonce2key test" "tools/nonce2key/nonce2key e9cadd9c a8bf4a12 a020a8285858b090 050f010607060e07 5693be6c00000000" "key recovered: fc00018778f7"; then break; fi if ! CheckExecute "xorcheck test" "tools/xorcheck.py 04 00 80 64 ba" "final LRC XOR byte value: 5A"; then break; fi + if ! CheckExecute "findbits test" "tools/findbits.py 73 0110010101110011" "Match at bit 9: 011001010"; then break; fi + if ! CheckExecute "findbits_test test" "tools/findbits_test.py 2>&1" "OK"; then break; fi printf "\n${C_GREEN}Tests [OK]${C_NC}\n\n" exit 0 done diff --git a/tools/findbits.py b/tools/findbits.py index d3f4c6bcd..809465a2e 100755 --- a/tools/findbits.py +++ b/tools/findbits.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # findbits.py - find Binary, Octal, Decimal or Hex number in bitstream # @@ -31,10 +31,9 @@ def invert(data): def search(target,data): location = data.find(target) if location >= 0: - print '*** Match at bit %d:' % location, - print '%s<%s>%s' % (data[:location],target,data[location+len(target):]) + print('*** Match at bit {:d}: {}<{}>{}'.format(location, data[:location],target,data[location+len(target):])) else: - print 'Not found' + print('Not found') # convert integer to binary string def binstring(number): @@ -49,32 +48,32 @@ def domatch(binary,number): reversed= stringreverse(number) inverted= invert(binary) - print ' Forward: (%s)' % number, + print(' Forward: (%s) ' % number, end = '') search(binary,number) - print ' Reverse: (%s)' % reversed, + print(' Reverse: (%s) ' % reversed, end = '') search(binary,reversed) - print ' Inverse: (%s)' % inverted - print ' Forward: (%s)' % number, + print(' Inverse: (%s) ' % inverted) + print(' Forward: (%s) ' % number, end = '') search(inverted,number) - print ' Reverse: (%s)' % reversed, + print(' Reverse: (%s) ' % reversed, end = '') search(inverted,reversed) def main(): if(len(sys.argv) < 3): - print - print '\t'+sys.argv[0] + ' - Search bitstream for a known number' - print - print 'Usage: ' + sys.argv[0] + ' ' - print - print '\tNUMBER will be converted to it\'s BINARY equivalent for all valid' - print '\tinstances of BINARY, OCTAL, DECIMAL and HEX, and the bitstream' - print '\tand it\'s inverse will be searched for a pattern match. Note that' - print '\tNUMBER must be specified in BINARY to match leading zeros.' - print - print 'Example:' - print - print '\tfindbits.py 73 0110010101110011' - print + print(""" +\t{0} - Search bitstream for a known number + +Usage: {0} + +\tNUMBER will be converted to it\'s BINARY equivalent for all valid +\tinstances of BINARY, OCTAL, DECIMAL and HEX, and the bitstream +\tand it\'s inverse will be searched for a pattern match. Note that +\tNUMBER must be specified in BINARY to match leading zeros. + +Example: + +\t{0} 73 0110010101110011 +""".format(sys.argv[0])) os._exit(True) bases= { @@ -84,11 +83,10 @@ def main(): 16:'HEX', } - for base, base_name in sorted(bases.iteritems()): + for base, base_name in sorted(bases.items()): try: number= int(sys.argv[1],base) - print - print 'Trying', base_name + print('\nTrying ' + base_name) # do BINARY as specified to preserve leading zeros if base == 2: domatch(sys.argv[1],sys.argv[2]) diff --git a/tools/findbits_test.py b/tools/findbits_test.py old mode 100644 new mode 100755 index d52334fd4..403dae413 --- a/tools/findbits_test.py +++ b/tools/findbits_test.py @@ -1,6 +1,5 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 -from itertools import imap import unittest, sys, findbits class TestFindBits(unittest.TestCase): @@ -46,7 +45,7 @@ class TestFindBits(unittest.TestCase): def commutative_test(self, operation, cases): self.unary_operation_test(operation, cases) - self.unary_operation_test(operation, imap(reversed, cases)) + self.unary_operation_test(operation, map(reversed, cases)) def unary_operation_test(self, operation, cases): for case_in, case_out in cases: From efc738ab9311271709e5c34795ca85bc3db4d36e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 21 Feb 2020 16:52:26 +0100 Subject: [PATCH 015/298] add test --- pm3test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/pm3test.sh b/pm3test.sh index cf560e74a..6a2256192 100755 --- a/pm3test.sh +++ b/pm3test.sh @@ -119,6 +119,7 @@ while true; do if ! CheckExecute "xorcheck test" "tools/xorcheck.py 04 00 80 64 ba" "final LRC XOR byte value: 5A"; then break; fi if ! CheckExecute "findbits test" "tools/findbits.py 73 0110010101110011" "Match at bit 9: 011001010"; then break; fi if ! CheckExecute "findbits_test test" "tools/findbits_test.py 2>&1" "OK"; then break; fi + if ! CheckExecute "pm3_eml_mfd test" "tools/pm3_eml_mfd_test.py 2>&1" "OK"; then break; fi printf "\n${C_GREEN}Tests [OK]${C_NC}\n\n" exit 0 done From a38d5f0839a402945870a85897d2c898e68ff1d5 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 21 Feb 2020 17:07:14 +0100 Subject: [PATCH 016/298] attempt to fix travis build on osx --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1cb60f8e9..663f1036c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,6 +41,8 @@ addons: - qt5 - RfidResearchGroup/proxmark3/arm-none-eabi-gcc taps: RfidResearchGroup/proxmark3 +# update trick to fix https://travis-ci.community/t/macos-build-fails-because-of-homebrew-bundle-unknown-command/7296/14 + update: true install: if ! arm-none-eabi-gcc -v; then From ae57feeee6789b35addf09fab00859ab36bfb0a7 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 21 Feb 2020 17:31:55 +0100 Subject: [PATCH 017/298] attempt to fix travis build on osx --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 663f1036c..eba0c5d99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,7 @@ addons: - libsndfile1-dev homebrew: packages: + - python3 - readline - libsndfile - qt5 From 2804a7dbadc9ad08524d0ef8569d7c7a2695e260 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 21 Feb 2020 22:15:35 +0100 Subject: [PATCH 018/298] hopefully fixes travis for OSX --- .travis.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index eba0c5d99..5aee2a918 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,6 @@ addons: - libsndfile1-dev homebrew: packages: - - python3 - readline - libsndfile - qt5 @@ -45,6 +44,14 @@ addons: # update trick to fix https://travis-ci.community/t/macos-build-fails-because-of-homebrew-bundle-unknown-command/7296/14 update: true +before_install: + # bug? + # homebrew update replaced python2.7 by python3.7 but + # python3 link failed while python@2 still present, so let's do it again: + if [ "$TRAVIS_OS_NAME" == "osx" ]; then + brew link --overwrite python; + fi + install: if ! arm-none-eabi-gcc -v; then echo "arm-none-eabi-gcc [ERROR]"; From 2ec4bc9a0e5c1b9c9971d0ebfa9ee258aaf05fe6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 22 Feb 2020 13:14:43 +0100 Subject: [PATCH 019/298] old->mix --- armsrc/i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/i2c.c b/armsrc/i2c.c index 2cd3c6f3e..3d1f050c3 100644 --- a/armsrc/i2c.c +++ b/armsrc/i2c.c @@ -709,7 +709,7 @@ void SmartCardAtr(void) { set_tracing(true); I2C_Reset_EnterMainProgram(); bool isOK = GetATR(&card); - reply_old(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t)); + reply_mix(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t)); set_tracing(false); LEDsoff(); } @@ -760,7 +760,7 @@ void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data) { } } OUT: - reply_old(CMD_ACK, len, 0, 0, resp, len); + reply_mix(CMD_ACK, len, 0, 0, resp, len); BigBuf_free(); set_tracing(false); LEDsoff(); From b304adeecabaceda477ebf019b35437f46f5f78a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 22 Feb 2020 13:16:04 +0100 Subject: [PATCH 020/298] hitag, determine adc levels to get better demodulation --- armsrc/lfadc.c | 39 +++++++++++++++++++++++++++++---------- armsrc/lfadc.h | 1 + 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 04f293e1d..6b0eb930a 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -10,6 +10,7 @@ #include "lfsampling.h" #include "fpgaloader.h" #include "ticks.h" +#include "dbprint.h" // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz @@ -46,13 +47,28 @@ bool lf_test_periods(size_t expected, size_t count) { // Low frequency (LF) adc passthrough functionality ////////////////////////////////////////////////////////////////////////////// uint8_t previous_adc_val = 0; +uint8_t adc_avg = 0; + +void lf_sample_mean(void) { + uint8_t periods = 0; + uint32_t adc_sum = 0; + while (periods < 32) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + adc_sum += AT91C_BASE_SSC->SSC_RHR; + periods++; + } + } + // division by 32 + adc_avg = adc_sum >> 5; + + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("LF ADC average %u", adc_avg); +} size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { size_t periods = 0; volatile uint8_t adc_val; - //uint8_t avg_peak = 140, avg_through = 96; - // 140 - 127 - 114 - uint8_t avg_peak = 140, avg_through = 106; + uint8_t avg_peak = adc_avg + 3, avg_through = adc_avg - 3; int16_t checked = 0; while (!BUTTON_PRESS()) { @@ -98,8 +114,8 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { } } } - previous_adc_val = adc_val; + if (periods >= max) return 0; } } @@ -131,8 +147,9 @@ void lf_reset_counter() { bool lf_get_tag_modulation() { return (rising_edge == false); } + bool lf_get_reader_modulation() { - return rising_edge; + return rising_edge; } void lf_wait_periods(size_t periods) { @@ -147,7 +164,7 @@ void lf_init(bool reader, bool simulate) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_134); if (reader) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); } else { @@ -168,8 +185,8 @@ void lf_init(bool reader, bool simulate) { // When in reader mode, give the field a bit of time to settle. // 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered. if (reader) { - // 50 ms - SpinDelay(50); + // 10 ms + SpinDelay(10); } // Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation @@ -195,7 +212,7 @@ void lf_init(bool reader, bool simulate) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // Prepare data trace - uint32_t bufsize = 20000; + uint32_t bufsize = 10000; // use malloc if (logging) initSampleBufferEx(&bufsize, true); @@ -203,6 +220,8 @@ void lf_init(bool reader, bool simulate) { sample_config *sc = getSamplingConfig(); sc->decimation = 1; sc->averaging = 0; + + lf_sample_mean(); } void lf_finalize() { @@ -275,7 +294,7 @@ static void lf_manchester_send_bit(uint8_t bit) { lf_modulation(bit != 0); lf_wait_periods(16); lf_modulation(bit == 0); - lf_wait_periods(16); + lf_wait_periods(32); } // simulation diff --git a/armsrc/lfadc.h b/armsrc/lfadc.h index 8c33aa778..09e5762c6 100644 --- a/armsrc/lfadc.h +++ b/armsrc/lfadc.h @@ -17,6 +17,7 @@ extern bool logging; +void lf_sample_mean(void); bool lf_test_periods(size_t expected, size_t count); size_t lf_count_edge_periods(size_t max); size_t lf_detect_gap(size_t max); From e56f14fe4d4af39a312ec5ab727548524c741de1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 22 Feb 2020 13:16:36 +0100 Subject: [PATCH 021/298] textual --- client/cmdhf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index e90f2ea28..78ebbd256 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -179,7 +179,7 @@ int CmdHFTune(const char *Cmd) { int iter = param_get32ex(Cmd, 0, 0, 10); PacketResponseNG resp; - PrintAndLogEx(SUCCESS, "Measuring HF antenna," _YELLOW_("click button") " or press" _YELLOW_("Enter") "to exit"); + PrintAndLogEx(SUCCESS, "Measuring HF antenna, " _YELLOW_("click button") " or press " _YELLOW_("Enter") "to exit"); clearCommandBuffer(); uint8_t mode[] = {1}; SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_HF, mode, sizeof(mode)); From 004b4ae3c9a2a5e3047cfcf97447619ad33bb788 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 22 Feb 2020 13:17:36 +0100 Subject: [PATCH 022/298] textual --- client/loclass/cipherutils.c | 8 ++++---- client/loclass/ikeys.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/loclass/cipherutils.c b/client/loclass/cipherutils.c index 5f16b68fd..09f4bccd7 100644 --- a/client/loclass/cipherutils.c +++ b/client/loclass/cipherutils.c @@ -160,12 +160,12 @@ void printarr(const char *name, uint8_t *arr, int len) { cx += snprintf(output + cx, outsize - cx, "0x%02x,", *(arr + i)); //5 bytes per byte } snprintf(output + cx, outsize - cx, "};"); - PrintAndLogEx(NORMAL, output); + PrintAndLogEx(INFO, output); free(output); } void printvar(const char *name, uint8_t *arr, int len) { - PrintAndLogEx(NORMAL, "%s = " _YELLOW_("%s"), name, sprint_hex(arr, len)); + PrintAndLogEx(INFO, "%s = " _YELLOW_("%s"), name, sprint_hex(arr, len)); } void printarr_human_readable(const char *title, uint8_t *arr, int len) { @@ -175,13 +175,13 @@ void printarr_human_readable(const char *title, uint8_t *arr, int len) { int cx = 0, i; size_t outsize = 100 + strlen(title) + len * 4; char *output = calloc(outsize, sizeof(char)); - PrintAndLogEx(NORMAL, "\n %s", title); + PrintAndLogEx(INFO, "%s", title); for (i = 0; i < len; i++) { if (i % 16 == 0) cx += snprintf(output + cx, outsize - cx, "\n%02x| ", i); cx += snprintf(output + cx, outsize - cx, "%02x ", *(arr + i)); } - PrintAndLogEx(NORMAL, output); + PrintAndLogEx(INFO, output); free(output); } diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 339ea91f7..9d9926547 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -199,7 +199,6 @@ static uint64_t check(uint64_t z) { ck2 &= 0x00000000FFFFFF000000; return ck1 | ck2 >> 24; - } static void permute(BitstreamIn *p_in, uint64_t z, int l, int r, BitstreamOut *out) { @@ -219,6 +218,7 @@ static void permute(BitstreamIn *p_in, uint64_t z, int l, int r, BitstreamOut *o permute(p_in, z, l, r + 1, out); } } + static void printbegin() { if (debug_print < 2) return; From 7378ea531a4d14b346a5e545b59088d29a8f6af2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 22 Feb 2020 13:18:59 +0100 Subject: [PATCH 023/298] hide function xor since it interfers with native xor funtions --- client/util.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/util.h b/client/util.h index 21db9198f..fb31e6013 100644 --- a/client/util.h +++ b/client/util.h @@ -23,6 +23,7 @@ uint8_t g_debugMode; uint8_t g_printAndLog; + #define PRINTANDLOG_PRINT 1 #define PRINTANDLOG_LOG 2 @@ -85,7 +86,7 @@ uint8_t GetParity(uint8_t *bits, uint8_t type, int length); void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length); void wiegand_add_parity_swapped(uint8_t *target, uint8_t *source, uint8_t length); -void xor(unsigned char *dst, unsigned char *src, size_t len); +//void xor(unsigned char *dst, unsigned char *src, size_t len); int32_t le24toh(uint8_t data[3]); uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bits); From 181a659bc069ac731aee10f42f0efededdfa7eac Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 22 Feb 2020 13:32:42 +0100 Subject: [PATCH 024/298] trying another loop --- armsrc/lfsampling.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index c492a4eda..2e33ec434 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -253,11 +253,11 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in uint32_t cancel_counter = 0; int16_t checked = 0; - while (true) { + while (!BUTTON_PRESS()) { // only every 1000th times, in order to save time when collecting samples. if (checked == 1000) { - if (BUTTON_PRESS() || data_available()) { + if (data_available()) { checked = -1; break; } else { From 802e62285baae746a392951d7e2f78626b2eab46 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 22 Feb 2020 13:34:15 +0100 Subject: [PATCH 025/298] debug print hitag2 for cleaner client outputs --- armsrc/hitag2.c | 152 ++++++++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 71 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 8a0d4934a..37c716efb 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -20,6 +20,8 @@ // Anon, 2019 // Doegox, 2020 +#define DBG if (DBGLEVEL >= DBG_EXTENDED) + #include "hitag2.h" #include "hitag2_crypto.h" #include "string.h" @@ -305,6 +307,9 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ break; } + // LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); + // LogTrace(tx, nbytes(txlen), 0, 0, NULL, true); + if (tag.crypto_active) { hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8); } @@ -337,12 +342,12 @@ static uint32_t hitag_reader_send_bit(int bit) { lf_wait_periods(HITAG_T_1 - HITAG_T_LOW); // wait for 26-32 times the carrier period wait += HITAG_T_1 - HITAG_T_LOW; } - /*lf_wait_periods(10);*/ + LED_A_OFF(); return wait; } -// reader/writer +// reader / writer commands static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { uint32_t wait = 0; @@ -953,17 +958,18 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t memcpy(tag.sectors[blocknr], rx, 4); blocknr++; - Dbhexdump(4, rx, false); + DBG Dbhexdump(4, rx, false); } if (blocknr > 0) { + DBG DbpString("Read successful!"); bSuccessful = true; - return false; + return true; } } break; // Unexpected response default: { - Dbprintf("Unknown frame length: %d", rxlen); + DBG Dbprintf("Unknown frame length: %d", rxlen); return false; } break; @@ -1017,7 +1023,7 @@ void SniffHitag2(void) { // Receive frame, watch for at most T0*EOF periods - lf_reset_counter(); +// lf_reset_counter(); // Wait "infinite" for reader modulation periods = lf_detect_gap(20000); @@ -1071,8 +1077,6 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { DbpString("Starting Hitag2 simulation"); - LED_D_ON(); - // hitag2 state machine? hitag2_init(); @@ -1094,21 +1098,25 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { Dbprintf("| %d | %08x |", i, block); } - uint8_t tag_modulation; + uint8_t reader_modulation; size_t max_nrzs = 8 * HITAG_FRAME_LEN + 5; uint8_t nrz_samples[max_nrzs]; size_t nrzs = 0, periods = 0; // uint32_t command_start = 0, command_duration = 0; + // int16_t checked = 0; - int16_t checked = 0; +// SIMULATE while (!BUTTON_PRESS()) { -loop1: + LED_D_ON(); + +// lf_reset_counter(); LED_A_OFF(); WDT_HIT(); +/* // only every 1000th times, in order to save time when collecting samples. if (checked == 100) { if (data_available()) { @@ -1119,6 +1127,7 @@ loop1: } } ++checked; +*/ rxlen = 0; @@ -1126,10 +1135,10 @@ loop1: bool waiting_for_first_edge = true; // Did we detected any modulaiton at all - bool detected_tag_modulation = false; + bool detected_modulation = false; // Use the current modulation state as starting point - tag_modulation = lf_get_tag_modulation(); + reader_modulation = lf_get_reader_modulation(); // Receive frame, watch for at most max_nrzs periods // Reset the number of NRZ samples and use edge detection to detect them @@ -1141,7 +1150,7 @@ loop1: // Just break out of loop after an initial time-out (tag is probably not available) // The function lf_count_edge_periods() returns 0 when a time-out occurs if (periods == 0) { - goto loop1; //break; + break; } LED_A_ON(); @@ -1159,32 +1168,36 @@ loop1: periods = 16; // We have received more than 0 periods, so we have detected a tag response - detected_tag_modulation = true; + detected_modulation = true; } // Evaluate the number of periods before the next edge if (periods > 24 && periods <= 64) { // Detected two sequential equal bits and a modulation switch // NRZ modulation: (11 => --|) or (11 __|) - nrz_samples[nrzs++] = tag_modulation; - nrz_samples[nrzs++] = tag_modulation; + nrz_samples[nrzs++] = reader_modulation; + nrz_samples[nrzs++] = reader_modulation; // Invert tag modulation state - tag_modulation ^= 1; + reader_modulation ^= 1; } else if (periods > 0 && periods <= 24) { // Detected one bit and a modulation switch // NRZ modulation: (1 => -|) or (0 _|) - nrz_samples[nrzs++] = tag_modulation; - tag_modulation ^= 1; + nrz_samples[nrzs++] = reader_modulation; + reader_modulation ^= 1; } else { - tag_modulation ^= 1; + reader_modulation ^= 1; // The function lf_count_edge_periods() returns > 64 periods, this is not a valid number periods Dbprintf("Detected unexpected period count: %d", periods); break; } } + LED_D_OFF(); + // If there is no response, just repeat the loop - if (!detected_tag_modulation) continue; + if (!detected_modulation) continue; + + LED_A_OFF(); // Make sure we always have an even number of samples. This fixes the problem // of ending the manchester decoding with a zero. See the example below where @@ -1194,7 +1207,7 @@ loop1: // The last modulation change of a zero is not detected, but we should take // the half period in account, otherwise the demodulator will fail. if ((nrzs % 2) != 0) { - nrz_samples[nrzs++] = tag_modulation; + nrz_samples[nrzs++] = reader_modulation; } LED_B_ON(); @@ -1233,8 +1246,8 @@ loop1: // not that since the clock counts since the rising edge, but T_Wait1 is // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low) // periods. The gap time T_Low varies (4..10). All timer values are in - // terms of T0 units - lf_wait_periods(200); + // terms of T0 units (HITAG_T_WAIT_1_MIN - HITAG_T_LOW ) + lf_wait_periods(HITAG_T_WAIT_1_MIN); // Send and store the tag answer (if there is any) if (txlen) { @@ -1266,15 +1279,15 @@ loop1: void ReaderHitag(hitag_function htf, hitag_data *htd) { - uint32_t command_start = 0; - uint32_t command_duration = 0; - uint32_t response_start = 0; - uint32_t response_duration = 0; + uint32_t command_start = 0, command_duration = 0; + uint32_t response_start = 0, response_duration = 0; + uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t txbuf[HITAG_FRAME_LEN]; uint8_t *tx = txbuf; size_t txlen = 0; + int t_wait_1; int t_wait_1_guard = 8; int t_wait_2; @@ -1292,19 +1305,17 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { set_tracing(true); clear_trace(); - DbpString("Starting Hitag reader family"); - // Check configuration switch (htf) { case RHT1F_PLAIN: { - Dbprintf("Read public blocks in plain mode"); + DBG Dbprintf("Read public blocks in plain mode"); // this part will be unreadable memset(tag.sectors + 2, 0x0, 30); blocknr = 0; break; } case RHT1F_AUTHENTICATE: { - Dbprintf("Read all blocks in authed mode"); + DBG Dbprintf("Read all blocks in authed mode"); memcpy(nonce, htd->ht1auth.nonce, 4); memcpy(key, htd->ht1auth.key, 4); memcpy(logdata_0, htd->ht1auth.logdata_0, 4); @@ -1314,19 +1325,19 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { memset(logdata_1, 0x00, 4); byte_value = 0; key_no = htd->ht1auth.key_no; - Dbprintf("Authenticating using key #%d:", key_no); - Dbhexdump(4, key, false); - DbpString("Nonce:"); - Dbhexdump(4, nonce, false); - DbpString("Logdata_0:"); - Dbhexdump(4, logdata_0, false); - DbpString("Logdata_1:"); - Dbhexdump(4, logdata_1, false); + DBG Dbprintf("Authenticating using key #%d:", key_no); + DBG Dbhexdump(4, key, false); + DBG DbpString("Nonce:"); + DBG Dbhexdump(4, nonce, false); + DBG DbpString("Logdata_0:"); + DBG Dbhexdump(4, logdata_0, false); + DBG DbpString("Logdata_1:"); + DBG Dbhexdump(4, logdata_1, false); blocknr = 0; break; } case RHT2F_PASSWORD: { - Dbprintf("List identifier in password mode"); + DBG Dbprintf("List identifier in password mode"); if (memcmp(htd->pwd.password, "\x00\x00\x00\x00", 4) == 0) memcpy(password, tag.sectors[1], sizeof(password)); else @@ -1338,19 +1349,19 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { break; } case RHT2F_AUTHENTICATE: { - DbpString("Authenticating using nr,ar pair:"); + DBG DbpString("Authenticating using nr,ar pair:"); memcpy(NrAr, htd->auth.NrAr, 8); - Dbhexdump(8, NrAr, false); + DBG Dbhexdump(8, NrAr, false); bCrypto = false; bAuthenticating = false; break; } case RHT2F_CRYPTO: { - DbpString("Authenticating using key:"); + DBG DbpString("Authenticating using key:"); memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code. - Dbhexdump(6, key, false); - DbpString("Nonce:"); - Dbhexdump(4, nonce, false); + DBG Dbhexdump(6, key, false); + DBG DbpString("Nonce:"); + DBG Dbhexdump(4, nonce, false); memcpy(nonce, htd->crypto.data, 4); blocknr = 0; bCrypto = false; @@ -1358,7 +1369,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { break; } case RHT2F_TEST_AUTH_ATTEMPTS: { - Dbprintf("Testing %d authentication attempts", (auth_table_len / 8)); + DBG Dbprintf("Testing %d authentication attempts", (auth_table_len / 8)); auth_table_pos = 0; memcpy(NrAr, auth_table, 8); bCrypto = false; @@ -1371,7 +1382,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { break; } default: { - Dbprintf("Error, unknown function: %d", htf); + DBG Dbprintf("Error, unknown function: %d", htf); set_tracing(false); return; } @@ -1382,9 +1393,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // hitag2 state machine? hitag2_init(); - // init as reader - lf_init(true, false); - uint8_t attempt_count = 0; // Tag specific configuration settings (sof, timings, etc.) @@ -1395,38 +1403,41 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { /*tag_size = 256;*/ flipped_bit = 0; tag_size = 8; - DbpString("Configured for hitagS reader"); + DBG DbpString("Configured for hitagS reader"); } else if (htf < 20) { // hitag1 settings t_wait_1 = 204; t_wait_2 = 128; tag_size = 256; flipped_bit = 0; - DbpString("Configured for hitag1 reader"); + DBG DbpString("Configured for hitag1 reader"); } else if (htf < 30) { // hitag2 settings t_wait_1 = HITAG_T_WAIT_1_MIN; t_wait_2 = HITAG_T_WAIT_2_MIN; tag_size = 48; - DbpString("Configured for hitag2 reader"); + DBG DbpString("Configured for hitag2 reader"); } else { - Dbprintf("Error, unknown hitag reader type: %d", htf); + DBG Dbprintf("Error, unknown hitag reader type: %d", htf); return; } + // init as reader + lf_init(true, false); + uint8_t tag_modulation; size_t max_nrzs = (8 * HITAG_FRAME_LEN + 5) * 2; // up to 2 nrzs per bit uint8_t nrz_samples[max_nrzs]; size_t nrzs = 0; int16_t checked = 0; - while (!bStop) { + while (!bStop && !BUTTON_PRESS()) { WDT_HIT(); // only every 1000th times, in order to save time when collecting samples. if (checked == 1000) { - if (BUTTON_PRESS() || data_available()) { + if (data_available()) { checked = -1; break; } else { @@ -1471,7 +1482,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { break; } default: { - Dbprintf("Error, unknown function: %d", htf); + DBG Dbprintf("Error, unknown function: %d", htf); goto out; } } @@ -1531,7 +1542,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } else { // The function lf_count_edge_periods() returns 0 when a time-out occurs if (periods == 0) { - //Dbprintf("Detected timeout after [%d] nrz samples", nrzs); + DBG Dbprintf("Detected timeout after [%d] nrz samples", nrzs); break; } } @@ -1552,7 +1563,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { tag_modulation ^= 1; } else { // The function lf_count_edge_periods() returns > 64 periods, this is not a valid number periods - //Dbprintf("Detected unexpected period count: %d", periods); + DBG Dbprintf("Detected unexpected period count: %d", periods); break; } } @@ -1591,13 +1602,13 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Verify if the header consists of five consecutive ones if (nrzs < 5) { - Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs); + DBG Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs); break; } else { size_t i; for (i = 0; i < 5; i++) { if (nrz_samples[i] != 1) { - Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one, abort", i); + DBG Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one, abort", i); break; } } @@ -1608,7 +1619,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { for (size_t i = 5; i < nrzs; i++) { uint8_t bit = nrz_samples[i]; if (bit > 1) { // When Manchester detects impossible symbol it writes "7" - Dbprintf("Error in Manchester decoding, abort"); + DBG Dbprintf("Error in Manchester decoding, abort"); break; } rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); @@ -1671,8 +1682,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { set_tracing(true); clear_trace(); - DbpString("Starting Hitag writer family"); - + // Check configuration switch (htf) { case WHT2F_CRYPTO: { @@ -1710,7 +1720,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // init as reader lf_init(true, false); - + // Tag specific configuration settings (sof, timings, etc.) if (htf < 10) { // hitagS settings @@ -1734,7 +1744,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { tag_size = 48; DbpString("Configured for hitag2 writer"); } else { - Dbprintf("Error, unknown hitag writer type: %d", htf); + DBG Dbprintf("Error, unknown hitag writer type: %d", htf); return; } @@ -1744,11 +1754,11 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { size_t nrzs = 0; int16_t checked = 0; - while (!bStop) { + while (!bStop && !BUTTON_PRESS()) { // only every 1000th times, in order to save time when collecting samples. if (checked == 1000) { - if (BUTTON_PRESS() || data_available()) { + if (data_available()) { checked = -1; break; } else { From 3f0f08ffbb95a4d3dc288cbb7f45d1a2bba23316 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 22 Feb 2020 13:34:52 +0100 Subject: [PATCH 026/298] updated fpga lf image for hitag --- fpga/fpga_lf.bit | Bin 42175 -> 42175 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/fpga/fpga_lf.bit b/fpga/fpga_lf.bit index dd64db8a7762141fcee85b6fb5cb9af3a4705313..ba6b4322e6d470175b46d7116b49ddceaa3408f3 100644 GIT binary patch literal 42175 zcmb@ve|Q|#c`yFXnOS+XyYh}@iz>l5qm`hGSxIZz7{`&NvFy+dc4L*0)a^IV{Vv39 z-Cmk2(%gHU-rVG9CGZ-VdI7g}5;t8NCs7h7UCR#s!LP9pAdJ9*aubITvQUL6)JYcO zfNTuDpZCn}?8o7z76nN4&X1v~y`Y2v@#u_Te8&rql%(UEAkJK8%sXcN^g=~#LFl9fxA z(Vr3R>$`~GcfRt;KTnX~2kv%l}NJe_xv*v{(LFOOQjo)bbgs zx48Lt{0yo7MSbt@`1jmwNc<0xQ2+Zo{>PE(U;H2Ykk_aFcRWHh8~?BRsHa`5cY-`_ zNj5={B1Z*UL30U0tb0)PaRX=QqU2P8(3$M{oy6sg61tYouS5}u<3!{%3w2W;mdi^tP*njWL5H=gg(%HtT}8Ehc@3W3#X zUbPAFoO6(d-F1nmKd%{VG5l<;o({{_LTHP4g$@rk6|USOUZ8KuYq@3Idrs0MdW$;U zI(#4JEwRFlB=iY-94(PV^9$a_ajrU0H7|dHo-ip={I21^l&pLod%3$KuV2u3UITgk z4R5`Y^L84CwN^LOCtjw*R+GC9g4jx`R}0 z1!Kk@!Qht`HD#@JOg5cSvXPFFN+R)yZ2@L zTS}>}eYhb0Oduh3cu6 zit%*brA6)r7*9&@yfmvwCuyk*n|a(BgnSwPQ!F1*q#7QM6gRf@c>b?A~ zTtkuGQ6rpRR6`9FoBc6Q*Yt58#;*z4-4q$uFUXU(Ep@{)^WQfWqPcpaj9<^ukYu!? zi_VUY=3+3@^BNtIZB4NAw)dSg&{N4HBrFrgJZahx9`IVCW&9fM2U<}mUw>MCgy4O^ zL1?ZW+9?v=x;qW8(bM&?bzhl(T0Db=3+MG|HlK)}1&DmUWl zXX!ob_njS2hkX3n=R9q9JsG(V826Ncg;NIB?#e{61CyS9jR#_Mx7lWe_N6b-4r+Eo ze=nw-qsg|LL%S;Ym6Z26aVr!P6N1-b-3P>z&H*=`3T1?kU(4z5Wosd{5%{%LHWfmf z#Y^;{Y|TON@heO(P^TNQ6>KHk2{B_P9eSu@Jfg zMYBb{_nlq(dIi4@^O!TDgSN{i8$g!#^o#K;pNvz8(!Bk6A4bE$0m`|dCE`9q?PuT@ z>rNTJIv|8%bi#n}%g{0JT}gn}1?twYOs=Jjo~xgs3$oje3~D!f`ej6aN$ zBUEF?yqYjUQJRG%gr{GP4Ts={@!S<;WA2keeGNBc_0)K4k!zST@ttpG7&T{)XSW_J z;g`0LN7%=G#GCY}2V`h*B3}vl_;o;D5ZxB9DPXIE!ehExWr_@jf}VcGpkK$#wwtk%0iDfowv!9T1kjb|*hM)&b+H$CVf?90w!7<`QR zr=?k7f;QV;d%>tYz_tZ*H(0-FO)*ON8g|GK8E@T(8}``e@?9;Fztb7NMr2(^FJz!Z zH%A^TW2L0ibly>xpZj252L^7ZcN@Dh8wN4K1iwqe-hGd{Wu&l`A>g3&oPTaPtNZx1 ziQsRr|8v@U2fpbQ^+v_ad$FGO6l!{JXpf8))THbnful>711;5lPm%dN3!<}3HKDt@Kuia%$d6^E{ z*GjWb|1?@Y>_X#y7k&k|h(&Zb{nv%ixIi$2zfW=juW4!S4^d2-GU{Mw#_B_{V7;eb zj9=_gd+vegkaKg*F-Ej(WJ+II#;;e^3eG8+3oGK=y8Z#5f4yF2B@6*8Q+2ySZ08rH zU`2iWT1($1rC*9$Z83MJ_t8rac6x|bjbHP|jW1E18neBET1o9gco$Xp#Y2Tvhn=^8UpGbW8$gQ&VN&<;3!W7% zN1tW}j&3JBskeX_c7rqO)%;6SY|A5JbyC3ci#9eOW&ZV1=3gzPF=K+J6*Ov@k$ue) zqhju^k%Wo(+~MeR8=2X5u?9#i~_!mMB0 zd9xMGhlR2mXA$uz@voe=pt7Htb~W~86rvSs`v8dQIm70nGFp9|-pO_s!ZSLzbQfB; z=sy3dvIz>vl#vl#?%aF@zh0oHqGdjeEgcA`vF_Zwg3x6hD5|Un29$Amx=K*ehtHXMcoM7 zOy*zVV;_vuyUDIX=s+1O8NWO%@Jw75uKsEIAJjD#Ia0wdnD?@6fiP8fexTDEq_>ed7-S2{j6>LE{uPszKGfDzyG-ooJ_h&k*1|N@3YO;;C)jyz zx!u7`g~rQH^)*5z$6>vpO8X=6`80YMV#uOZc7%Oi&hP&$NU|dpx5z z7VfuOq?r(V%lvD{XzA?JI4?s30)*}oC zB38jK5W#kW=P*OBM?d87|anigFylNmTG_k#k7478?H)5OAlwE@y5L zKXbk*n^M*B!!VV28IS@8MSY5E#IZ>`<*=X5I7RlsMNq6s?aLh$2<+i4I6*X$LIG&rx-se=+31GLOF z`w;g_@w=FR{UgSV5&kFIDccJe^ADLk79sfY!wHfiz92|9YXoxbVD8U3Lu2fmRK*YJ zCF;z9S8j&TEyLis;yLqg^6{MR#}8ct{7b9`9JkD5=Mwy0Aez}FB67ZuUsLo;TItNq z>ic*b_rRPoqOEYkRrs|@Q7Xz}|9FO4{9=%aSg;DeS}^nL95E@*a-Y?JtuY|lV#ln+ z4-I4ZPEeRkA1F*IDE9=OY&${50{%Q4Ka|t7lHeZXc_V2Uvn$5`XeGfu`}}Jv$N04& ztB(P;R>97H=C|~o)7{I1uTj2VV*?_JqQwbV^Ea74COFAi4D4yykqT#({d!z~MdSu_$Of?w~```};j;zk?CRZI)$OWPCJ~vF20r@KLr0usAcj3i66=f1W0+aRmBf4 z(68B&oYOBj@2Nmy^Hk<3bBP-+R`}QL7JN~TEWM^316C?CI7Exxx_pIyweeEASjyAJ zLqY`-3!YU+p9+4B5E!&2Tsk5>QiC-e=EbezUvH?a5KQ+&)Zq>FBm~&8GXMI(1w!-* zu%#C*7!Vg`&9PSeHud~2ehk;F2eDEP>+_SDa@;cUoQApMz+~z2Ke=mjOOZA zKo}Z`=3wv(hQjV~=$F(OYNKJ~wxTZLhbE;7PJ5z?e+l@;J+Zuk^{9lC++uGFE?!-Y zUlUfw>1+uL!0}r=ovhwO-ttJm5O zv(s^3cptvcyVN-z&+FI96RD0}8}b8|VY7`={A**hU_K&#Ll5<~<;;Kx$bM<}h0Y+D z=5U|szIJ`w@e8wfgqI1^vB1Bc*Ne_+ z>m%BRH>>gMJax$JQV+v1>*DVNJJ0dMe3^fZ&)W@e5N=^#bRpeIaaorVr(gl#F`g;& zFA4nOup!WD5n$`Tu<(lZEwqHb&@+pF*=}q_FpSt~Tz;$u8#0Fk2=ZT5{Oj$^lD*-- z(qr^wv`gZHPm4Fih}@A2`TPq}8u6$Fw-ADZ;HL|t_h|vAF$i|Ms znA7_A^S0R9imGKLB!Rb6T9gf$9vuhOJaS)-Z;1^i` zUg!$KhNq|*SP-@8h=%y#on`)&MEvj(YUb%Iz?$xHf>rUuD*Qs9Uh{|1W%N(z4CiDy zJtEsvFhphi0{?o`PV|Kr>INORI-I$?Lf7zjzAfV8*Jf=W#~70;mdi^}#~8;*jXq`k zvU1iJm2DYF&;@fTD3o55FfwpX2CDGuSfMQ&8Wz{lv7DV1->HAYR{5_2u*u?o=vYRL^f9QFGL2MNFsC^wgnqf&M&Z?XNSsO@5w`zLq*Z|rwBV$ASYJ)cCZJ|X)L`6#cg5!rLsXN8C#W^XLjztPXoi^4hfqhttA4=mdiT#bx zp!he+xY1n5s<)Y2oe6EP;8%8OOAXZ|(Rk3x>$Ani4j{%op(U(CN4wt{&P z2h_%ohwS>8$+>*(zI80EKZ&=_&Bbd5iMTY+rI+`0mHeyc@Q4lTg3mgu%bCfAM4dI!mi4avb@} zcj`gJ3V>s9d|tuHniTgL#`l2^Qkd{ro|o`j_Ug8H280gtD(AmGu$!Y{uF@S&d#$?~ zF*ME{*Y%b0tDOIe0l$oYl(!bvZJzr<+A7=g7;_)l{H~-iVdRxhQcs3TG-K|(xP{t$ z@MaHFrUPF73vg_Le~qv&v4T#BRoQS(|65PLP`|_;nu^ z8$Xkjo!|V2fGwj`w$VZ$ESq5YMFqbOXf`t`0FVRN%GS@x!XrxEbU$`f3BQ<{H9NHo zTV9`Fo7g50aLbAsZ%s|Z02b_VYKw@|s1k^J5rD?E-4wKHs_=``I;~Pq0KcGCcjALX zKzuCJru+DHPV02$X6KKQQnY(RX9WidBlQ*h+UMbyr5obM)ZxUldM9se$C#XjU&dbW zubvofhk}?;5FNmO@=Z=N)p#S(jydm*@tne)U1wT9sS2ifqgnUX4F5eqQd|zw|*ra|6zhEVT3GsK> zTAK}UkPz>&d}c+|uisF#i%j4b4N?<@J}2hUx2QcG+a$)lHH~@k!&Go{=R+`FjO>I^?=r7qo6spSoq~zFl*Y&bnD>9D&MaE|`VGX{rZ_$?b8gc5pvn7?Fn3+eeVrvXdV79&0mcmT6>k)a;ilp{7ximt9kty8 z{JO4;UvSawu2|$d`Y$Am!{i3UMU8g@AlHW~_{F|)x6}4Csu(6{Y16{K&$ ze67+!#1Acm4JD##1`SA1#XMg6@1l(ZZhrpjcG&s23}!{n-eyPdHuJ&7Ht;JLI+8As z(hC#T=^*bqTZ93KDHjxmD>^Vi>{V~w$-JGRmKIArhc)bwW?r|sg;&SLI^)Oj!*{e& zKEX|L5-#9GoLhTlj z^q#}~t7rqZkoJ=7UPclFV-Ap7qNSRD*}yM%evt!i5cD_Ai}dBO5B2%@72rC(L;+u8 zf}WAU<%He@zG^^;29q4*21qxQI=S@FY%Ws_|t#Tk1yd>?aMT!}F^ zy#}Yf5NiG?gj)tq&`V}VJ{;GtqxVxw z^P#HvVFBS#p3Wy!LN**ZK2S7gv`*R}tNGWtEN1bQffm#izx@eBNP zb;#o~pj|8+h}k!pj0L>xrTRm53!zpDzvTP`&7hD2_PHECteb)veAMCk4e=&*LeQt^ zJp=d!Qe30;hlfgk~vzl*a`L4f1d8?0c*qD zJzIzR4c?O?55d34E}%4s zX;=7Vsu2=)BgS^aj~_0i$FwGQsIUHIEL?jbSrohJpg_UHCHb! zdRu-N@xyBVH6yzEF$)-c(d9xY;A;RBX2lQRkxQq-Th=T>B5X+^d`j;SsBp7kA^rRp z#}AusOx}8*<=mw;ndYqsY;NsU9%B{%dX$=v!-rgD-;->5-Ylj&5d%?us`ytvYtM@r zLXecUZO#>%)^Emb%-!c-uw!nb7=Bo9r^nsIsc)j_|DbA;P@8R}0Fy#dJ=) zXROXq2tNP1fbG})&G4y#PI?yc!*Bt9)Jal{&fL%gY6;c2^)|djy~yGl47NP!>a^C*sueRNB0;5nFE43J`2CBf0u2{ zzoPU|x_!)iPh2C0GRfA<&$> zxJDZQYlGn97eY*{JDu&e{`)rI*p27)xu_RaxKkBB{0&kq?UP8=!G&;l9QE>gE}Rpe ze<9Z0+vRNEqfaIIIpIWe9KKe<#hOl*@r%*3EtC8w@pFu)-8COUU~`CWcn!5QKL1M6 z0Xv?KEfB5^r^0On7sdqb@lYb|^RFui)rKkaFU1Scop>SkKhlekUAmgHOC|r1@e5%? z8J;Ix7ToYstk=7g7)Sij=U;hVFDLRUI6mez8hI-;<6x$fC`6pBNwHn!`olMwcCCPU z=lEg#fWF;?Fkx2V*G}Nq9zwij0bIWLgn37h>kpOgROP=^*&#wq0#va8+Vvsu(Dnkh#%gqACoN1t->#F`yu^`#WlKU z1Bn!fSf|xgg6=VW$*gCL^VV}2F7 zWAXQC3@o$mA;8w8>JxX&ox!+?KF-}$__eJ5PHJ5p>J?lR5$}!FgV6QUCHXH8wp>_% zlA<*^=K+@yTsU5hUwi0f^KoT2YGF4l5V1sz z(5IKzG^bhK-1}7hVcZ?&!1z`XbK#gxdp2{}tfv>#t8By%Um%nnUTEDI>JldlN236; zH(-ah`zDwOIEy9;ws0W4q-?eLZ+D)X<^@vZJ+PRt?yMP@3vxXiye?FEmqSNzmQpE30LG<2|uVtp8m&Ev5bxGe`9 zyE$Z!jslL`+{G(It2-caWF~}ZB)HFT!(KY)bTmfx>Hmf?ce`_K{YwIQA_`~q(z_%T zob!#C*S+4n-1YE61d{_sWR_o^|&&i6H|JQ39utK)}19Xz-x z^0eOJT#!o>;Ryg4*EXY1pSNDpnvnf1(WEJQNajqa7513Ki7+>Fq*6aWVc%=o&XC0F z&~4Zbw|Q?exequvJjg`sCZIWjjo@DiZ{4~6@W(WgY99>Q zz=sYC>JX=6$u3!!U(@Ty55Yu}EOxJtUkHcFXwmH8xG3#)V@G=6OUSm~P_cqvA5U*{zH@VoqD}RgF(la!iFCSO z#*^S6K7MfuscBQ})4@gJ&fK+|%#Vq$H`esG?irYcU&m>s%d2|#D2=QQC$7uctIf`v z=2YPqbNmmvKw&JCeRvE8|BKH1oCqsc@awd>j)3M_d={K9(8Abb7WOLtSAPA*ZfMFL zH`W(iD0T?c_c}NQiP$>H(b|ChQR9zPa-(09Y5?loE{cFZtAHPs?sljVHDq3m4 z*;_EFChF#4X%Wz_!mksVj=kFp`bzt`?FZA>=Jc3(#{R5?P4MeCP_5y>KSb%Tjj|0m zR0xow#1aVzSR18Zod5b|ZY0%~)i>2VZH;V>TO3FfDiJp7=`!+P=C-G!n_}7Y)y6h= zZz`4*`z&BnZzfy8F9XP(bAr3XUx)z*uF&;QGUz z75;S=_;t*QXG5C+6AwCbnSVVCLloati66R@!6`zMZn9aB841<9Bz_3|`UYL=n7!f_ zx`$~O0*O|?5nr8IP{FT3%%VAIPO>?*kpP{9&D;jC)4l{mtMISA&ID{r`zUP7gpJHF^RMxmE^}^G z{P0@3I}^=ka)7P$>gc`ZzS|ayyKTg%tN7Q)u}t4DT=($J&(%Lbx$$d{fnais8a|Sb zUnoPOCJ}Se_tHMINoZ?(8ttum>!?}9zdlG4lJN^U-qUi49T=}&?mQ&{K$ZH9y8Y(6 z;!(FfAG%%q1jPd|m9Nsf1|n2d{OdeTZXtg7YBm4*d)oS^ z&8N&e?gornd$?>P;oK?U0QXhpzr@z2CP1zDV$W7;c4J7E(N?onppVbLT$1di46f8& z>EtZ)PGP3{Gx2C+75^Hh@ieyI_Ry^~-aBH2w>LM7XJl6qj(v&iNyOgYrAOTjhdBS` zbiEjPP-o`^ryHvImvhoN=*G_tbvh@lrBB9-i1Ys}hkaPA@UPEM#)(?y_H;8zcW(kh zJ3ERNbE`6b8DhYQj-w@vR11>h2e2+jDSm?cRPajzqM66R4O2qcg3|@yDC-y1IpnhW zBB&JvgdCAy{xLJMykEa@)mg#xWCQG>5@6!EninWsgJhq|2i*zuT#@qE_p zMr5giU$0X}c5wVKE;$hvx-WVW1|Li+Q^Bw4d3Qtg7AJ1nE>UakuCvpqBWgjPT+MCs z`WSNEhW*f{Ym$GJ7W?s8zT<{u`m`9b+m4%iYJB{1>2a_mc<=j-H;t8UyhjYY`S6aWp^(ana{t5>4e>p2|qAD&WAqO#d;2w1m}|S zdaq&gc({J!+ZjZkEW|UhOfKT{7cehOP$Hw~aGyfJp?jTNFD(RtI$(s|kcGn<4^Yb# z@XL=ME~f|cO*y2!7y?=gI0*I}-6^lm0SnA>{>!9E9NQ0DYr@uBMyDIG^a=36L&@s; zjotK{#Hz9O=`x*k=e!3*`-ls#DO;1`@eBtF^gMMqVQP+>=On&Qz5YFi56XpB`1!AS zJH-#R>m@XW69-LhsBdprs`FpHQNMovtMd-YZ`&)AbH7fH$!iOtQ{w9YG6*xlKI}RC zP(LpY(th`Y%WL*)pq%dim&2yrmW?6TC2saGWx64Qki|+lH>GnTY$d}MzC3+oIPykS z{)=|g916G^(=K(^wE*z{rj1;GIsau%!Mu;G4twFXE(goBiT;E-`sP%}53M~EbAmg? zK5V2m)T&}^Z@$rkRHLi7nePR&!g<8G^c+MWj zcCMTiKU8HKu5ObTKh#rHG*m><=U-zr@6y9=BpaIA`&+`8v#=XKrN$V&W>=jC8t zn_yDl66e?OOtFI5HC6Q+%(h}KUcvkePGG^aY?b_1;6;r2R;O{YX068j3;S?P%^kb9 zihq5NuH!zNw4*lWz7r%A-{()N@#}Tg0%v=6%_i#$h8pt}9Y^Fg{FMrReN+CJmOJen z4rTs@c}>tc`KbFZRrr;YI0Qp;UESlSa79u!BR+DPKL4sk)QGE6fM3UGt{ljTVPY$> zt^jOu2)|gM7c~O=={gE-w^Z3iLi9KQvau^|^zr;~EkQdF9tjnL3nlZN&=+79w!`n-73!uh=zIj@x$}<8<_XDnGie4oKza9 z2mk7xjuZw;^&9<0QbJgKyjuy#~s< zSH@(z=y59x{EMdp6pkAwto)|%_W8~Bcy9UR_OGm|s^7SX5L~1W^Lm@QQwWew$Dn9~ z5K8!k`a_MMQ1R|gC9R! zujYkWs1R-#bnTk|{>suBO+J2)jFczidk3%o=&m0e)Erjrj2l*NfgqvEz+K&yL;!%1xL}J*DTA z&o9S8yP)`oWjr=;wC9KJ4f(q1%K0ytIMGQkab;U~KY*-JMeM8i7n@4PFJoMG^Z>tV zU};C#cvkoq9Tjb0Qo((qzklz?LObiPk=txlAMVEwTi6vz)uP73+-Bil?Mk;~zsDu}<@C#`##=+b+7OKyG@lk8|%P<$?NPF#&x;;1@#X;uT=fAWrCwSl2&hEQ# zEz(}rm1pS@>gMxbuhl5s*%e?2z_BmJWu#FYlx-Y>4>{6{K4tu(0--cYYlWpZPW2Et)W_gQJx2*%uO#>v!xqqrIb+=2m=%KtGP4Y1FKFsrjSc%Od>>~UrlWlYX9vuC zd*bF%Gs=euUibNzf+RJbr!jaCv3>HK+p%%ZE+~l2??U|{`gCGCz^|EH=ce{u`s<&6 z)9Tt3*{#3i?TzyN8*vG@89;B%9UQpT8NXTKyN_QCTWUJPuw)NNb5s3F`a4pE9GBE@ zpvo&u_sg6MTXz$2-T}f1Pj_!SUYH;@>#LZT;SO{ac>#?5Rm{AIGzY zsvaPEGX0TPkv{vN`=dcP_A`2Q{f5@+-gAfkY5I|M?b_DQiG`^_TjiHaF+B?&+hHsd z`;g97y4I~N+;sim*XiofkRLx(^&1ply$$AF+z+=9F{>I%Pqs{kIz^-BA0F|>%q*!B zj{UJhZI@n0&#%7WY-H8l*LgOxbpFeU!-7Gd57T3Gv=V7J#e}Il}<~ zLP6}Lo+!r;e`5?ikFpIry4O6ChQRknWjHan3-@LucszW66j(n&o5G$Sg(G-0AW{+< z*Wu}x+weUBG*5)=o*W7}+6Ysgw($|tW;R{sU-N!N$mZCvb++==@p<3m@mS%rI+f#x z-Gm}&tcHhHu0Q1a zqoPgH663xGzzZQ{X+cE86hiAuJ`Ug6k#ZhanUEMA}W19e9@GoHQ?bwGl&po*S zM+OZ0xVbD{cYL7FE&#;YQ3MY1JsxV^ryGvg=V|HA_&$_vjJivXU>Gq0fR^#;s``0* zhRc;*Y%SzrMY{)Nk77es;)i1dbGjK^rUj}u;)Fj4gMTiEJkbY3!h4sB9|D^~Rn#fx@6{ z!%#)(_2~tqqrAy_cV}>#DOjO9j}vZ(uCU z^&9OVVrYSd%vSgpQe#H@^qk)O-2`{E|4$?IP`UC~%MVUB~1k zAmckeLQNHZX`QLI?3zJ3uC3tl;QWQt!9vW_FVt^@-$nh#v)TEZ1Rr*8&kl^`-;`J# z3;31dF*AOZXeqn9?7G4^8BdMyhYEW76$`ASyRq0nIFh{qi%?d^yY20i`CX&<6NcoOT1^_}$3)a(KjURM5Cuup9Ep2O#t z$1Y-H-N0T* z_B9;XTme8t;a>p}yabP@-}noe(V_=%pF`9@Ah8}wbe%+orI2|z-Qww&3|vFI=o%ZQ zyH##;qT}eZn1*7}LJ+wmZ!Jut#gdp}C|_f1pxXr6Rhm~KC^UW*@?V>9RAf1A0KX7C z9Sk+5<~293+n#>qpkJ!)tIx9=Y%XSC7!{Ds;$K*uY0&KnxwM53GB3E0T}m6y=steE zPRFF3Mzw}Y7`f(=o4-%T?8W;+XVay*bNwNrG)ds{?VOAqhpjWwXS4Q`r8h-A{c;=j zas45o5A+l{FwmTR@X-EhbSMuTOsRP_oR)7UI=nWPbecd!C<}(@%q_qRwGNj}ziHlkuwaUo8xynrTN}OKNQd z|Hn4A(G@S6ZwEWPwE%u8<=kxd9Jh0+I5iqVvn918aPYhoKTK)$g!+wrnJovm4r znsZ_i9QLaVwI9YuaClxx(}ZQ~bixTSLGb;s{SbtEoR-zpRn;HndA&4Dr)WKlWeT}- z&eA*9DtB&G{%e|0c8Kq@#uYA&P+ZQrruHYYWBfzMD)^P9y9Dqng?cRx8=8GJjkFz# z7W%K1`uStx9{E5jwi)#R|H!a46YQ!V>~DH?=x>7wPrvy7C>5Vi;Z0ezC5h)Q?HTyS zK7M6DZ#!i88~U{Q5(_!h_rBteWDp0aKL4d5Z0OE^lTP#Y8^ea2u@pK~_?LJZmLFDh z3c`pJ|0?5`*;Rm%sp4N85{zYgo-q0y+sQ1{IX2j~Idq?>;$K|D0BAd_-QxhixR4%w zl29~1e#n)3t&X{|=d6L$7-PXL%x-4$FKoXy-hR_KsDgc%gE}xHi-=17#u%^ZI*f3N zH``4x@2G9!i=_PXU*KPu4$y&Xjh=uI?+q=$K3wA5j>7daeiamKB_-+{09%TGnUeNG zK`QtKB!UMLv!X00NMa%ua~iqkU+D$#i?$8gDdY!V2Z%>g3g7#k#cpG^rV78*czDd7 z(A*-Pc2*|wOG?h)&RmjJZKeti263e56*OPcQe$X^MZ1 z$NJJgCKUCJp=_g%WNmk;A;9o}96WE#4 zxZtt#6a?Ion(A`f9xUS*^RIU#$_{5j%jrU{yAVehfs|uEq5JVea4V#}kkYc8L#x|e zbCU|xw>}w4mGfUF_!sKu-B_N$$iDJR_sMutFQFSN<#c`^T5YDPyhB*;Es$46rX zC;6a#`{Ynn{tG!fJO^dQ*T{3D-G#6fGUQ`!7h_W?R+**K4#%1z`vyR}WY<{xH?b)1 zTIjP3LW18V75_q+#5lI`v$ES=UkEJ|C&kiH5Efdi`k?;M;P}|E?9t84Xqy|$MERgo zbTV`#IGcaD=09{SjtwE}iCA0=m>V5K&6|&3ihsE#;Mjum?_#;R#=~|){{0(L@vkqt zVHt{vXHX;`m(4MwbP*!y-ny6W-)MJW)m0b@fy4zMVh${%k6)#m=*D#wNGwDy=ofMb zbZpu_tA3vE?_J0DN3jqZ0c_w##Bm^6!BBJ0c<~J$q34Y$;QOSQOo4icbP<-8w14A|`V&Kl28?+Qu8a`VEEA3Btuj3?IB zMNh6hC=kNM9TfHe`V1v{D)k%A;lb8IXiE>*?n3y2c%^3$!n&&Z4TEi+3kxuTAbd%9 z-0ED57C(M?gqI2DzjV|eT55vt*okmRgF{_ytbwUH_uy9wwOr16on3Km3k; zBGV~%B7S9Wd zVnd1gAo%#Thb}m%5O|VZ5pPZH9u*L%!Y?m=82Y|=gB4#QMbb!V+RFg#;}`Uc)E@I{ z)k29N&VO0pARIsR?3kwR?>&yl+fOaEpZ^wkfeTBgL29Nw9OU}LvvO6gTz|-RY?1lY zwk1XIuQ!BRQ?5V6ELO8gVZn_Y(I*VxR{<@4{_Bju?F}}rfjw_t?C<7_^^ge5A4G+K zUa3E1w{Q&SQ(kmR`qk)cwVIza@2H&r$`Wc$Bu043gDnKgXzOjbGo*;o*gPQAAIbsK zz6~XtW6DVeVL_dqv|<rNjk*QBf?qa)e@WO46_jI}xt$ou@L#1p{UX#Ka@HRA_nsEYd?8_k7BzSu zzb4_&uVTC5UAuuXmv8i~;1}~{tk*dBG9Nq#|LV*FmnXt+0jU*U@coB*juwJ5S@7#1 z)I$-I%`cnph+G-JCa@1}0_K8H zA3+mbbmJA1hZ46{@QWVJHQDB;#T9g?Y|3Re;!rRmiVS4qo_=}t^LaO(2-VW#76|4N zJuDs<3dnr?dYCTSNPFGExV(V(*e5R7k0nt^e|F7eO^WwC=fB?KV_!TSY*8nY6Tiwm zlj?dST*bdQ_TF?n#wx@5wGQ!?^wuUgLZ3(eOFhRszuXMkCH|9#xj4K=Tt9EFgcY^< zUC4hK2lv=+G7}-|GAq zpagI%)lfSKw8EC-h#$_%e;J%pi1flH0JfaDlWSh2FL)Or&cZJ>3(U*#u)t$vv-lUE z>jzpD7{BC|Ikzo4;`3Gf>k)x#Hzvhd=MmAqdT8>- zvx>Dbc6;m2=fB>hkxxbLgFVCt?+xvQz!xU3&xU64FKGB~eJTNeelsr9W~Pb3TNV7u zF@DuYxc(49gGL6jG~?HLIqUx3o7?uR+yB}d)-l!=mcz?!Y@C5xR4I1`#0(*?L%R{h$DT<*s3*+BO?~`p2P7&;1}u-*Sw&F4axaW zMjxNR$*In&_+iPsf8w-PvYVg(s(g3tqo>+^{zc$lZ^I0($F;oedxQK7L)`+sk1Ffiy@MxjTybiv-~~1fPGsua+D5rOtm9Fv0T#f>}V_P8EJJ?Mia| zQ1P!Luu%$pbCvo-UJF!6T38*9hGRpX5D&0m2dnT4ksOasmiX5j^j(5KpDV`?9n^1N zUT)ZC`^<0ynydnVaP0l~A@GZN$|Q8BL{DbuXIad&a0z}f>M1*qHPxrRC-ZaE{^9z= zBiKI(V>a=^v3oF0AECD6!EYcddrQl;< z7{&~puty|jQH5X79nX(~qNznNhH^bc;<9-F*=RZ=_r_u; zD)B?FetxL;3WhB;W>h5FO+Dt#)%f*2>pE}lUhQSinDq^6a?IWee(`yfnbMe{G{$97k$ntuVmE?rX?SXf%OlK+Y!pgfloHYdvbYq}=L z0n!3;TMqAM+}~>?a`D)jAof^EzhJ|`LChHXRQQ((nCMHtY%9J4f6UzKG)*FK=i`^+ zUrmu@^9x@6;TE0$5{kN;YO$wZCH}=K13T~Ojymuw(Nf`G#L>bHGtH%V)QtW#}C>KIh-95jzqAgh^~U@g`a-KDWyvOD^*?sf6N6cVzAhUK7J|J$g>-zF*74mmfy#(SD1el)-irf z$OATLvUl)2@;RV`;$M9KA#U3!;9kclp=={(W_pxhhu-Tc8tVIS{UP|5yN-GY7a`h6 zD&ZU=BK9tT?2P6;2emXuXfM8V(AG0{RK~KHGW;>ZmoLQ+so}I$#I@=XscZK5o`hps zdLaFH5*}<`udY9I7?<@64w9{aE&SP(3-p*oONoE+{fFZYtY3Zr*H4-7=OxnRxF_(o z@R5N975oAU7tBODE(c_E#vBnbQ~8I*GJf&>hj5JwrrASQcF=B)A+KkrQ+C!&lged;o9C&-0Mj6udxKJZwi@d>|Y5+R*xNx zpM(4|!t$<)F>-wrA0XvbPDOrDi60`JXYludA$^7t4wl=+eNC_%N6Yxd^@p7Hg6<$> z0l`c`iEwG2i!qn#HzfAuzeu1J&VMb~(chFZ*NZducG;YWZNZ}0JRa~b8Yo}|yF|Eu z;9i=NoiO7wR|e)C&UVzpQrL zE8^|LS@`v|3!1!3Z;?-19k<1^`aT%g5hh|){A-(L-<)g^0i)lJ_MzxYxIT*i776tt;D)OElsSukm7-xeWtI&& zKWB}jkRx7IfA}Kq)&Ku7qD)f5^;b1J0U>f=4|a*v4xP&jUo{??LBAM4ANb)$*x2C-Wt1e z3EQ!ojVI)RJ>jbR4~GTnD&4ujui$^CM{kCrO^NfoUVi;N=f9rXxwK`@xQ4{a&hEcN zK(dRTIuxaPP9gO5L}S09l0P%bK7{Q8akG-{(fFY`E* zNOYz!<~lLzi~yTLK7O6Xynt4Uf3ef`pgwJ#bC9du2_mNKv*f>@VjnDqiv!?a68CKX z@=C0ic~EX}^@3-^rLmcg*>)^>rzosFVxh=zpJ*|L9K<*HZ=+aj6S)2mH>kL=Lx>+T zewn%YINNZix_+Md7kB{)*Th8}60W`pt;|U{ilZ7oh9vGkJg4FOm(;<(kQ|Tabb_Ld zDCbu1^eXH6*j?+Io9OoznBYS%06}{P?&v;TDZl}e|c~W-sIzQ9ElaKSkV3a7vgMH z^YSKGn(3_gA=VW6uL{uPIpe^=$qIhq^z=Ax?yB-7usTKH=^0Ni`2Hy67A~vIYXW1o zi@@co_@PRBF@-4$&ZBY<-^DcUJ;#e5c8)1*^7+>pN-$czfE|sWcYkkXy=Kj8vL?lS zy!v^}tLppghoY;C=>7Z`#}5_lD*1jz!026sMDwisqsl`qkNNAc0Ikd-{rs1|lqDfA z_;7@ZAHLx2`Eva{EPzT}N(jT|lK@}%hyMBHN{E019oV9L5r-1sBrE;m^UKh|-pE&d zpI>hQVd((ds>UxxyZBgBNw_+=&58D25Mmc^cyrOidl>uXJ zI~Dz^{`-~Xq2i7$@C$fW{`s#mJt>bFe?KLM`i;x-Ur@ctavv_FFV*`!>Dfc|_rDO@ zD8~;ebayZc{`G(zo0b0pRdg}J(wKYG3vA$*cjr|f?+vcsn9WZuT)=Xt0RO_=EAc~* z=gt}rzB3%5+4(Q0ihor)`}r^M0$xF!N%y}G?2iI6zkZ{X|0)1wO8GBFv}QJFRrux8 zE+wqs^UKoCRpZw}-p@{`x6EZeFRmi+uPpYnk6&EBu_}f0U$3xGh@kvcfPZoQ;TxWQ zdG{YGTrSy!(xzo?^7)rCgN#;Pq{=o<=?{u$K?Hy-`do}%F_Iedxh3F9f% zR1hg0{rwaNJf&n0 z3&9oieS+_o7lm^EE6z4NRq101c7$-+3w=CWSFWE&fm+FKuzu~K90e0){3`wZl&Uck z@XLim4)4O%OZau^m`erBPF=AaKcpvC>wV74)(uA8abM6%E$$Nj%tTMD4cwu9+WBLv zVXR7^q|;+HxJ%T#@P{@uTPE##(@0+?NLxLIBxxzyNLNrm`a*zPeh)3BK2IbApVK}q z|JZIAH_AfbbEI0z?|Qoc`YYE%62_&nv8bf++La^RjAqydCH!GvJ) zKd)}`=Ke%Vn6Uk}MD2M+(C(%tX|684>j@{2(*A@#MGevuoCY~(la^F1!fL zNhRQ8X0(*xTGTp!UOh&lKWwitEie~fkgBEp4J83M5DQbArX*NkajL~8^~0JbItO!H`<>v8`33V-asIQK4_8UdG%a6Z+wYFzxonYV@~xq+Bcf> z(uOZ=>aVreB`g6b40wW37SKYK zd69H%%S0_H3#dUCnlZS#$x0gKK2O}J|B-w#b$w%9wa~9x%I|vO#=sr@pHBU8W5bia zFsIbwme%W|H|lrDms2-1);(DgYM<1&<-a#x<<9fI^G7dx&L^KVz+h9KXk6gV^Yn|v zWonhy`mmd>Fay$i3{j1CtK68nqA_q+Nzm>J+$xi)Pc=4_`+U?1^l6`_KcEIgGa!6| zEH}_+tfxQ5E-$_7qdk<8jdqQxrInyIYzpgz7Fiy1k71*w$F$N)Pzz^c1<_LJ6M#0^ zx0oQz5E7pZH}q)E@muT#W`N4`(zRaqmPA81u%=3ox7ZD4z$wqmL{!I8>dOKv8ea?0 z$SvhAAMFt&CGzelB8HH&V=VNmmh!tW_ms9#X_LlghZSv3xurC(Cmem2ez961d^E1~ ztNb!D5?Ywn;L}xv6!e{2{64H-PPKkbQVaU1mQtsHw!~TAJAZ-kgf9e^z^=}>4F5UJ zfz8MNwC_{f8y;XG;R&u1WaV9o?GP+11SxFF^2u8g+*10PYj2y^=-${gFT;Xyqvi>N zXz}~dM|VY+_t8Y3v)lT8qxSeE z!h%}2+{vhd<5>XR*x>j1kL-p*YBD7GzyAPF%LrTQV*-vB%0IC2XAv(IT>mljfAgG6 zak&K0DIB^e{T3TH_1EXt4$r$>DD^PiFih71H;~ZQUnY3279$&7ip!-IM}v0q&vYH7 zB-Q%ksSUUIeGK3X-AMD~<$~A8(j1W@oGhVQd6|$_uOjE8{~<1W0PTAA&_UPBaJkZ= z9^_zv381-d5+78XEx4+SdY2EQmkP4^bFkIYzIxfIdp| zE*E;dcO|KYR!b{oG-{U%-eU+E2nEMJE>{bsJ`V8oKfq-Vshtw0Xg3;n^e;^PLF2q9 zFB9C-n6(?l9ddW-_Zw@Uyi6$d>Af76D?mS5Ua#M&U#1~T@50<~mAJQ}QM>Chq11;y znliR%i|7yJyuxKdd2e97X5q3A(2UEacVWF|;j$0VjLW4y*oRKPWv?~oiOU2k&r7FX zcR?Z$*4A7mIHl)6L#lDv2k0tX#-5*r%RWG}P=1%@T&`ArOX*$zC;gJ8KKO+CEWVWSI4|235!!e_V?RppCSuX(!4N2;K(568aXy$W{Y z5A{ztFHT;+tnPBbDbFi;83g#C;Fcal49E3lT%IMYE_eBVip#U%xD3$$(|_0Ha9nPA z&+jt}mwkX%g5O6Bf{No3C95RVTIq6&--kU^A|HEJYnJ1;_?-~Upp1j-&Ia2c^az}m zMI8&b_+6@=V|x#jmp?~dvdJWSffMFZ>^ARr$qsbEf-8H{@1xvCb$VCMwcQMc;nE&929$K*ja1^2ZJnJ3!&8F_bC&vl7a7Os#tpOF?bFKdk6^@ z3xWm#et)^8{2YtsB(w?o8(QejSyl_K4YwC9#4V#nX*~XaRTdUH>N$TS7LJx)R{0wE zLp7My5|gW-AUI~#T9l`2$(97+&d#h3K~6FZ~&L)Ud}5Nx6oiBTZoDA zlxrv&Xwt^8a#O=34xus?Au?mTZN~mQPwJ~gruVohXU`%V-0=~89 z5>Cs=99)&p?Wn;IHDku(hQSy+Bw8K|(mqeiX-ul+G$y-;Rhb%muC$3gtBv7-O&a)F z|Ay!$#oPO2P-!R#6a)$a1%ZM#@G>^IB9 zjJ|%C?WXx?@3GnBJ7?G!59L`r9_;X~3LiZlyiq&@lAsG+mXetgW#CV)>&nF+e2jeOCuaLq)Z4rMYUcnRM`Adox dM^Q=9V8h{d8RGAx_@sVVOHrPy+m;$q`~o95!odIl literal 42175 zcmeIb4|G)5buYZ{xmV(9W~8|YNLByAS0mXT<3S7pV}e0C2<$4D2Gwy}w=1u2{HHDH za#A_X>qqkPoTHI!#2=dpCMjv%d}B;fk~rxYumOYZ3zl7hv8}jX4RKsDc4Sv}NFo#B z2#n45+vnbyxdYVgde3XUuJuJ(%h_BV?mhqZ{_Wr1`y8k)KJNdI$heuN{8{gx-~8Wi z|FfCBx8Hp0pWfE?nOkq8TPV{0S98*TeaGx{nr@|Nd%8V6%bh)Ic01ihb+fNpFlY7x zx1Ii!Xlw5o{CxXszyD`xQU(!CN*fvee>-is2C2@OY4Z5b6#Tv}O?Y1UvymoAJ=A(D zH9GwG-}$kW{zYTYzw>*3Y$^PQNa+8b|35-0{fiH3L*%zU85r%yFZa8!6}K zv{$tiqr1g>-a0oy_BIhb*(QpX%WVd04%5Sw@}g;RnEJ_$MAD6(wVhHFCGi@T13%uh zhv+eC^P&aaCLxk}ag6p*1HXCP%5WQ+e2m`Bb$IdZ<}vG8qkU>y!F+>G(sUW$WR6(6 zKSg67_t}dV&0}n zmp?UJlcLA++@B?1q;-_=>ht1F+TGKZkM8O^jtzvLV$E`62ajv+H)A|5>_9QxQ;?~A z)D;uhV)${5>9kAD9F4B3{S#WPnv3>I@h|)&6TL|c`|s(tW0;?XL-Dj3Q|OOpr_EvK zI4#V^XPYnj8%JKek1&d-FBvya(;3k@gyEc!?@{N{xMz;kX82p%YK~zxI*J(1G4)gG zAP6ab;>GjkTcqcwd-DDC2+j2DJH&H|)ew?yOAkFtGb!35Ui9bLqp#B=gENcvDsfb; zRx`)#386<(jII*n7$<(Zryiz)N};P*rhaN0wp}5q;IHY6mR{4bY1`1}4wcHAW6oRD znUCeoB%Q(&^yifSt!^sP1a&y^tf>Wx6YsG;?6D#9MW`@-Y-f~5A+cVg_CW}-oY89Q zCpq(g|1D+RhTYQE6W!D}N^7W1+Bvb6_E>E)n#&f+;rBGvv~ruS=q91tEJmBT^f=9u z(FyU4zZSMNzp$_# zpPN1Wt<4vYV*4%Bea@e}qH|e1XJQmWkKzr{>-T4r-lKN80lyLlX}fIDZFroXap9 z7<(Tjq+JjvF!s2Nj)-Ucwa8E1N+)GIe|^+CXtejXapRNDbo{NBF<-xugf_nJ4DoQf z{c-tyKIH3H(#e z$(rT77LCz);;`LMc@KNcqhOC6D(Tlnv`b?5_KH`m)#+x>&NRN_?!v~#ld<4E_H_D{ zT69bNQ|9}L7gV|!TWS7_fhQSQwzmW?1=$yCn;_#`%%913?T(kRMaTTTs>}nveo5HF zU#mH8e9Y{i7gXnK4Pz|}=zWE~I&6CWdToP#?V_tF`Z@EHg7wSJm^boT96*2G^5>a| z+g!?hzKB-CfJE}*B8fgrJn?+}%0Rz%c&!wj+qj(iMe2y{-U9u~r3%qnfjQ+qZ-dP| zDd$mquDOt2piZx$U?$YW2=psw2H#Qyn>iPIb!R^W>KKaeG>^6J6|i;NpmF*=hI1PG zaE^?Rn+u&Ycu#!1{{+2f&0;I+E!A!MtlMb^&5+TZ;vw3r4Rr$R#rtqmwkRF$kAltI z3nYgPXF(ft-DUv0uIR6YO)>l`$!*r-g&Guw=wShkb4&U~vD?wrc7ncN1SLX$V9*?G zvGXmS*~8z;Uko$IJF1uMq3&~OkByjPqLxJ7@v?qXH8E&KT ztFNtS4~hg0su^zN4&jPH*lj#1`t!{A^&q-hm%i>cbbbaKy;kP|u~I?^;TI3t9uP?a zl1`1JYm>BvW@MWNOZX*$Uq7XVUj1BiCA}@@d$B?^i6;v@SjaGb@o@Ug6LgdZI6mnm zdWHTUijP#|*8-lFeCADBFccr3;=+K;yHUT#<#927=_R-v zFDyaQt0NI}66qvem=?<^n@jZ7Ip^TlMD_-{2l#d2Dsh8*SN?%a-AWO{uV2!9uU?pz zdX45&G#$N-hGm-SoiKg{%XEZ(<#dk5-!^y4Gp*Nn4P#;a!YUW*73Sv%&2#JDF_SO` z+Z7CK2)|gn?cT1b)@o|@y61?gbQd*CyElwqK-gkkx43~e4PNfneO|QFfNFN_ZV|#S z-hPp^s89E+RuA?tCf3mwFPX-B^qyz@dJJe)pEtYdMVbcz>vhQ3(gz@`#xJTHGT(-Y zyM{r51uWd~l(X^6S+doBQ_PSna^_{N2lMSKV`t+R+vir`R{}!UW#ZuQmR^8V(b4)9 z;1?`*cBlJ~bR{>Qn!U$r>9S$N1O2irAHPNbZFkY9WVA7>=cmU$2fw1q%+nb6IU7w1 zSQpGk7{5*u@XIlW=xv%S;~V>j@^2;?o2I-`tM#j?2I$~h{@dt>G!MTr`J;0HzSZ~z zE1|kv;MXh&tY21Q27oMtU$FCwFB}n{qp#4V65wlD3}m(go8W(o@ryo#vDeO}dl<5F z!lE^X>tTLM_%%)UXEFMG9sN+u!#qb@YYsZwWh!Tu@XG*x85&_n)kzD2V~!4-9K4f( ztO~#Gqz2C{l-AUBhef-cQf2(ANn&q&hS3UwDweq zewV(p*nQhhcLn&BH-KL>Q$am1q9;|e7fmNF7XP@oxySCs+DO*rZNRTztC{(Ro6N7$ z3H4ET#TTP@I{(%OgLXE4skm!yqhB&WABVa4F?C8A!BsGN zDau0I!M_r|elh>@A-l1d*$dU{R$zx;vuiyde%fCPIqeva%fq;S0s-zDnJ(-+o(z~y zh=2KT{B!#ZHy(e`2j~@xtMN;}=S_MRb~RRLd1&yIgmbbT?{Rs40{kjsnU2BvO=Rr5 zMT@=XNZU|!Ust=o7T{kzt|4qK4;-!auWd_YuYFj>icv$%FZqYlEye;cm!q^g*OE`J z64Q-G`N>Cx?Z1cl*Dq=J%C%)i7;30R*B{~7*a zT|{s^P9E3JcmAh!9wPy zjMC2lTMZ-TZNvl__%?Yr@`i>{XNP|Ci=3gbwNDn}FB2Mk+=q^k1 zuWT5iK0D?z-#%CKFPca7cbRu!e)Oh|`1+NsVf<>#YyNewY#D%K z@|MDrK|G20Yr*_0(67U^ZhvdBZl7Q;;dY9W9r5)mz%LIFa9FIin-5^UUNLrwPxF(c z{~jN|7QMP+)smwy%U2icSDH64BXi^P%^8B1qQt*gQ?wE(=+`mcy&iUE6@D#Zv;vUj zJBz6abAg0CWJDu>y)=G_nM=7FOuJ-#Moi88z~@%q_UAdkFOGryD?Qp8KVWCp&Nm*h z8TGPZ{4!D!9zFsc)aKOLqQ>3sVINv>U((!XAHSxNbm*yOusP!cLdJ7Pb}RHI=Y7Iw(g;>TVQ2T1_Y!gi^d`R+D&kq z^Z3;sm_b1HN;uLp;EPt_S2yAtdGl3v0=?AN%rV+8(xWjaj9>3N@Fhm3oaTU=hkf`t z_kEh=#;f9o&_NGt`X&s1rx(kbz`-UMSQW-EY#X*4qX^*4@&@mX#5s^C?Lrv8f+*+^ z_89tXfgSgI@Ou}8@QZdTw)~AR69bw3G12a>2atiwgz)RQwXhEs;IMO?$JJ+A0|%U5 zisk!5_yr3fF^X}R+)gk0bjyVGD`%01SZ)ZvPGveWfC)C9oiD|5i<5Bd+vQ!kFn;ZX zrr15=2!{=aA`<3Rc*!O7lFCERBFub&Tgbls@Vl23*i@rj3Edtm2C4O zDsm5kJgyfhL_+xW1)83VZ8OHKQ*Z)f--vFLFRLx8{@Z31ez9f4_WPm>*itYAz-0!q z5dQ)$`*xL$XKbfAKnEoZZ0>ycWg|!^?M;naRi8UUc5j02IIQnJet~+7h|?Oj>|B<~ zNVANLh${TjmY+j#sb#hUjJu1jkoM;y=fN*JZFJZv_)!Sze0FMsXP$*$@q(d&Y#H+} zI+?_-%b6AaWt^lt;;8d$wP>timH7whU#ZSlkq`;vmv7z~zd8>;Js!>TqP+B7uL{2gE-AvF*F@~? z<*USkrC?;^K(q>eIlG+tXQFqAS2!f-MY_Z$xvOiIXWt+KPNeb6hQ|nub9dRW8z7G^ zz;4LyO@#5wON~SqisxxZ5rGbcaOA^1XuLkmzy2q+jZfOw{|kE8gB{!5m!Nl5+)Hii zukbGi;ZU}9$JDz7bMX#f3s0VjkDi5J2M{*&UH#bMCG+ygO?avCr^5Ip+Po4rdG!iJ zY;P73v)3bT6@FFPFzvGTD)f2aEc~jhDS}tT-j@eU65?MB$150@wS5K+rIXf|yyZ?c zetpS{j~jlUH+a!;=uYSU4Hf({uuR_78LaYW=~(WX*4SyYmyXfZ?17B?`sE@2wIh*O zHdt8e!U4}yvOVJFzhx(i_U=;raG3d*+uA)NEu@=oUTNFy!X3y{t5?VIL#?OGzjla( z94sVkK$|;&v0p~tv6;|OkpJ@e*F4!)m~x94gR_<@#9QbsZ=ScXa8~?qB`D{w=sgbx zfBd&5=#=dAR*aYU*HX@ZrRNoA?ucf(CerN`+iqSV_d5%Cl}CL4@JJ2fhhAa?qnOpT zPCa%axqEG$TsHzDUl7NAUqbUQby-*4P9Y<^yIj}aDYB$g600ME{8zyMbICQ|W`901 zy?=G?Q=?6vuYF8jhCrgZ3Y1u~4*L9So;R~#eu|FE^jBl)DeJ|4n(s|YhvJ8_in}Yn8qOSwCT3$o`>+2={)j(fCpR4mGdd04HR{=!)_z@Ih6l8 znOwAN*2V`<wu_h{>!pw(2Y%&M&*u^Ha)y)qsD=Z*NY1bH)tH-r_=tTq)MNGZZ}7aQqOFrDVFR&F!a$JdlwF zu?{{G^eYrUe3Y)Bq)eop0Z;;43a9yQx`Oxfn7^jXzur-E+}Lom5#ggJ-BdTi8i&>F z;)b*1htL%Buy~i|v4CuHL|gt4|9anl&vv{=zp!0Arx47aFg@QMGXHwSXdbaYXZ|<& z1K9#>GEdWh3$(hUI{($|)iFoo7=H2&1V8T zpdMEh|C%$DLVC#kg`9K18b?Cyd79(ZkC*aa%DSC)t3-Ondhwtblux8*t`}SE@2CXZ z!%+U~VFwXu*aY<*k$7qCY!Q>|CMWiDo05LTsGwZBfEpAjN*M^jDePvwrh$HO{ICGE zijhfn5d&;cCin$y^y&+yXZn82Z*$I0TffudOZ24oU7qLQNtu70#xiyK{0nYI5w89z zZj%Ro_4@0@@xyiS)tP?pEUV&&3RWH9>km-ZIeZJu zrCh(Uo}M*24s0lxqkdYjV7^X&m+r_SemG+3{loFYL9eYbdRO*MSNG=;G1{|kX=-yc z6~-^s1m3V_pRr(m2uTXnZtMN5 z{e&QXsG!|1l>&)OG@2=z5ik1h(eXpS&&4NCM80itHGVzrf`7dvPVleFZ6GvO@GH+@A7H^tm7v_i z$&|#VJusQ4nej{MuBuX>6PLo{3}7Q>f^-xixor@v8Y$VFODBR?&DX`XYM>Z{}=Wm|E2N0Y1&q-a*K?Pl*fMA z3H7+G*=Q;M#q}FEp+8?XUsu6AzhQ%9aeu~qy+Hkjg;rdbAnw|U6dFRtGR z))e%_w=L}aYa(4CB|4lndMPl&@cD_$?3TtsdytO_p9$#;*z4k&dr7 zUz574+sq`Ll!+d!PKAH*C=SPWn1~|e75sl@sWOSss0wn z4}&`!ki4i|zoE@V8W5m`0`Lo!U~aUj z@qk`-G`gMp%qSczK_2-g{Ui_ka<~=85B(igvWLA8PScl+cuzQf2!Dgw*82z>c5=G& z9n?b1A)OKH<@Ydt?HNe8gM*3J?7?iC+dbI$8b%6@EAubTe?6vV7)|zdMao;BF`DSQ z;mHLnBY|ik{*3E4f^GYT3tAbq58uoRP)5T z&nJ$4?#b_8T8zGz{bSmpE-ixHgz)QaN)Mshknw9S?=fjZ7>R}X7l%XZ!ILU*KP9Gv+*%ZTI5yBbVmh6?!LB)o(PzO^rBW0D%!Cl#bhw{~D!$h=uu=mEdS|s~yxIzCmjSw_KOZ0TA_`=lJ2{^x!SYk;pv3H4OGh z*E>iC>AzLMFM3?H;8%_F5H_5-7(C@A(U){NkQm}$6L1UHs}^<(QRk_ajMH#yI~O8` z@at__DE~5mBsq%(CStHHq58vL(QGd^a_dX4D+w{ z<+07?(}{z_9V;PV!jEjfDaH7u^*w3${A<=m^WW%X0`-UYw~VT{RYwNn3iB@)voT;c zBR$ubL#n*Ug+km~Y*CWAk?VW<*SxVr+7X-e&Z{tk9X%SzR+*LfA?<8> zpf>t@jTdKjW}0iGh|hbE3eIhbZ&&bZA2mBbtBdJLd2=#@4i(>R z9&&xGUUjrfm=IhY@wuwuG&u4z1_9l zY@*D+OuR=%xa|2`G{eJ?BQ$7##02AbwJq+hc`d#Ymi{+!` z`VF?~PpaSL_}rh+F04hAR|obm#J?T_OyI9StnppHCrK~Uob|DMCI8i`_5!w+D0{?C%+{uFC|SHW(yN3HBruA|6{E{F&??X79st*z8=(2iU)>gUDL zrd@+N1lQjD4Rz_t$V$=ezemRpopg4EJ877XQ{Dr9k#(GQQp&BW-G^%C$aB|*C`C4<}y+6aS}9sFx020D+s zny16SF9=d}_aGN~S0(>-B7ZWuP=Y}R+-jg zlZh=2*KYu}jBeHF(t391)Rbjntpt8$MW}wG51i5NY20MoMM>`S0QE_?2Z$zo{c3`* z4%o`rN5rFakD9^rvy|4jTe>Nn|3WvAKixd#Zra}m8=f=2VI7p)GfQ)o{MUd_Cv!_~ zgYZorAhsq0-r+RFv)I+ji5 zzD>x(Dk#3>c}~`RoH(P3TCwHM4%Ld%AkjdGA8wA!k3^`4+vJU@v^tOIfsFJ(VKf9> zME^j|xyUJ+7ed4HmE;oncQMw-B_S8fLzc$g6)LdiBjU(3GO{`xa zVn492x*K>Ja3b(8c#O>|c}wkxxheN44lRz;-w;SZuaJ(*{c)!v?Pa>RA(eSJbDz@s z<)yE;IfZ-}zphcKL+jFh&A@4Me)31~vSTMqTB>!qk3L0vwQFSF&an$G z`Y22REH?UMW~9S?RyA#~3CM`$#O?Ik+@{c#y8b>&6bOkhe=RsZ587qGs!JORvmf<` zDFdslwxw&k{P+gduVfcOVYh%*;61SOuJvO?fR^`0$?V~80uOh9-~W zHVzgkJSpSX`vm@#i5)T7Z<#$Fy9vTO>S_;;$9M_9ehzMxaB=J_;S4I&&<_I0_71?{ zSMjgCuq5!T*x)5>_=hptF0di1_!rucy|F8$FfCp(pG_HiujTmaEg}AOiqeBIt6wOu zfB@-SGX;ZxHD~%l{EN#rW=%xj7iX*|Uyr|Oo<{wK9$<)n0l%^+14t><>3OmH`&(&v zc)`&6D*lE3OyCrNYYnowP$FfmRV_t(dzgQ1r##us5h0c9lHCeNaU%e_ntwf}nltt* zDB)Ype;u`a?%x0%?9Yo3|N14i5~@&Q^c1D{#{`5I(+l=j^Dn(#8BLSnZ@h$f?=Kup zFh^=LyrvvK)R6(ryRC&DHh@pSWAn|w@YjpuhbY_F54UiHc8Zyl>=CcnyXe!y$=(ot z5yFP~Xt#LL*r{f@HqNZMj|`@`^S$Kqw}Se^ah%P8qETwZo-Gg%kTD*61;5arg&X5r z%|j!nmUrA8+h&f@``&aF%eQ>N*Dt^Ru(J`>8spCCSSQUIV*I)ppfFIyzYuv#X*vJ_ z{Ob*RQ*|r_Qiu7M(bj8Ul(?MM$Tk`Isu*(D$dt725A&}*G%I6&KQb5ig+l}*VpM*s zr>%=NhVx&K5UANW@5$ zt>~&N(N%p4peGu_FRq_Qwri7Ub=SFWcO4%z*fSYM2H5Sdg|0v3tl~5i=|yV4DYhAH zPWH6{q$>Ee6|nULpzV5urdik+9hL9G8Nj&8_?3s*X=k)*mh3+Vh6wCNnQJY*f4Kf| zJGErHi;Yd)clRY!%9$PCCrNUq`A58=Nd^={K zY@V8n*u58t4YK)g8aos*U!&p+QoKk&RelnQ!YUK@T2)lR+--};TQX~ z*mZQF2b0n zaA>vrX+nQO{A(A1c`=0As8}J&A-5{MD#9b6SkkXOo@N8)*?_A{rj`{7iYUrqv!z03gTyK zTjnzge4|*xuNa#P9)(AsT^ce~$6FTO4MtXsoq}i8%VXE^!@f43f9=j9 z5%x>b(X%1ba(wV~IRAxWcLmHPi~Ef2hdRBCdl*Kq!oM6&N!Ymv2kscVMT+r#KPDmV z>z73S>lDI<59I(`6T=<*u@)(0vf8~=p~AoR(R&QX#r|Mi<1McM&Do&}#}7}*c6ce~ zF*WSAh$_0YpJr(|yqCIMhOxB8`TGKtR2(te;G^NFZWo!4>qF4j{a^00SiT%{) zxkbQn%)+jNqJ`@Z_ib+3+VpwxzPw9aS_Bc}>WJo1V1ezw$FJW=ABef87uk<)VEe@+ z`ZKgV9c}dWi|gn4bOS8gEA%T3$I;W7GamyH`&F2K{gU!Bk^_vwk@n&{`yaBg!w<(E zG0Xhxez>X3zgVpd_^T({FOs|52ZthQvC*Gr&VS)3O>yn2u8!naaFCh%tajy_$1eCn z7{3Y#YuHwo;oLXMYbp>w6sSL}iXU?Q#=WiP6?9ZWt@0*U)VHgKycxnT4jaawiH@r= z3AIvn5}S4*Eg^HGuV4Q8<$1C`$Kfn4=gygzt^FZwm)%wMhYu?^V}CtTOKbArRypxa zFph*=n+x-=z3TE}-4S5Z8ih6v>@&BSk*lpO>6b;1Sg=1MVrm`KN=B#pT&8 zZe85;{p;p7)=51-40iA;bJg|pL4P#Q^(VZY&wqvM52<76iX7K(@VHPkD^Air7DD)S z+MQ!BM@^|3c6ff4xb_hr$jbbS@yk`+t{8UirM4_mB-<1KTGi*pT7NB)HIfRl)v06s zdN9wvdM(j?2v9)3%KXcLR$lIXthezreUtguXGM-yi{|0F^hdV&@7ZQI!s~t{KXaA& zviN4ezv#!W&Y1ubmHAhm-nQmTu>K*GJVAH1M_*Uhun>wLzDTdDIT_S}%o9g*i;Ah! z{nyYL4~dl!|H{d`IWCH_sLV5s`uxRa9iPXOGXKiaKl+yBi!^Wn{HR_iBgYRhE>JJF ztL{{f)M&mrX+;({Dt5!tV!+-Z0160R`Rl%ITAs!-?QZN|^Hw_KEtD~wV+AXL!7oIE zZzJmp zz%P#O#wMa2^ggUl{8+R@>Ui(CIW9GRas44GBoFEM;bRu!hg-T*>Zi5_prSv|s6VuU zxx-1AcWhed*A@tPatNb%P3iUW&wpVQ3|o)!Byi5|J4PGOyldQ#y%X?@kqEexf*C~Z zlWV46pRvcrP0w#rH1_EgT#W+FM08| zC-qFqaGTQkFU${*Yrc%-F;V~1&woXHz3}S~XL|L$;uU%V`7b+Te$v`yK=H?G8~rwZ z{ozbzTSu)&2R@Yt|MEu>{huZM^7&VrSC{TOj5W>VK(3eT==b%^zg+H5seS`&Yna}l zYx1cg_Mx9UuEY=7#nKRM#b4|nMMSY<*@}(*uhnYZ*<8caY`Tn% zXm|G-;&E9A(H}%SO8g7c587uO$hpEo;+A>(11A#EqZ z_?4H*siM))-{SfW_76Ymm$f7~v}oC1=5e9O(Dz$P=f99=YotLNFDaPTje=TO%l zVl4o*qr7lQEd)UJvcG>y=fBpgeqKslcF06^JHe3-<-fRWBT`I^!C!TW@r%9<{7M!@ zrG5k2#Cr^CwO9H6Aw9_cp^G+pP4km4B4lq5ufu+B+9jJ0Ar^N({e#;)JSeve`)#%% zd%$HI^<2MkrZ{^dehNhF7r8lOv6aRlKnH$o#8+Vxj(j{fh41Zo!izs@{!G1lW5>V5 z)s#^E2CUz>b<#L0Urt|>V zaudD)7GUmQ>gqPu?OMB&lugmz9EZhVpZ5v~k7tV|{K6AhKRXW&g5Z_kW(Ny-QKTMz zPjLQgKYace+8{Vwh%gr9JvfsGYPbn0eSUe7huxCGq6FhQgG})XWqQ6n49vrSrk{fRz=J*D9+EhMS1^B0PaWCrL8!(rBRFCzRnQG4nE+*1^Py)a5)%;6mFYcj-y;Ki|v!3q5 zfer|({Pha%k8-0&5Lm>qvBxLzlm$@e5OBTUn2k zN)a57gQ_4gcFMl!ue-)CV}WYOV@DmJh51z8JW1~tK*UDF^&4;t39Nry=wn|BYQ;}B zg!5lgTS$!s)VR{Ot4dqZaQx8Gv|^O@EKcyX8(RTD`bnsMgKc<}Yw#YI-(k}YzLV5# zD)k%A4z4!j{MX}jWhUt$4aTHqU3L7>En%(&+);e~%SYi*{YItFxXS|PzmWf8%U@N0 z$oEGzFdUym*#@v6M*oT@5Z>_D3-yPnHU!T_*wEU?3Zl%+ROVj|RrMPW)2%WB&geW2 zNP;P7rN8rq7k&Nm@e47lk;q((E6e=!Pf_TCjPs^&{l?o=K!2vRB8;iKVbKqZ+qpmG z`i+NpNAVM29A86(uF8`*GmBBY?At@&mz=PXCHG@HdZKQoVNVMo{?(Cb`_|wL@g~lH z&EjLrNxGZb6ohj8a2X=fDT2lJ6nu5I3Cjrvg!L=Lzjnc550Qwp^-tf%c^ z@GZ^1Bs30ZLR~CeBW&F<7v~*32&0td`C`LwbIUqV-rv%?bzMN{Ko9{daDUE2-jU!?6J1nzT*e*wRKtvZYK zC(SR&A$65oKWyGWuWY&+fy6L=fq!+u6d>HE63{l}zko!CqVHsbu`_;xB!7s#D*`z##_(4L!pHH$s=4t+w;dy5M1;1C-yXNhYL&WzHnJcl` z=JB{f`7b>j5A_=wzu39`SASd~{xw0!59UD!eoEU9ug8Uo#OJ&9dtCmMu0Ny%>_#LB zm2n+Amh~|Az^`!;@Gl)dB+hmvl6Jo6x~ym-(64}hWsK>BSX?IgN0AP`e}mIr8Wi9I zz~o8(mLETy&(X^my&6d`MIvm--VXo*euengml%#YehBH*B?f3kraKGX0S02@vp}TcD|<(N2u79<%^{5VJtX{f6WJi zw79qqtAp<4LXKm!fbR^cjvwOK@;cBiHZt1agMR_Yg7~4&zwVS8j-R8eWQ_MJH(rrj zQsQ6w{=+uvRtXNgB>JEiAS~1dAS>}Njvq4rN;0KdL#@(wU;@PIn>d7+dXknH^7u(z z2){J{8n*vRyrNJq>e#md6cCFWt@~^RznFh@o{oLN{IT=Qz@j|PfBg&nda(1g`UREx z4WEC-cRuyA1S=6t0S?z>?)+ifqy5$V>s3^1bckoNR~JE(U-mE7n|Lss|3VTMAwgUT z<>)}-5n}_e2~UEUoEkr%?>62W@cA za{O?&=8Ut3W5)rJ2e-_-Eq1^737wIs*BU>oex54?j=85Y@cH+dKe7G}_=P7$AHT}{ z3$)8Q%(i6&=KYKX{OT>m5AUMe3HBM;9Go9Q+G|TRpDo$}$tuSWQL%v4K@VeMaIh_p zEqcriFwP}y>jM78ZI%cus+#t?Y#;>jJUYGxRWQNVTKVUa1+!!xH{0rA^=+h`mT3iSo_Snxo?ITs; z7jD#4X3-h99#@y}aI{n53mL!#NoO0KbbYOKp@aH8g!_A07y+rk&u~pEJ@#tbzG$ke zg#$0>MkB^$wH-iz%J{XEwnNFEozW<0c4%C$Vt@gDxyA*~BWh+QdXs1*2*vAHb^Vw$ zm#M-p+|~=YxzD~CMb{o+YnXx?rONnKFy3=Im_3T)i`3{ppyre?-j9HT*bnRCI0n2(iJAF#LK$RfZC%VVhm)WTtDx@ zi*%h~OZ=0&!_jNH-{phM7<-w24bqFWeIWLL`L2S0sIU)zr1&B!2&epSbra&)s?+#O z&xDE7K!(l-LI}S&iseHjiz0rw8m#`W&SmludQ1Q{smAl7y`sIz(Fkp{vqEV#nG_1H>KRwA`Qc0Blub2 zUpAIx@Pr5wPtTP37x`$_HSQn#Qe8#jLV6g7 z=Y9PGep!#;s;g)Z&KNR~q0d8=KKuAJc`InwET4Psae3^Gugf)-o`iD!Jl}?`yYV_7 z^5Xuy&JF_$W&X8Q@vk=I46fhMWgBn!hbXJ+H%^Pd6$xnRPY^8curNPo#SgE~i?`gD zsf}sZ%K&IC9P(|Q&VRvfMhVw__fw3w7IGyjRfKTJk8k7+$Ju4+ZT!CVH`veD_lkej zu{iAKG5C&dJq&CHzax3`u+t3`FcIS>IcVAA*0m9QueZ&i;^4e8Q@C z1Q|??U!IR&?$oDLe_iUC=v-_+PN`$a{IuR2VEzwX)%@q+ zDeYbi`tIu&_!oN)4rYEO%qg3=DPuCQnE`$=|H5@xW3h?;6IK8Lr|E^fHZtB)ZNvNU zy4|wP=^oe^oQEyY^WZ5sFH@-0Z@9E~aoY$g+(5g0(~Y2o-;p%zQhF{J*s`H#2kL1kz0F z)#bf)$AIRN`@{STr82`6!61m~Aa`1N&-upBl7 z?P?w$91}OtK6NWjgjMj1Ikon+;2Rg+VmIzqRXdDx>o+=8EYmVU_qynY8(m4q-GXY! zRPakj3)6o&X#V6Q6Z8blQhe#F)k#s$4B;2s%-H=cm(xMj-n(L>4!E_;^=I*~)D8A# zl+E{f30#zPK`SbP60$xgs`Fo&WG-^4K>iChyq1G$EwXzg%)b}{@Sau+rP>mpFjcpy zI}*M>3Lz%2i58az5l!9z!I}V~#m>4vD&WiS8H;4x5u+BL2m=Jsf|_jhk)Z1_b>T3`{WG7 ztb8Iik9~&+qS_?SfNVd=Up7Haf9is__d)gz^zvfr#ajuK6kXBE>e@8DNvv z3;+H@_eC6ykI@d5ny9;q4}#$>u;FF=()EXgT3N@~X@A2zE* zqn_6EfvoOOq7J-5ydu|249%8f_SwCR9aH!hJ&Y9QITD35f z+Ec+VZ8Poo_9;KJP)I)lAls5VneW&ZAB3Z*v5D&s5iKNC<#i}r4>%S(*?)qbH#%jk z7(V}ndK+)0b-=hx9dT(TZ%Fuuu!j}=N&&XE@YP9dJQE{>`P!mH(UFCyTG3xqpMSZF zZAu_qW4UCf!BhHGn|DR!{(0oTP~|1T)_whA{tnMY^Y=1-ai15dc&|Pl^|*IQ59)i* z=3hsVjJn2MKitw`oym5xzp()M!8v*O8x{N#<*=cqT?GW()=2~atLo<;q-|=OGb6@@ z91OKK^~=0UqJG2IFV24- zZp7lY03AZ{LzK;DW9k0GQqwN(&r|46sw#eXf?x)v`Ne=HN5Ly?od_GL)#KV$Q^YpG z`8fB&psd9om!6+8|3Y;Z;p|Bd)QS_$2!}S=tMgYW09hHo?i2s0nv2MP1!Wt2{tG~s zN1x05>qQr1cMvj#ZQ(U7L=uU0Vk@s{nSZULx2SzngWHm{P6^GwuAxJybV`NzR}tas zC&6W)O(p&%&*opu0@`Igmsxk%B3_*X!w5QajZL18woJF(^D4FCLct&b@+T#k~Kw>wwzxHQeN=%7pkILr$F zf^YsPe+v#U)2_9VM0POW;)eOx2}C$sWO4-YL(RW>vQyo=+~#HI{DBI7{XJbS>qa8C z`D1s0%l8N%8pdA1uY-m3Z3thN`*Rt3xSjh`;a|9kPIomJ7w}63yfTDehcj0bU@KFa zA2zT%fcO>svMD>5*kX@DWq@DIzmm?k>B!YyNCk#GXGMD1YlgH zQZ5L3Lwd79{Of&jSUsFszH&;3t;^VsAdvWi+Tn)z*Zt5hXj56geotH^H_+A89pYaF zT2F|9beH-pg+l|>oI#(<_~qIC-K|ILc_sZK-1n{s!Ql}9dWfEN(_U=;gT5aQJ2uOG zmeMK};$NI|dBOs0X&{5mxzhdJR{E|3pmsmW* zug!oxED9dQm0q$C!Y_wy_#l_wX`AUl;Hn1L%rbtZ#DlQv(9^(fIH(!ury0~;#lLh} zlwZFAJ5MGoG9y}{Qa?Wew)Lb3s~*^SKiP^Cvg6_W*BP}4)CA|UvD};hZL~JHa}F<` z5aUAYpsqh0XlrKv#pl03#6-g0kZTzRevOmHchn!UiL3Y$+Nl6G9l=_J>NjxqEvs*O z984yb*lJ^|#MnK%&=~M9OV=MRq?l!r2f8#DL@Yti3SIYJUB98?2h8J*XVjAq%tD2@ zV3HNauZMUA-;V8E@^hN-P=LCxzb*MxqvqW&SuWv6-+u^pY!|Y);8B5J%ohy=N878f z!Y>|I(#EbUP@a;sj6{FF)x)>~{POD$XSw!r@z1o&YaX||!N2}SU0ST;>Ili-^7CH{ zrLI53#a}Gg>M3Kc$N0r92=#}$&)9yv4-E{54`1`Y9fKz$zWwp*4;M;%z8S+o?~Z(I zw*bDo9fxuLE2y6@)gLBt?Yz+cK2a}}Xmw-iP^4FE_uo^gKfGZ&U~5(}IZ=D3wYo5~ z2>f!%<^BZczg}vZgK6m>P7T>}?_Pm@hyxv5hp*Qi^&8G9f_FM*ew3c?hI{#1^b1+! z<5VnPeSfcxyuIq_K*xZYchANzZ7RD^Z8)k9dhMBp&E}{)>0-u0_~n~rd!u-o`PWU+ z`x-}c93-sIh44$8Zu|>4uRCj&CYFMKaUk(CGK^mqU<-Lz&?T{k@-phwB9NF&Evu`- zFYY0%aS={ey8+_>TjzG1b^ivgP?obskkWdO9gkjm3Ev9im!JRYkd))=Ni}{g9;J^$ zPg5girG7)h7P3OFk6#LAd7lNFP>vt^^@ljKHUda0Uw-unxjc%h`i+^g>HDB&r9k53 z$Jt}7!Y_2A%f8=i&FrC$8{%I>U*KfmN9{M50pY-J zldoTVe-!LkK91TR+U=n>Ly4Oa2iW1&!?7>vGKRxj3)ddfyApN-f^`x?Lm9t<{Fg#m zCJ1J}^EL34C*Ak^wu2#->Nk{Me<-gX5U;lGw%g{h;O=;U?Q==LRE>tMp6Jf5V@l)K zqX;BE=DPdWavRBZBglXCT~ESu;P6qDx)4Z2+~$HZe);(?^cl2^IFafLz|%JL+3ex> zl>hyd-V%NxeXbKL^=IK%XAtI9T3A5Os5$(k!oMiUb_HoKuK9nN=6TiUm$i$Y_V*z# z!8RoCbWk_Mzk-nIG15X>eB1q7x(trJsE!{7Hk_~)1#>O@c^&u-)o+wTxPh<=OjE~l z%lzvh8DzWk;_`dm4A;z*dwbw!JW`J3;)E*dNyZ}~{Q5YDHU0%vC|bWT zE>J4mD!}*Kl=)Yg!W^X_?e#K!Pd)G&*iDFk1=+4r*}OSM2QV%GSvmi;k6ojo_}k_6 z0-eN7`yTE~8L7>1pG)=g7*2UyDLp?JSDAnL@xv(6UM2p;Nn{;+FY_-yeyG!4L7y*h z?^ex>UuFJP9&#WQ1pYw*tZ6dDzxcG5rd?wt;Tn1dRtor4&VOky7h9Ae0H6?8(UJgb zqj9kG?^nVrD*OCg$f50ODgR{!v?7OagwAb&TLFL)J@E7@{LBAUs7(!GAo(i(#rPGZ zkOBb(55R)RIrtUovq|#0ACF zz7%*-;a@&%c^E~Be<3;E;#Tm>uJQk=j%ben)Nekp1c`{^f7u@_zmt?s8u(n{(Cti}PQIA0937FT|0Mz{2^jGXHvr?L3=; zKzH)c!Qe?beu&#&Rc8j*Zs^2H5yGSNoSNgNLiw++fGy8d(M(Cd{C`O9YC?a4oD|XK zlA96epv0LqtVITxTjpOwgri0(C~rV~14#XhS$<9^wpUq25sh|cm88871(J-yiMm9IEgTlM?3@LLd!;E6YzRgmcEr8RdLpOk;- zOdARbq@Q@RHCB=m2A@=Hw5{wpf^zk1NRg4Do9H7{qsl@}=}FM$>F%1(8lO~u=uR6h z3)W}pB0QN~`qtBuGSo!1WT=o}_)kiG?zXtH5H}hOmITFTarucVwOLlv)z_21F*z+# z5`-c9dI~qDrcr5JG2;{T``)xP{vl>9^g{SUlHTOBCClR?iSU(025Dg_88$kGs#T)J zL7S&Dh^NB#E93*qLej`mv$7Wl-+EfsWQ;$eKcH#K7vwZG={BQVKPmNDni-r8;*+%{ zVbI7R{=`p8ZMv*wv$^8R+TDBzgTN%&hC#p2AuCvC?6OiuHGZE@@rmxAp&YqmL z%EH{fI`_Kn$>lbgnwyM2plj7MU-*4BIb$>#T?9dv)~nW7ta>t2n`)|r8~F(Zea5&* zNz{8;A;D6MU8mbBwR!qF^Y_$CnX8)W!$RLCep33@)7RD9(f7&BA2v;UrYuYfo_N7p zTzj2)hk7M*byNK_Wx?Pl^O`R9Ci`=E?Rnlab+(FSmNZTCCj0tD;vBWg8olZ!ULEDX zhN#xKS>2TRNK?(-TBwCkbF=EklW7X;%0Ji2nqK3R^gA@o)50fcDu*?e(;wnV@U3gR zD5IL(S{vJw1-)T2eZ)^xsn1=Oixup`C2?BN3+MJZ{G`&R2HND_XipO?q<=p)t&8OT zsd!RDrE!@?k9T8wTC8SCNKiMr)9f0ldyN0s)J2X~Ulv%=Y*sXWQfhK-mmsBF7nfPE zkarO=5!9!jl)iFT^29trHD&KPPW&w@G_Jz~qQjS_NNBT+7$Xw5~O#NiF=oF4m9Af|h32#k!SMJ=)^Ur5aoO$nDq1@&_Bcy&5o%htw3OjCR;lOiYq5Rk9EL{G=lwS@Vep?H3 z!a}*tHFtje$M@|T{n<$tHeNk?&&g|6bw4xZ;n8ECFSjv7ue{&6+^XAumT*y>S88O1 z;P@rA1ON~HY|z$=`p%0aD2{tO5c)Jk1>_5rOD?CUH-Sasg@Qi zCu21k=L-I7s2dn}E-nX8f;JL(dLCT%ky-|rVq9n4(RWeicbXGV5la`7CY zv^TI`Rk&ORXvSs#Jre6xh0A4tW?T;1U>`~#^-_DXI7gt;xJ>HtrlxCR#*%Xc8NBB# zTrLB22$!+vt8lpt&@7a`Wyo{Ys{ADQ)(7dA3ff=}=Nk>QL^;KCgkTPP2%0aEJ;m*- z=LlZ#9;%_)GS*{GrKisk4wSyN#LDb%N?#Y740rb|K?QSYNQUEzIjOcZ`bE;{W;kXP z*0@|HsM5FO(w@mvfyKUa{Y zadn>q0cB9|f)^3PabpRWtAxd+CLby;SHp1$p#N9-Tj#=Y>B)QLHdVM>252pm+XSg> zgt~N2yNiX`!$@vN0@UG_6{Nv_qs8pAIuIC*%0EaZ)1XW^NJm0IYSSJ{76=7*(pMFwqQ$@T21AiH8Ke)O7DSU}|e(WIY9tchR1ef9ZjckV| zrH#Y%S14sG2_uu{;>lvV=zu@6^S)=PJNYmduVsUeoo7^ylD=#qxmB7Uv^-~?9hGXf zZE094cu&c|27l!Lb1A9+6oXCF!g>Bv8guDa3m2B8%KxVozR$ZS9_?bVV}^X@JGoJW_>dCxg}%q~Ci-*Y|DP-*~>CSm| zIe1gKO+|&zQR;G=^XYQn$CcZhPnQGjF10z2E|-=1gLJuMC4%?Rd2|`S^5>_#6qWfZ zPh43D8l6X%D}Vjp*X2qZUpk*Im)m@RE|=SU=)(E*^#7&~epvnak0&aPJ1Tgaq^av; z|8eWzwD`>o{ALDzGXuYwf#1x)Z)V^(Gw}bv8PNU`947cn^1P!*iL@89%dw;Lw)syy z#A{57Q9AaYX!}7;gdwwPY9*HSL2W Date: Sat, 22 Feb 2020 13:37:48 +0000 Subject: [PATCH 027/298] Mention shebang changes and python script porting in CHANGELOG.md Documents changes from issues 560 and 564, and pull requests 561, 563, and 565. --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a36b58da..af8b073ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Ported all python 2 scripts to python 3 (@doegox and @sigwinch28) + - Removed undefined exit behaviour from `analyzesize` tool: it now exits with code 2 when called with wrong args (@sigwinch28) + - Replaced shebangs in scripts with more portable versions which use `/usr/bin/env` (@sigwinch28) - Added `hf lto restore` - restore LTO cartridge memory from dump file [.bin|.eml] (@Kevin-Nakamoto) - Added `LF_ICEHID` standalone mode which searches for lf HID credentials and store to RDV4 flashmem (@iceman1001) - Added `HF_14ASNIFF` standalone mode with storing trace to RDV4 flashmem (@micolous) From d0241ed24f4c5f704973867d00fac583227995df Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 22 Feb 2020 19:59:54 +0100 Subject: [PATCH 028/298] does this solve opensuse warning? --- armsrc/appmain.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 15d939a35..415e03291 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -726,7 +726,10 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_SAMPLING_SET_CONFIG: { - setSamplingConfig((sample_config *) packet->data.asBytes); + sample_config c; + memcpy(&c, packet->data.asBytes, sizeof(sample_config)); + setSamplingConfig(&c); +// setSamplingConfig((sample_config *) packet->data.asBytes); break; } case CMD_LF_ACQ_RAW_ADC: { From f2ae1ff57abf9eea3a867988921db5a097d4196a Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 23 Feb 2020 11:21:55 +1100 Subject: [PATCH 029/298] Update cmdlfkeri.c --- client/cmdlfkeri.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 892dfaf5f..b0f45da04 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -104,6 +104,7 @@ static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *I if (FCDecodeState[31- 1] == '1') FCDecodeState[31- 1] = '?'; if (FCDecodeState[31- 2] == '1') FCDecodeState[31- 2] = '?'; + PrintAndLogEx(SUCCESS, "Partial Keri MS decode"); PrintAndLogEx(SUCCESS, "BitState ID : %s",IDDecodeState); PrintAndLogEx(SUCCESS, "BitState FC : %s",FCDecodeState); } @@ -210,8 +211,12 @@ static int CmdKeriDemod(const char *Cmd) { PrintAndLogEx (SUCCESS,"Descrambled MS : FC %d - Card ID %d\n",fc,cardid); +/* + Scamble: For dev testing only, will/should move to the create keri-ms code when added. + uint32_t testCard = 0; CmdKeriMSScramble (Scramble,&fc,&cardid,&testCard); +*/ // End Descramble test From 8b10107c405cd1236d6ca3eefa94dd31b54526a6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 23 Feb 2020 10:28:51 +0100 Subject: [PATCH 030/298] fix: #520 - calling init before initialize mutexs is bad --- client/cmdhfmfhard.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index d83c60047..f9e68ca67 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -2019,12 +2019,12 @@ __attribute__((force_align_arg_pointer)) static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) { - init_statelist_cache(); - init_book_of_work(); - // create mutexes for accessing the statelist cache and our "book of work" pthread_mutex_init(&statelist_cache_mutex, NULL); pthread_mutex_init(&book_of_work_mutex, NULL); + + init_statelist_cache(); + init_book_of_work(); // create and run worker threads pthread_t thread_id[NUM_REDUCTION_WORKING_THREADS]; From cfcb0494590d8dbe611e9e1eaf60f52495fd69de Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 23 Feb 2020 10:45:23 +0100 Subject: [PATCH 031/298] chg: hitag2 now obeys 'lf conf' divisor setting --- armsrc/lfadc.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 6b0eb930a..63b246025 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -69,11 +69,12 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { size_t periods = 0; volatile uint8_t adc_val; uint8_t avg_peak = adc_avg + 3, avg_through = adc_avg - 3; - int16_t checked = 0; +// int16_t checked = 0; while (!BUTTON_PRESS()) { // only every 100th times, in order to save time when collecting samples. +/* if (checked == 1000) { if (data_available()) { break; @@ -82,7 +83,7 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { } } ++checked; - +*/ WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { @@ -164,7 +165,11 @@ void lf_init(bool reader, bool simulate) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_134); + sample_config *sc = getSamplingConfig(); + sc->decimation = 1; + sc->averaging = 0; + + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); if (reader) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); } else { @@ -217,10 +222,6 @@ void lf_init(bool reader, bool simulate) { // use malloc if (logging) initSampleBufferEx(&bufsize, true); - sample_config *sc = getSamplingConfig(); - sc->decimation = 1; - sc->averaging = 0; - lf_sample_mean(); } @@ -237,20 +238,16 @@ void lf_finalize() { LEDsoff(); - sample_config *sc = getSamplingConfig(); - sc->decimation = 1; - sc->averaging = 0; - StartTicks(); } size_t lf_detect_field_drop(size_t max) { size_t periods = 0; - volatile uint8_t adc_val; - int16_t checked = 0; +// int16_t checked = 0; while (!BUTTON_PRESS()) { +/* // only every 1000th times, in order to save time when collecting samples. if (checked == 1000) { if (data_available()) { @@ -261,12 +258,13 @@ size_t lf_detect_field_drop(size_t max) { } } ++checked; +*/ WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { periods++; - adc_val = AT91C_BASE_SSC->SSC_RHR; + volatile uint8_t adc_val = AT91C_BASE_SSC->SSC_RHR; if (logging) logSampleSimple(adc_val); From d9e073410dc29e24fc644dc5f1d8da2af97255a0 Mon Sep 17 00:00:00 2001 From: h4waii <30473690+h4waii@users.noreply.github.com> Date: Mon, 24 Feb 2020 00:04:06 +1100 Subject: [PATCH 032/298] fix: #520 - free mutex after work is done Why not just free after key found or not found? --- client/cmdhfmfhard.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index f9e68ca67..32afd8cf2 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1845,14 +1845,15 @@ static bool TestIfKeyExists(uint64_t key) { num_keys_tested += count; hardnested_print_progress(num_acquired_nonces, "(Test: Key found)", 0.0, 0); crypto1_destroy(pcs); + pthread_mutex_destroy(&statelist_cache_mutex); return true; } } num_keys_tested += count; hardnested_print_progress(num_acquired_nonces, "(Test: Key NOT found)", 0.0, 0); - crypto1_destroy(pcs); + pthread_mutex_destroy(&statelist_cache_mutex); return false; } @@ -2042,9 +2043,6 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) { pthread_join(thread_id[i], NULL); } - // clean up mutex - pthread_mutex_destroy(&statelist_cache_mutex); - maximum_states = 0; for (statelist_t *sl = candidates; sl != NULL; sl = sl->next) { maximum_states += (uint64_t)sl->len[ODD_STATE] * sl->len[EVEN_STATE]; From 87cbe12773eaa4e9468492e30c92c9ba61355af1 Mon Sep 17 00:00:00 2001 From: h4waii <30473690+h4waii@users.noreply.github.com> Date: Mon, 24 Feb 2020 09:23:22 +1100 Subject: [PATCH 033/298] Update termux_notes.md --- doc/termux_notes.md | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/doc/termux_notes.md b/doc/termux_notes.md index d86ec7f08..6b3eb132c 100644 --- a/doc/termux_notes.md +++ b/doc/termux_notes.md @@ -27,17 +27,38 @@ ref : https://github.com/Proxmark/proxmark3/wiki/android - [LineageOS (Android 8.1)](https://download.lineageos.org/) - [LineageOS kernel](https://download.lineageos.org/) - [Magisk 19.3](https://github.com/topjohnwu/Magisk/) + +- Xiaomi Mi Mix 2S (arm64, USB-C) + - [LineageOS (Android 9.0)](https://download.lineageos.org/) + - [Magisk 20.3](https://github.com/topjohnwu/Magisk/) + +- OnePlus 5T (arm64, USB-C) + - [LineageOS (Android 9.0)](https://download.lineageos.org/) + - [Franko Kernel](https://franco-lnx.net/) + - [Magisk 20.3](https://github.com/topjohnwu/Magisk/) + +- Samsung Galaxy Tab S2 (arm64, MicroUSB) + - [LineageOS (Android 9.0)](https://download.lineageos.org/) + - [LineageOS kernel](https://download.lineageos.org/) + - [Magisk 20.3](https://github.com/topjohnwu/Magisk/) + + ## Setup ### Setting up Termux -1. Install [Termux](https://play.google.com/store/apps/details?id=com.termux) and start it -2. Run the following commands: +Install [Termux](https://play.google.com/store/apps/details?id=com.termux) and start it +### Install Proxmark3 package +Run the following commands: +``` +pkg install proxmark3 tsu +``` +### Optional: Building Proxmark3 client from source ``` pkg install make clang clang++ readline libc++ git tsu git clone https://github.com/RfidResearchGroup/proxmark3.git +cd proxmark +make clean && make client ``` -### Building Proxmark3 client -1. `make clean && make client` ### USB_ACM You need the `USB_ACM` driver enabled and working to communicate with the Proxmark3. To see if it's working, run `tsudo ls /dev/tty*` and it should list `/dev/ttyACM0` (or similar). If you see this, congratulations, skip this step! From b05042d8963cce38fa747e9d483e666700072648 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 24 Feb 2020 09:44:48 +0100 Subject: [PATCH 034/298] textual --- client/cmdhf.c | 16 ++++++++++++---- client/cmdlf.c | 18 ++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 78ebbd256..35b50b852 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -178,32 +178,40 @@ int CmdHFTune(const char *Cmd) { if (cmdp == 'h') return usage_hf_tune(); int iter = param_get32ex(Cmd, 0, 0, 10); + PrintAndLogEx(SUCCESS, "Measuring HF antenna, click " _GREEN_("pm3 button") "or press " _GREEN_("Enter") "to exit"); PacketResponseNG resp; - PrintAndLogEx(SUCCESS, "Measuring HF antenna, " _YELLOW_("click button") " or press " _YELLOW_("Enter") "to exit"); clearCommandBuffer(); + uint8_t mode[] = {1}; SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_HF, mode, sizeof(mode)); if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_HF, &resp, 1000)) { PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark HF initialization, aborting"); return PM3_ETIMEOUT; } + mode[0] = 2; // loop forever (till button pressed) if iter = 0 (default) for (uint8_t i = 0; iter == 0 || i < iter; i++) { - if (kbd_enter_pressed()) { // abort by keyboard press + if (kbd_enter_pressed()) { break; } + SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_HF, mode, sizeof(mode)); if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_HF, &resp, 1000)) { + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark HF measure, aborting"); return PM3_ETIMEOUT; } - if ((resp.status == PM3_EOPABORTED) || (resp.length != sizeof(uint16_t))) + + if ((resp.status == PM3_EOPABORTED) || (resp.length != sizeof(uint16_t))) { break; + } + uint16_t volt = resp.data.asDwords[0] & 0xFFFF; - PrintAndLogEx(INPLACE, "%u mV / %5u V", volt, (uint16_t)(volt / 1000)); + PrintAndLogEx(INPLACE, "%u mV / %2u V", volt, (uint16_t)(volt / 1000)); } mode[0] = 3; + SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_HF, mode, sizeof(mode)); if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_HF, &resp, 1000)) { PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark HF shutdown, aborting"); diff --git a/client/cmdlf.c b/client/cmdlf.c index 617d87c0e..b83ed0c89 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -253,34 +253,41 @@ static int CmdLFTune(const char *Cmd) { //Validations if (errors) return usage_lf_tune(); - PrintAndLogEx(SUCCESS, "Measuring LF antenna at %.2f kHz, click button or press Enter to exit", LF_DIV2FREQ(divisor)); + PrintAndLogEx(SUCCESS, "Measuring LF antenna at " _YELLOW_("%.2f") "kHz, click " _GREEN_("pm3 button") "or press " _GREEN_("Enter") "to exit", LF_DIV2FREQ(divisor)); uint8_t params[] = {1, 0}; params[1] = divisor; PacketResponseNG resp; - clearCommandBuffer(); + SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_LF, params, sizeof(params)); if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_LF, &resp, 1000)) { PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark LF initialization, aborting"); return PM3_ETIMEOUT; } + params[0] = 2; // loop forever (till button pressed) if iter = 0 (default) for (uint8_t i = 0; iter == 0 || i < iter; i++) { - if (kbd_enter_pressed()) { // abort by keyboard press + if (kbd_enter_pressed()) { break; } + SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_LF, params, sizeof(params)); if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_LF, &resp, 1000)) { + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark LF measure, aborting"); return PM3_ETIMEOUT; } - if ((resp.status == PM3_EOPABORTED) || (resp.length != sizeof(uint32_t))) + + if ((resp.status == PM3_EOPABORTED) || (resp.length != sizeof(uint32_t))) { break; + } + uint32_t volt = resp.data.asDwords[0]; - PrintAndLogEx(INPLACE, "%u mV / %5u V", volt, (uint32_t)(volt / 1000)); + PrintAndLogEx(INPLACE, "%u mV / %3u V", volt, (uint32_t)(volt / 1000)); } + params[0] = 3; SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_LF, params, sizeof(params)); if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_LF, &resp, 1000)) { @@ -292,7 +299,6 @@ static int CmdLFTune(const char *Cmd) { return PM3_SUCCESS; } - /* send a LF command before reading */ int CmdLFCommandRead(const char *Cmd) { From 11f50ef7bc4ecd7d4f8c0c6d25f5e9459954b366 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 24 Feb 2020 09:45:56 +0100 Subject: [PATCH 035/298] chg: textual and remove adjustment for antenna measures --- client/cmddata.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 613ce11e5..14f8ac259 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1662,16 +1662,15 @@ int CmdTuneSamples(const char *Cmd) { #define LF_MARGINAL_V 10000 #define HF_UNUSABLE_V 3000 #define HF_MARGINAL_V 5000 -#define ANTENNA_ERROR 1.03 // current algo has 3% error margin. +#define ANTENNA_ERROR 1.00 // current algo has 3% error margin. // hide demod plot line DemodBufferLen = 0; setClockGrid(0, 0); RepaintGraphWindow(); - int timeout = 0; - PrintAndLogEx(INFO, "\nMeasuring antenna characteristics, please wait..."); + PrintAndLogEx(INFO, "Measuring antenna characteristics, please wait..."); clearCommandBuffer(); SendCommandNG(CMD_MEASURE_ANTENNA_TUNING, NULL, 0); @@ -1691,7 +1690,7 @@ int CmdTuneSamples(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, ""); // in mVolt struct p { uint32_t v_lf134; From 7750fe24e19af2d83581a06e31c53d129eda49c1 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 24 Feb 2020 14:33:01 -0500 Subject: [PATCH 036/298] timeout --- armsrc/mifarecmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 9e9c721bd..b869489ab 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2229,7 +2229,7 @@ void MifareHasStaticNonce() { nt = bytes_to_num(rec, 4); -// CHK_TIMEOUT(); + CHK_TIMEOUT(); } OUT: From 743325e90f5f492cd395a26e66855b298b864a1c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 24 Feb 2020 20:39:12 +0100 Subject: [PATCH 037/298] chg: make it slower --- armsrc/mifarecmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 9e9c721bd..b869489ab 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2229,7 +2229,7 @@ void MifareHasStaticNonce() { nt = bytes_to_num(rec, 4); -// CHK_TIMEOUT(); + CHK_TIMEOUT(); } OUT: From 17dd4bc57217d9046f14166b411766b98e52151d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 24 Feb 2020 20:39:32 +0100 Subject: [PATCH 038/298] revert #520 --- client/cmdhfmfhard.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 32afd8cf2..90f686b80 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1845,7 +1845,6 @@ static bool TestIfKeyExists(uint64_t key) { num_keys_tested += count; hardnested_print_progress(num_acquired_nonces, "(Test: Key found)", 0.0, 0); crypto1_destroy(pcs); - pthread_mutex_destroy(&statelist_cache_mutex); return true; } } @@ -1853,7 +1852,6 @@ static bool TestIfKeyExists(uint64_t key) { num_keys_tested += count; hardnested_print_progress(num_acquired_nonces, "(Test: Key NOT found)", 0.0, 0); crypto1_destroy(pcs); - pthread_mutex_destroy(&statelist_cache_mutex); return false; } From b87b0313dad220c0c26d3a499e58bdf4b54ea2e4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 24 Feb 2020 20:39:53 +0100 Subject: [PATCH 039/298] chg: tighter detection of static nonce --- client/cmdhfmf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index c8ee0013c..24296b31d 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1279,7 +1279,7 @@ static int CmdHF14AMfNested(const char *Cmd) { } // check if tag doesn't have static nonce - if (detect_classic_static_nonce() != 0) { + if (detect_classic_static_nonce() == 1) { PrintAndLogEx(WARNING, "Static nonce detected. Quitting..."); PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf staticnested`")); return PM3_EOPABORTED; @@ -1839,7 +1839,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { if (!know_target_key && nonce_file_read == false) { // check if tag doesn't have static nonce - if (detect_classic_static_nonce() != 0) { + if (detect_classic_static_nonce() == 1) { PrintAndLogEx(WARNING, "Static nonce detected. Quitting..."); PrintAndLogEx(INFO, "\t Try use `" _YELLOW_("hf mf staticnested") "`"); return PM3_EOPABORTED; From 2f2443c7fa3c493453dd5f86d5b70a4bd3368ec5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 24 Feb 2020 21:31:58 +0100 Subject: [PATCH 040/298] text --- client/proxmark3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index d582bafc0..522d982c7 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -61,7 +61,7 @@ static int check_comm(void) { rl_set_prompt(PROXPROMPT_OFFLINE); rl_forced_update_display(); CloseProxmark(); - PrintAndLogEx(INFO, "Running in " _YELLOW_("OFFLINE") "mode. Use \"hw connect\" to reconnect\n"); + PrintAndLogEx(INFO, "Running in " _YELLOW_("OFFLINE") "mode. Use "_YELLOW_("\"hw connect\"") "to reconnect\n"); } return 0; } From 52452c8ddeb0afe94a43e3ef325436833553710b Mon Sep 17 00:00:00 2001 From: Iceman Date: Tue, 25 Feb 2020 15:37:27 +0100 Subject: [PATCH 041/298] Update Linux-Installation-Instructions.md --- .../Linux-Installation-Instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index 30d4fbf54..b381eb7d9 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -51,7 +51,7 @@ If you don't need the graphical components of the Proxmark3 client (such as in ` ## On openSUSE ```sh -sudo zypper install git patterns-devel-base-devel_basis gcc-c++ readline-devel cross-arm-none-gcc9 cross-arm-none-newlib-devel +sudo zypper install git patterns-devel-base-devel_basis gcc-c++ readline-devel cross-arm-none-gcc9 cross-arm-none-newlib-devel libqt5-qtbase-devel ``` If you don't need the graphical components of the Proxmark3 client (such as in `hw tune`), you can skip the installation of `libqt5-qtbase-devel`. From 33ba0c6f3676e2432ba0481a2d006b36a9eea392 Mon Sep 17 00:00:00 2001 From: bosb <12600404+bosb@users.noreply.github.com> Date: Tue, 25 Feb 2020 20:19:00 +0100 Subject: [PATCH 042/298] hitags fix uid sim + write --- armsrc/hitagS.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 40cdf47ed..68fa825e1 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -940,7 +940,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { memcpy((uint8_t *)tag.pages, data, 4 * 64); } - tag.uid = (uint32_t)tag.pages[0]; + tag.uid = (tag.pages[0][3] << 24 | tag.pages[0][2] << 16 | tag.pages[0][1] << 8 | tag.pages[0][0]); tag.key = (intptr_t)tag.pages[3]; tag.key <<= 16; tag.key += ((tag.pages[2][0]) << 8) + tag.pages[2][1]; @@ -1555,6 +1555,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING From ab7bf0cb2ad9d8579959f25d05025eeddfd563bd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 27 Feb 2020 14:26:28 +0100 Subject: [PATCH 043/298] fix: hf mf autopwn on debian... --- client/cmdhfmfhard.c | 53 +++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 90f686b80..beb85df5b 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1390,7 +1390,6 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ char progress_text[80]; FILE *fnonces = NULL; PacketResponseNG resp; - num_acquired_nonces = 0; clearCommandBuffer(); @@ -1402,24 +1401,35 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ flags |= field_off ? 0x0004 : 0; clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags, key, 6); - if (field_off) break; + if (field_off) { + SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0); + break; + } else { + SendCommandMIX(CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags, key, 6); + } if (initialize) { + if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { - uint8_t nullkey[6] = {0}; - //strange second call (iceman) clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4, nullkey, sizeof(nullkey)); + SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0); return 1; } - if (resp.oldarg[0]) return resp.oldarg[0]; // error during nested_hard + + // error during nested_hard + if (resp.oldarg[0]) { + clearCommandBuffer(); + SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0); + return resp.oldarg[0]; + } cuid = resp.oldarg[1]; if (nonce_file_write && fnonces == NULL) { if ((fnonces = fopen(filename, "wb")) == NULL) { PrintAndLogEx(WARNING, "Could not create file %s", filename); + clearCommandBuffer(); + SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0); return 3; } snprintf(progress_text, 80, "Writing acquired nonces to binary file %s", filename); @@ -1486,17 +1496,24 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ } if (!initialize) { + if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { if (nonce_file_write) { fclose(fnonces); } + clearCommandBuffer(); + SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0); return 1; } + + // error during nested_hard if (resp.oldarg[0]) { if (nonce_file_write) { fclose(fnonces); } - return resp.oldarg[0]; // error during nested_hard + clearCommandBuffer(); + SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0); + return resp.oldarg[0]; } } @@ -1513,11 +1530,6 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ fclose(fnonces); } - // PrintAndLogEx(NORMAL, "Sampled a total of %d nonces in %d seconds (%0.0f nonces/minute)", - // total_num_nonces, - // time(NULL)-time1, - // (float)total_num_nonces*60.0/(time(NULL)-time1)); - return 0; } @@ -1681,11 +1693,12 @@ static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even for (uint8_t remaining_bits = 0; remaining_bits <= (~mask & 0xff); remaining_bits++) { if (remaining_bits_match(num_common, bytes_diff, state, (state & mask) | remaining_bits, odd_even)) { -#ifdef DEBUG_KEY_ELIMINATION - if (bitflips_match(byte2, (state & mask) | remaining_bits, odd_even, true)) { -#else - if (bitflips_match(byte2, (state & mask) | remaining_bits, odd_even)) { -#endif +# ifdef DEBUG_KEY_ELIMINATION + if (bitflips_match(byte2, (state & mask) | remaining_bits, odd_even, true)) +# else + if (bitflips_match(byte2, (state & mask) | remaining_bits, odd_even)) +# endif + { found_match = true; break; } @@ -1694,7 +1707,7 @@ static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even if (!found_match) { -#ifdef DEBUG_KEY_ELIMINATION +# ifdef DEBUG_KEY_ELIMINATION if (known_target_key != -1 && state == test_state[odd_even]) { PrintAndLogEx(NORMAL, "all_bitflips_match() 1st Byte: %s test state (0x%06x): Eliminated. Bytes = %02x, %02x, Common Bits = %d\n", odd_even == ODD_STATE ? "odd" : "even", @@ -1706,7 +1719,7 @@ static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even sprintf(failstr, "Other 1st Byte %s, all_bitflips_match(), no match", odd_even ? "odd" : "even"); } } -#endif +# endif return false; } } From 2886a99350369dd3fbbe151c1a4a1fb63b131883 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 27 Feb 2020 16:35:17 +0100 Subject: [PATCH 044/298] add: cryptohelper support --- client/Makefile | 5 +- client/cmdhficlass.c | 172 +++++++++++++++++++++++------------------- client/cmdsmartcard.c | 54 +++++++------ client/cmdsmartcard.h | 2 +- client/emv/emvcore.c | 2 +- common/cardhelper.c | 83 ++++++++++++++++++++ common/cardhelper.h | 21 ++++++ 7 files changed, 231 insertions(+), 108 deletions(-) create mode 100644 common/cardhelper.c create mode 100644 common/cardhelper.h diff --git a/client/Makefile b/client/Makefile index 6e2ebd001..fae411a52 100644 --- a/client/Makefile +++ b/client/Makefile @@ -130,7 +130,7 @@ CORESRCS = uart_posix.c \ util_posix.c \ scandir.c \ crc16.c \ - comms.c + comms.c CMDSRCS = crapto1/crapto1.c \ crapto1/crypto1.c \ @@ -250,7 +250,8 @@ CMDSRCS = crapto1/crapto1.c \ bucketsort.c \ flash.c \ wiegand_formats.c \ - wiegand_formatutils.c + wiegand_formatutils.c \ + cardhelper.c cpu_arch = $(shell uname -m) ifneq ($(findstring 86, $(cpu_arch)), ) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 567600d15..d69efd475 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -1,8 +1,8 @@ //----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh , Hagen Fritsch // Copyright (C) 2011 Gerhard de Koning Gans // Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende +// Copyright (C) 2020 Iceman // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -12,14 +12,11 @@ //----------------------------------------------------------------------------- #include "cmdhficlass.h" - #include - #include "cmdparser.h" // command_t #include "commonutil.h" // ARRAYLEN #include "cmdtrace.h" #include "util_posix.h" - #include "comms.h" #include "mbedtls/des.h" #include "loclass/cipherutils.h" @@ -28,12 +25,14 @@ #include "loclass/elite_crack.h" #include "fileutils.h" #include "protocols.h" +#include "cardhelper.h" #include "wiegand_formats.h" #include "wiegand_formatutils.h" #define NUM_CSNS 9 #define ICLASS_KEYS_MAX 8 #define ICLASS_AUTH_RETRY 10 +#define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" static int CmdHelp(const char *Cmd); @@ -290,16 +289,6 @@ static int usage_hf_iclass_permutekey(void) { return PM3_SUCCESS; } -/* -static int xorbits_8(uint8_t val) { - uint8_t res = val ^ (val >> 1); //1st pass - res = res ^ (res >> 1); // 2nd pass - res = res ^ (res >> 2); // 3rd pass - res = res ^ (res >> 4); // 4th pass - return res & 1; -} -*/ - // iclass / picopass chip config structures and shared routines typedef struct { uint8_t app_limit; //[8] @@ -311,7 +300,6 @@ typedef struct { uint8_t fuses; //[15] } picopass_conf_block; - typedef struct { uint8_t csn[8]; picopass_conf_block conf; @@ -321,6 +309,13 @@ typedef struct { uint8_t app_issuer_area[8]; } picopass_hdr; +typedef enum { + None = 0, + DES, + RFU, + TRIPLEDES +} BLOCK79ENCRYPTION; + static uint8_t isset(uint8_t val, uint8_t mask) { return (val & mask); } @@ -429,18 +424,18 @@ static void mem_app_config(const picopass_hdr *hdr) { PrintAndLogEx(NORMAL, " Credit - Kc"); } } + static void print_picopass_info(const picopass_hdr *hdr) { fuse_config(hdr); mem_app_config(hdr); } + static void printIclassDumpInfo(uint8_t *iclass_dump) { print_picopass_info((picopass_hdr *) iclass_dump); } - static int CmdHFiClassList(const char *Cmd) { (void)Cmd; // Cmd is not used so far - //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list iclass' instead"); CmdTraceList("iclass"); return PM3_SUCCESS; } @@ -475,24 +470,9 @@ static int CmdHFiClassSim(const char *Cmd) { return usage_hf_iclass_sim(); } - /* - // pre-defined 8 CSN by Holiman - uint8_t csns[8*NUM_CSNS] = { - 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x13, 0x94, 0x7E, 0x76, 0xFF, 0x12, 0xE0, - 0x2A, 0x99, 0xAC, 0x79, 0xEC, 0xFF, 0x12, 0xE0, - 0x17, 0x12, 0x01, 0xFD, 0xF7, 0xFF, 0x12, 0xE0, - 0xCD, 0x56, 0x01, 0x7C, 0x6F, 0xFF, 0x12, 0xE0, - 0x4B, 0x5E, 0x0B, 0x72, 0xEF, 0xFF, 0x12, 0xE0, - 0x00, 0x73, 0xD8, 0x75, 0x58, 0xFF, 0x12, 0xE0, - 0x0C, 0x90, 0x32, 0xF3, 0x5D, 0xFF, 0x12, 0xE0 - }; - */ - /* - pre-defined 9 CSN by iceman - only one csn depend on several others. - six depends only on the first csn, (0,1, 0x45) - */ + // remember to change the define NUM_CSNS to match. + + // pre-defined 9 CSN by iceman uint8_t csns[8 * NUM_CSNS] = { 0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, 0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0, @@ -505,27 +485,6 @@ static int CmdHFiClassSim(const char *Cmd) { 0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0 //0x04, 0x08, 0x9F, 0x78, 0x6E, 0xFF, 0x12, 0xE0 }; - /* - // pre-defined 15 CSN by Carl55 - // remember to change the define NUM_CSNS to match. - uint8_t csns[8*NUM_CSNS] = { - 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 - }; - */ /* DUMPFILE FORMAT: * @@ -801,8 +760,6 @@ static int CmdHFiClassELoad(const char *Cmd) { return PM3_SUCCESS; } -#define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" - static int CmdHFiClassDecrypt(const char *Cmd) { bool errors = false; @@ -812,6 +769,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { uint8_t cmdp = 0; uint8_t enc_data[8] = {0}; + uint8_t dec_data[8] = {0}; size_t keylen = 0; uint8_t key[32] = {0}; @@ -865,11 +823,14 @@ static int CmdHFiClassDecrypt(const char *Cmd) { if (errors || cmdp < 1) return usage_hf_iclass_decrypt(); - if (have_key == false) { - int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); - if (res != PM3_SUCCESS) - return PM3_EINVARG; + bool use_sc = IsCryptoHelperPresent(); + if (have_key == false && use_sc == false) { + int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(INFO, "Couldn't find any decryption methods"); + return PM3_EINVARG; + } memcpy(key, keyptr, sizeof(key)); free(keyptr); } @@ -878,10 +839,13 @@ static int CmdHFiClassDecrypt(const char *Cmd) { mbedtls_des3_context ctx; mbedtls_des3_set2key_dec(&ctx, key); - uint8_t dec_data[8] = {0}; - if (have_data) { - mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data); + + if (use_sc) { + Decrypt(enc_data, dec_data); + } else { + mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data); + } PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(dec_data, sizeof(dec_data))); } @@ -897,6 +861,8 @@ static int CmdHFiClassDecrypt(const char *Cmd) { getMemConfig(mem, chip, &max_blk, &app_areas, &kb); uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + BLOCK79ENCRYPTION aa1_encryption = (decrypted[(6 * 8) + 7] & 0x03); for (uint16_t blocknum = 0; blocknum < applimit; ++blocknum) { @@ -904,8 +870,17 @@ static int CmdHFiClassDecrypt(const char *Cmd) { memcpy(enc_data, decrypted + idx, 8); // block 7 or higher, and not empty 0xFF - if (blocknum > 6 && memcmp(enc_data, empty, 8) != 0) { - mbedtls_des3_crypt_ecb(&ctx, enc_data, decrypted + idx); + // look inside block 6 to determine if aa1 is encrypted. + if (blocknum > 6 && memcmp(enc_data, empty, 8) != 0) { + + if (aa1_encryption == RFU || aa1_encryption == None) + continue; + + if (use_sc) { + Decrypt(enc_data, decrypted + idx); + } else { + mbedtls_des3_crypt_ecb(&ctx, enc_data, decrypted + idx); + } } } @@ -920,16 +895,43 @@ static int CmdHFiClassDecrypt(const char *Cmd) { printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen); - uint32_t top = 0, mid, bot; - mid = bytes_to_num(decrypted + (8*7), 4); - bot = bytes_to_num(decrypted + (8*7) + 4, 4); - PrintAndLogEx(INFO, ""); - PrintAndLogEx(INFO, "block 7 - Wiegand decode"); - wiegand_message_t packed = initialize_message_object(top, mid, bot); - HIDTryUnpack(&packed, true); - PrintAndLogEx(INFO, "-----------------------------------------------------------------"); - + // decode block 6 + if (memcmp(decrypted + (8*6), empty, 8) != 0 ) { + if (use_sc) { + DecodeBlock6(decrypted + (8*6)); + } + } + + // decode block 7-8-9 + if (memcmp(decrypted + (8*7), empty, 8) != 0 ) { + + //todo: remove preamble/sentinal + + uint32_t top = 0, mid, bot; + mid = bytes_to_num(decrypted + (8*7), 4); + bot = bytes_to_num(decrypted + (8*7) + 4, 4); + + PrintAndLogEx(INFO, "Block 7 binary"); + + char hexstr[8+1] = {0}; + hex_to_buffer((uint8_t *)hexstr, decrypted + (8*7), 8, sizeof(hexstr) - 1, 0, 0, true); + + char binstr[8*8+1] = {0}; + hextobinstring(binstr, hexstr); + uint8_t i=0; + while (iblockdata, sizeof(result->blockdata))); + + if (blockno == 6) { + if (IsCryptoHelperPresent()) { + DecodeBlock6(result->blockdata); + } + } + return PM3_SUCCESS; } diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 6422fe605..ba48fae96 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -216,23 +216,23 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { bool protocol_T15_present = false; if (T0 & 0x10) { - PrintAndLogEx(NORMAL, "\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]); + PrintAndLogEx(INFO, "\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]); T1len++; } if (T0 & 0x20) { - PrintAndLogEx(NORMAL, "\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr[2 + T1len]); + PrintAndLogEx(INFO, "\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr[2 + T1len]); T1len++; } if (T0 & 0x40) { - PrintAndLogEx(NORMAL, "\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr[2 + T1len]); + PrintAndLogEx(INFO, "\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr[2 + T1len]); T1len++; } if (T0 & 0x80) { uint8_t TD1 = atr[2 + T1len]; - PrintAndLogEx(NORMAL, "\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f); + PrintAndLogEx(INFO, "\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f); protocol_T0_present = false; if ((TD1 & 0x0f) == 0) { protocol_T0_present = true; @@ -244,20 +244,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { T1len++; if (TD1 & 0x10) { - PrintAndLogEx(NORMAL, "\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr[2 + T1len + TD1len]); + PrintAndLogEx(INFO, "\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr[2 + T1len + TD1len]); TD1len++; } if (TD1 & 0x20) { - PrintAndLogEx(NORMAL, "\t- TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr[2 + T1len + TD1len]); + PrintAndLogEx(INFO, "\t- TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr[2 + T1len + TD1len]); TD1len++; } if (TD1 & 0x40) { - PrintAndLogEx(NORMAL, "\t- TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr[2 + T1len + TD1len]); + PrintAndLogEx(INFO, "\t- TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr[2 + T1len + TD1len]); TD1len++; } if (TD1 & 0x80) { uint8_t TDi = atr[2 + T1len + TD1len]; - PrintAndLogEx(NORMAL, "\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f); + PrintAndLogEx(INFO, "\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f); if ((TDi & 0x0f) == 0) { protocol_T0_present = true; } @@ -271,20 +271,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { while (nextCycle) { nextCycle = false; if (TDi & 0x10) { - PrintAndLogEx(NORMAL, "\t- TA%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); + PrintAndLogEx(INFO, "\t- TA%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); TDilen++; } if (TDi & 0x20) { - PrintAndLogEx(NORMAL, "\t- TB%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); + PrintAndLogEx(INFO, "\t- TB%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); TDilen++; } if (TDi & 0x40) { - PrintAndLogEx(NORMAL, "\t- TC%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); + PrintAndLogEx(INFO, "\t- TC%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); TDilen++; } if (TDi & 0x80) { TDi = atr[2 + T1len + TD1len + TDilen]; - PrintAndLogEx(NORMAL, "\t- TD%d [ 0x%02x ] Protocol T%d", vi, TDi, TDi & 0x0f); + PrintAndLogEx(INFO, "\t- TD%d [ 0x%02x ] Protocol T%d", vi, TDi, TDi & 0x0f); TDilen++; nextCycle = true; @@ -314,7 +314,7 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { PrintAndLogEx(WARNING, "Invalid ATR length. len: %zu, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K); if (K > 0) - PrintAndLogEx(INFO, "\nHistorical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]); + PrintAndLogEx(INFO, "Historical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]); if (K > 1) { PrintAndLogEx(INFO, "\tHistorical bytes"); @@ -361,7 +361,9 @@ static int smart_responseEx(uint8_t *data, bool silent) { if (needGetData) { int len = data[datalen - 1]; + if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); + uint8_t getstatus[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, len}; clearCommandBuffer(); SendCommandOLD(CMD_SMART_RAW, SC_RAW, sizeof(getstatus), 0, getstatus, sizeof(getstatus)); @@ -740,10 +742,9 @@ static int CmdSmartInfo(const char *Cmd) { PrintAndLogEx(INFO, "--- Smartcard Information ---------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, "ISO7618-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); - PrintAndLogEx(INFO, "\nhttp://smartcard-atr.apdu.fr/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len)); + PrintAndLogEx(INFO, "http://smartcard-atr.apdu.fr/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len)); // print ATR - PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "ATR"); PrintATR(card.atr, card.atr_len); @@ -756,14 +757,14 @@ static int CmdSmartInfo(const char *Cmd) { if (GetATRTA1(card.atr, card.atr_len) == 0x11) PrintAndLogEx(INFO, "Using default values..."); - PrintAndLogEx(NORMAL, "\t- Di %d", Di); - PrintAndLogEx(NORMAL, "\t- Fi %d", Fi); - PrintAndLogEx(NORMAL, "\t- F %.1f MHz", F); + PrintAndLogEx(INFO, "\t- Di %d", Di); + PrintAndLogEx(INFO, "\t- Fi %d", Fi); + PrintAndLogEx(INFO, "\t- F %.1f MHz", F); if (Di && Fi) { - PrintAndLogEx(NORMAL, "\t- Cycles/ETU %d", Fi / Di); - PrintAndLogEx(NORMAL, "\t- %.1f bits/sec at 4 MHz", (float)4000000 / (Fi / Di)); - PrintAndLogEx(NORMAL, "\t- %.1f bits/sec at Fmax (%.1fMHz)", (F * 1000000) / (Fi / Di), F); + PrintAndLogEx(INFO, "\t- Cycles/ETU %d", Fi / Di); + PrintAndLogEx(INFO, "\t- %.1f bits/sec at 4 MHz", (float)4000000 / (Fi / Di)); + PrintAndLogEx(INFO, "\t- %.1f bits/sec at Fmax (%.1fMHz)", (F * 1000000) / (Fi / Di), F); } else { PrintAndLogEx(WARNING, "\t- Di or Fi is RFU."); }; @@ -1156,11 +1157,12 @@ int CmdSmartcard(const char *Cmd) { return CmdsParse(CommandTable, Cmd); } -int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { +int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + *dataoutlen = 0; if (activateCard) - smart_select(false, NULL); + smart_select(true, NULL); PrintAndLogEx(DEBUG, "APDU SC"); @@ -1168,10 +1170,11 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave if (activateCard) { flags |= SC_SELECT | SC_CONNECT; } + clearCommandBuffer(); SendCommandOLD(CMD_SMART_RAW, flags, datainlen, 0, datain, datainlen); - int len = smart_responseEx(dataout, true); + int len = smart_responseEx(dataout, silent); if (len < 0) { return 1; @@ -1189,7 +1192,7 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave // something fishy: we have only 5 bytes but we put datainlen in arg1? SendCommandOLD(CMD_SMART_RAW, SC_RAW_T0, datainlen, 0, data, sizeof(data)); - len = smart_responseEx(dataout, true); + len = smart_responseEx(dataout, silent); } *dataoutlen = len; @@ -1204,6 +1207,7 @@ bool smart_select(bool silent, smart_card_atr_t *atr) { SendCommandNG(CMD_SMART_ATR, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return false; } diff --git a/client/cmdsmartcard.h b/client/cmdsmartcard.h index 74c305a0d..798ea4678 100644 --- a/client/cmdsmartcard.h +++ b/client/cmdsmartcard.h @@ -17,6 +17,6 @@ int CmdSmartcard(const char *Cmd); bool smart_select(bool silent, smart_card_atr_t *atr); -int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); #endif diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 5bf330fe4..fe5ff3a31 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -305,7 +305,7 @@ static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool Lea break; case ECC_CONTACT: if (IfPm3Smartcard()) - res = ExchangeAPDUSC(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + res = ExchangeAPDUSC(true, data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); else res = 1; if (res) { diff --git a/common/cardhelper.c b/common/cardhelper.c new file mode 100644 index 000000000..704a4f749 --- /dev/null +++ b/common/cardhelper.c @@ -0,0 +1,83 @@ +//----------------------------------------------------------------------------- +// Iceman, February 2020 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Support functions for smart card +//----------------------------------------------------------------------------- +#include "cardhelper.h" +#include +#include +#include "cmdparser.h" +#include "cmdsmartcard.h" +#include "ui.h" +#include "util.h" + +#define CARD_INS_DECRYPT 0x01 +#define CARD_INS_ENCRYPT 0x02 +#define CARD_INS_DECODE 0x06 +static uint8_t cmd[] = {0x96, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// look for CryptoHelper +bool IsCryptoHelperPresent(void) { + + if (IfPm3Smartcard()) { + int resp_len = 0; + uint8_t version[] = {0x96, 0x69, 0x00, 0x00, 0x00}; + uint8_t resp[20] = {0}; + ExchangeAPDUSC(true, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len); + + if (strstr("CryptoHelper", (char*)resp) == 0) { + PrintAndLogEx(INFO, "Found smart card helper"); + return true; + } else { + return false; + } + } else { + return false; + } +} + +static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) { + int resp_len = 0; + uint8_t dec[11] = {0}; + + cmd[1] = ins; + memcpy(cmd + 5, src, 8); + + ExchangeAPDUSC(true, cmd, sizeof(cmd), false, true, dec, sizeof(dec), &resp_len); + + if (resp_len == 10) { + memcpy(dest, dec, 8); + return true; + } + return false; +} + +bool Decrypt(uint8_t *src, uint8_t *dest){ + return executeCrypto(CARD_INS_DECRYPT, src, dest); +} + +bool Encrypt(uint8_t *src, uint8_t *dest){ + return executeCrypto(CARD_INS_ENCRYPT, src, dest); +} + +void DecodeBlock6(uint8_t *src) { + int resp_len = 0; + uint8_t resp[254] = {0}; + + uint8_t c[] = {0x96, CARD_INS_DECODE, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + memcpy(c + 6, src, 8); + + // first part + ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + PrintAndLogEx(SUCCESS, "%0.*s", resp_len - 11, resp + 9); + + // second part + c[5] = 0x02; + ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + PrintAndLogEx(SUCCESS, "%0.*s", resp_len - 11, resp + 9); +} + diff --git a/common/cardhelper.h b/common/cardhelper.h new file mode 100644 index 000000000..14ae23d1f --- /dev/null +++ b/common/cardhelper.h @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// Iceman, February 2020 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Utility functions used in many places, not specific to any piece of code. +//----------------------------------------------------------------------------- + +#ifndef __CARDHELPER_H +#define __CARDHELPER_H + +#include +#include "common.h" + +bool IsCryptoHelperPresent(void); +bool Encrypt(uint8_t *src, uint8_t *dest); +bool Decrypt(uint8_t *src, uint8_t *dest); +void DecodeBlock6(uint8_t *src); +#endif From e14c11e1c804fc6d8986025f037eb265e418355b Mon Sep 17 00:00:00 2001 From: capnkrunchy <47148444+capnkrunchy@users.noreply.github.com> Date: Thu, 27 Feb 2020 11:26:16 -0600 Subject: [PATCH 045/298] Fix lf hid brute --- client/cmdlfhid.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 201dcef84..1e77cff08 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -369,9 +369,11 @@ static int CmdHIDBrute(const char *Cmd) { uint8_t cmdp = 0; int format_idx = -1; char format[16] = {0}; - wiegand_card_t data; - memset(&data, 0, sizeof(wiegand_card_t)); - + wiegand_card_t datahi; + memset(&datahi, 0, sizeof(wiegand_card_t)); + wiegand_card_t datalo; + memset(&datalo, 0, sizeof(wiegand_card_t)); + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': @@ -386,7 +388,8 @@ static int CmdHIDBrute(const char *Cmd) { cmdp += 2; break; case 'c': - data.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10); + datahi.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10); + datalo.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; case 'd': @@ -395,15 +398,18 @@ static int CmdHIDBrute(const char *Cmd) { cmdp += 2; break; case 'f': - data.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10); + datahi.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10); + datalo.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; case 'i': - data.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10); + datahi.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10); + datalo.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; case 'o': - data.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10); + datahi.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10); + datalo.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; case 'v': @@ -435,15 +441,15 @@ static int CmdHIDBrute(const char *Cmd) { } // Do one up - if (data.CardNumber < 0xFFFF) { - data.CardNumber++; - if (sendTry(format_idx, &data, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; + if (datahi.CardNumber < 0xFFFF) { + datahi.CardNumber++; + if (sendTry(format_idx, &datahi, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; } - - // Do one down (if cardnumber is given) - if (data.CardNumber > 1) { - data.CardNumber--; - if (sendTry(format_idx, &data, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; + + // Do one up + if (datalo.CardNumber > 1) { + datalo.CardNumber--; + if (sendTry(format_idx, &datalo, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; } } return PM3_SUCCESS; From de65a431cfd9a5dd45f3004bbe2ed220c0050b84 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Fri, 28 Feb 2020 19:28:51 +1100 Subject: [PATCH 046/298] Update cmdlfkeri.c --- client/cmdlfkeri.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index b0f45da04..4a0c3c8fd 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -181,7 +181,10 @@ static int CmdKeriDemod(const char *Cmd) { uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32); //get internal id - uint32_t ID = bytebits_to_byte(DemodBuffer + 29, 32); + // uint32_t ID = bytebits_to_byte(DemodBuffer + 29, 32); + // Due to the 3 sync bits being at the start of the capture + // We can take the last 32bits as the internal ID. + uint32_t ID = raw2; ID &= 0x7FFFFFFF; /* From 9dc419cec5803412c28d43c105efd5159232e801 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 28 Feb 2020 10:01:52 +0100 Subject: [PATCH 047/298] partial fix for mattyrun --- armsrc/Standalone/hf_mattyrun.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index 3e53fffe9..60619e657 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -323,7 +323,7 @@ void RunMod() { Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B' : 'A', mfKeysCnt); int key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64); if (key == -1) { - LED(LED_RED, 50); //red + LED(LED_RED, 50); Dbprintf("\t✕ Key not found for this sector!"); allKeysFound = false; // break; @@ -348,21 +348,24 @@ void RunMod() { TODO: - Get UID from tag and set accordingly in emulator memory and call mifaresim 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; + if (allKeysFound) { + Dbprintf("\t✓ All keys found"); } else { - Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!"); - LED_C_ON(); //red + if (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 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(); From c30bb354ac6d38a69a8e8d545e42c9020a1a0131 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 29 Feb 2020 09:27:55 +0100 Subject: [PATCH 048/298] chg: 'lf hid brute' - now uses UP/DOWN to specify direction only, more verbose and actually exits when done. --- client/cmdlfhid.c | 121 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 25 deletions(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 1e77cff08..c10c5c56c 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -83,16 +83,18 @@ static int usage_lf_hid_brute(void) { PrintAndLogEx(NORMAL, "This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step"); PrintAndLogEx(NORMAL, "if cardnumber is not given, it starts with 1 and goes up to 65535"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf hid brute [h] [v] w [ (decimal)>] {...}"); + PrintAndLogEx(NORMAL, "Usage: lf hid brute [h] [v] w [ (decimal)>] [up|down] {...}"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " w : see `wiegand list` for available formats"); + PrintAndLogEx(NORMAL, " w : see " _YELLOW_("`wiegand list`") "for available formats"); PrintAndLogEx(NORMAL, " f : facility code"); PrintAndLogEx(NORMAL, " c : card number to start with"); PrintAndLogEx(NORMAL, " i : issue level"); PrintAndLogEx(NORMAL, " o : OEM code"); PrintAndLogEx(NORMAL, " d : delay betweens attempts in ms. Default 1000ms"); PrintAndLogEx(NORMAL, " v : verbose logging, show all tries"); + PrintAndLogEx(NORMAL, " up : direction to increment card number. (default is both directions)"); + PrintAndLogEx(NORMAL, " down : direction to decrement card number. (default is both directions)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hid brute w H10301 f 224"); @@ -368,13 +370,28 @@ static int CmdHIDBrute(const char *Cmd) { uint32_t delay = 1000; uint8_t cmdp = 0; int format_idx = -1; + int direction = 0; char format[16] = {0}; - wiegand_card_t datahi; - memset(&datahi, 0, sizeof(wiegand_card_t)); - wiegand_card_t datalo; - memset(&datalo, 0, sizeof(wiegand_card_t)); + + wiegand_card_t cn_hi, cn_low; + memset(&cn_hi, 0, sizeof(wiegand_card_t)); while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + + char s[10] = {0}; + if (param_getstr(Cmd, cmdp, s, sizeof(s)) > 0) { + if (strlen(s) > 1) { + str_lower((char *)s); + if (str_startswith(s, "up")) { + direction = 1; + } else if (str_startswith(s, "do")) { + direction = 2; + } + cmdp++; + continue; + } + } + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_lf_hid_brute(); @@ -388,8 +405,7 @@ static int CmdHIDBrute(const char *Cmd) { cmdp += 2; break; case 'c': - datahi.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10); - datalo.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10); + cn_hi.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; case 'd': @@ -398,18 +414,15 @@ static int CmdHIDBrute(const char *Cmd) { cmdp += 2; break; case 'f': - datahi.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10); - datalo.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10); + cn_hi.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; case 'i': - datahi.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10); - datalo.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10); + cn_hi.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; case 'o': - datahi.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10); - datalo.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10); + cn_hi.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; case 'v': @@ -422,13 +435,45 @@ static int CmdHIDBrute(const char *Cmd) { break; } } + + if (format_idx == -1) { + PrintAndLogEx(ERR, "You must select a wiegand format. See " _YELLOW_("`wiegand list`") "for available formats\n"); + errors = true; + } + if (errors) return usage_lf_hid_brute(); + if (verbose) { + PrintAndLogEx(INFO, "Wiegand format#.. %i", format_idx); + PrintAndLogEx(INFO, "OEM#............. %u", cn_hi.OEM); + PrintAndLogEx(INFO, "ISSUE#........... %u", cn_hi.IssueLevel); + PrintAndLogEx(INFO, "Facility#........ %u", cn_hi.FacilityCode); + PrintAndLogEx(INFO, "Card#............ %u", cn_hi.CardNumber); + switch( direction) { + case 0: + PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("BOTH")); + break; + case 1: + PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("UP")); + break; + case 2: + PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("DOWN")); + break; + default: break; + } + } PrintAndLogEx(INFO, "Brute-forcing HID reader"); - PrintAndLogEx(INFO, "Press pm3-button to abort simulation or run another command"); + PrintAndLogEx(INFO, "Press pm3-button to abort simulation or press `enter` to exit"); + + // copy values to low. + cn_low = cn_hi; // main loop - for (;;) { + // iceman: could add options for bruteforcing OEM, ISSUE or FC aswell.. + bool exitloop = false; + bool fin_hi, fin_low; + fin_hi = fin_low = false; + do { if (!session.pm3_present) { PrintAndLogEx(WARNING, "Device offline\n"); @@ -440,18 +485,44 @@ static int CmdHIDBrute(const char *Cmd) { return sendPing(); } - // Do one up - if (datahi.CardNumber < 0xFFFF) { - datahi.CardNumber++; - if (sendTry(format_idx, &datahi, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; + // do one up + if (direction != 2) { + if (cn_hi.CardNumber < 0xFFFF) { + cn_hi.CardNumber++; + if (sendTry(format_idx, &cn_hi, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; + } else { + fin_hi = true; + } } - // Do one up - if (datalo.CardNumber > 1) { - datalo.CardNumber--; - if (sendTry(format_idx, &datalo, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; + // do one down + if (direction != 1) { + if (cn_low.CardNumber > 0) { + cn_low.CardNumber--; + if (sendTry(format_idx, &cn_low, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; + } else { + fin_low = true; + } } - } + + switch (direction) { + case 0: + if (fin_hi && fin_low) { + exitloop = true; + } + break; + case 1: + exitloop = fin_hi; + break; + case 2: + exitloop = fin_low; + break; + default: break; + } + + } while (exitloop == false); + + PrintAndLogEx(INFO, "Brute forcing finished"); return PM3_SUCCESS; } From 8617acee7135b1140fc4cd7083d19262e39c9dda Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 29 Feb 2020 16:22:18 +0100 Subject: [PATCH 049/298] textual --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index af8b073ca..8015a76f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,16 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Chnage `lf keri demod` - adjusted the internal id. (@mwalker33) + - Added seamless integration with cryptohelper (@iceman1001) + - Change `lf hid brute` - new params for direction (UP/DOWN); textual and main loop actually exit. (@capnkrunchy and @iceman1001) + - Fix `lf hid brute` - made it work again (@capnkrunchy) + - Fix standalone mode HF_MATTYRUN - correct logic when all keys found in printing. partial fix (@iceman1001) + - Change static nonce detection got tighter (@iceman1001) + - Improved termux notes (@msoose) + - Fix `hf mf autopwn` - works on debian 10 *nix. Bad exit commands in hardnested (@iceman1001) + - Fix `hf mf hardnested` - bad mutex strategies (@msoose) + - Change `lf hitag` - now obeys `lf config` (@iceman1001) - Ported all python 2 scripts to python 3 (@doegox and @sigwinch28) - Removed undefined exit behaviour from `analyzesize` tool: it now exits with code 2 when called with wrong args (@sigwinch28) - Replaced shebangs in scripts with more portable versions which use `/usr/bin/env` (@sigwinch28) From 05dc1f7e5f77e70a4e1544f76319886cdba6cf38 Mon Sep 17 00:00:00 2001 From: bosb <12600404+bosb@users.noreply.github.com> Date: Sat, 29 Feb 2020 18:35:56 +0100 Subject: [PATCH 050/298] fix send frame, some config bytes from tag, use global dbg level --- armsrc/hitagS.c | 59 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 68fa825e1..50a96f178 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -86,7 +86,7 @@ bool end = false; #define HITAG_T_TAG_CAPTURE_THREE_HALF 41 #define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 -#define DEBUG 0 +#define DBGLEVEL 4 /* * Implementation of the crc8 calculation from Hitag S @@ -207,6 +207,22 @@ static void hitag_send_bit(int bit) { } static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { + // The beginning of the frame is hidden in some high level; pause until our bits come out + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + HIGH(GPIO_SSC_DOUT); + switch (m) { + case AC4K: + while (AT91C_BASE_TC0->TC_CV < T0 * 40) {}; //FADV + break; + case AC2K: + while (AT91C_BASE_TC0->TC_CV < T0 * 20) {}; //STD + ADV + break; + case MC4K: + break; + case MC8K: + break; + } + // SOF - send start of frame for (size_t i = 0; i < sof_bits; i++) { hitag_send_bit(1); @@ -318,20 +334,28 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, switch (rxlen) { case 5: { //UID request with a selected response protocol mode + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("...UID req %i %02x", rxlen, rx[0]); tag.pstate = HT_READY; tag.tstate = HT_NO_OP; if ((rx[0] & 0xf0) == 0x30) { + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("HT_STANDARD"); tag.mode = HT_STANDARD; sof_bits = 1; m = AC2K; } if ((rx[0] & 0xf0) == 0xc0) { tag.mode = HT_ADVANCED; + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("HT_ADVANCED"); sof_bits = 3; m = AC2K; } if ((rx[0] & 0xf0) == 0xd0) { + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("HT_FAST_ADVANCED"); tag.mode = HT_FAST_ADVANCED; sof_bits = 3; m = AC4K; @@ -344,7 +368,9 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, break; case 45: { //select command from reader received + DbpString("...select"); if (check_select(rx, tag.uid) == 1) { + DbpString("...select match"); //if the right tag was selected *txlen = 32; switch (tag.mode) { @@ -366,7 +392,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, //send configuration for (int i = 0; i < 4; i++) - tx[i] = (tag.pages[0][1] >> (i * 8)) & 0xff; + tx[i] = tag.pages[1][i]; tx[3] = 0xff; if (tag.mode != HT_STANDARD) { *txlen = 40; @@ -439,6 +465,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, */ } case 40: + Dbprintf("....write"); //data received to be written if (tag.tstate == HT_WRITING_PAGE_DATA) { tag.tstate = HT_NO_OP; @@ -495,6 +522,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } break; case 20: { + Dbprintf("....read"); //write page, write block, read page or read block command received if ((rx[0] & 0xf0) == 0xc0) { //read page //send page data @@ -644,7 +672,11 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } break; default: - + if (DBGLEVEL >= DBG_EXTENDED) { + Dbprintf("rxlen: %i", rxlen); + for (int i = 0; i < 4; i++) + Dbprintf("%i: %02X",i,rx[i]); + } break; } } @@ -722,7 +754,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA | (uid[30] << 1) | uid[31]; - if (DEBUG) + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4); tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1); @@ -816,7 +848,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA tag.LCK1 = response_bit[26]; tag.LCK0 = response_bit[27]; - if (DEBUG) + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], conf_pages[1], conf_pages[2]); if (tag.auth == 1) { @@ -839,7 +871,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA tx[5] = auth_ks[1]; tx[6] = auth_ks[2]; tx[7] = auth_ks[3]; - if (DEBUG) + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0], tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]); } else if (htf == 01 || htf == 03) { //RHTS_CHALLENGE //WHTS_CHALLENGE @@ -864,7 +896,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA calc_crc(&crc, ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)), 8); calc_crc(&crc, ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)), 8); calc_crc(&crc, ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)), 8); - if (DEBUG) { + if (DBGLEVEL >= DBG_EXTENDED) { Dbprintf("UID:::%X", tag.uid); Dbprintf("RND:::%X", rnd); } @@ -884,7 +916,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) ^ _hitag2_byte(&state); } - if (DEBUG) + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1); //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16)); @@ -941,12 +973,12 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { } tag.uid = (tag.pages[0][3] << 24 | tag.pages[0][2] << 16 | tag.pages[0][1] << 8 | tag.pages[0][0]); - tag.key = (intptr_t)tag.pages[3]; + tag.key = (tag.pages[3][3] << 24 | tag.pages[3][2] << 16 | tag.pages[3][1] << 8 | tag.pages[3][0]); tag.key <<= 16; - tag.key += ((tag.pages[2][0]) << 8) + tag.pages[2][1]; - tag.pwdl0 = tag.pages[2][3]; - tag.pwdl1 = tag.pages[2][2]; - tag.pwdh0 = tag.pages[1][0]; + tag.key += ((tag.pages[2][3]) << 8) + tag.pages[2][2]; + tag.pwdl0 = tag.pages[2][0]; + tag.pwdl1 = tag.pages[2][1]; + tag.pwdh0 = tag.pages[1][3]; //con0 tag.max_page = 64; if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 1) @@ -1114,6 +1146,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { overflow += (AT91C_BASE_TC1->TC_CV / T0); // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + } LEDsoff(); From bf975af358e1694bd48f37458e709b05311bf92c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 29 Feb 2020 21:09:16 +0100 Subject: [PATCH 051/298] fix coverty 267216 resource leak --- client/mifare/mifarehost.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 31085a629..3668f3332 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -676,6 +676,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl //flush queue while (kbd_enter_pressed()) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + free(mem); return PM3_EOPABORTED; } @@ -695,6 +696,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6) ); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, "SPIFFS upload failed"); + free(mem); return res; } @@ -717,6 +719,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl ); return PM3_SUCCESS; } else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) { + free(mem); return res; } From 8908798efda9e9fab47a16674a7702995dc94e5b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 1 Mar 2020 16:38:01 +0100 Subject: [PATCH 052/298] fix coverity 267218 --- client/mifare/mifarehost.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 3668f3332..388cc029e 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -544,8 +544,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, return -5; } - uint64_t t2 = msclock(); - float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(t2 - start_time) * 1000.0; + float bruteforce_per_second = (float)KEYS_IN_BLOCK / (msclock() - start_time) * 1000.0; if ( i + 1 % 10 == 0) PrintAndLogEx(INFO, " %6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt , bruteforce_per_second, (keycnt-i) / bruteforce_per_second); @@ -724,7 +723,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl } // if (i%10 == 0) { - float bruteforce_per_second = (float)i + max_keys_chunk / (float)(msclock() - start_time) * 1000.0; + float bruteforce_per_second = (float)i + max_keys_chunk / (msclock() - start_time) * 1000.0; PrintAndLogEx(INFO, "Chunk %6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); // } } From d11716110f0a0377fa11b11c96d0f1ae186f5da6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 1 Mar 2020 16:39:25 +0100 Subject: [PATCH 053/298] fix coverity 267215 --- armsrc/lfadc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 63b246025..32d1e73b6 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -133,16 +133,18 @@ size_t lf_detect_gap(size_t max) { } void lf_reset_counter() { + // TODO: find out the correct reset settings for tag and reader mode - if (reader_mode) { +// if (reader_mode) { // Reset values for reader mode rising_edge = false; previous_adc_val = 0xFF; - } else { + +// } else { // Reset values for tag/transponder mode - rising_edge = false; - previous_adc_val = 0xFF; - } +// rising_edge = false; +// previous_adc_val = 0xFF; +// } } bool lf_get_tag_modulation() { From 9c9906c823b0fe7ec3dcd608ad6fb6e9384c8663 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 1 Mar 2020 16:46:31 +0100 Subject: [PATCH 054/298] fix coverity 267213 --- common/cardhelper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/cardhelper.c b/common/cardhelper.c index 704a4f749..93e361f60 100644 --- a/common/cardhelper.c +++ b/common/cardhelper.c @@ -73,11 +73,11 @@ void DecodeBlock6(uint8_t *src) { // first part ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); - PrintAndLogEx(SUCCESS, "%0.*s", resp_len - 11, resp + 9); + PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9); // second part c[5] = 0x02; ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); - PrintAndLogEx(SUCCESS, "%0.*s", resp_len - 11, resp + 9); + PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9); } From 4bd9f183dfec3824485fae7e3a8b7381848207b6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 1 Mar 2020 17:11:25 +0100 Subject: [PATCH 055/298] fix coverity 267206 --- armsrc/hitag2.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 37c716efb..87d6bf221 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -94,7 +94,7 @@ uint8_t nonce[4]; bool key_no; static uint64_t cipher_state; -size_t blocknr; +int16_t blocknr; size_t flipped_bit = 0; uint32_t byte_value = 0; @@ -582,7 +582,7 @@ bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *t Dbhexdump(4, logdata_1, false); bSuccessful = true; return false; - +/* // read next page of card until done tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE tx[1] = blocknr << 4; @@ -590,6 +590,7 @@ bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *t tx[1] |= crc >> 4; tx[2] = crc << 4; *txlen = 20; +*/ } } break; @@ -1288,10 +1289,10 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { uint8_t *tx = txbuf; size_t txlen = 0; - int t_wait_1; + int t_wait_1 = 204; int t_wait_1_guard = 8; - int t_wait_2; - size_t tag_size; + int t_wait_2 = 128; + size_t tag_size = 48; bool bStop = false; // Raw demodulation/decoding by sampling edge periods @@ -1417,9 +1418,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { t_wait_2 = HITAG_T_WAIT_2_MIN; tag_size = 48; DBG DbpString("Configured for hitag2 reader"); - } else { - DBG Dbprintf("Error, unknown hitag reader type: %d", htf); - return; } // init as reader @@ -1665,10 +1663,12 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { uint8_t txbuf[HITAG_FRAME_LEN]; uint8_t *tx = txbuf; size_t txlen = 0; - int t_wait_1; + + int t_wait_1 = 204; int t_wait_1_guard = 8; - int t_wait_2; - size_t tag_size; + int t_wait_2 = 128; + size_t tag_size = 48; + bool bStop = false; // Raw demodulation/decoding by sampling edge periods @@ -1743,9 +1743,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { t_wait_2 = HITAG_T_WAIT_2_MIN; tag_size = 48; DbpString("Configured for hitag2 writer"); - } else { - DBG Dbprintf("Error, unknown hitag writer type: %d", htf); - return; } uint8_t tag_modulation; From da21f94b665573e1832769c30bef240f817e9b2f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 1 Mar 2020 17:15:48 +0100 Subject: [PATCH 056/298] fix coverity 267478 --- client/cmdlfhid.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index c10c5c56c..3a4d16cf3 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -367,7 +367,7 @@ static int CmdHIDClone(const char *Cmd) { static int CmdHIDBrute(const char *Cmd) { bool errors = false, verbose = false; - uint32_t delay = 1000; + uint32_t delay = 1000; uint8_t cmdp = 0; int format_idx = -1; int direction = 0; @@ -375,9 +375,9 @@ static int CmdHIDBrute(const char *Cmd) { wiegand_card_t cn_hi, cn_low; memset(&cn_hi, 0, sizeof(wiegand_card_t)); - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - + char s[10] = {0}; if (param_getstr(Cmd, cmdp, s, sizeof(s)) > 0) { if (strlen(s) > 1) { @@ -448,12 +448,12 @@ static int CmdHIDBrute(const char *Cmd) { PrintAndLogEx(INFO, "OEM#............. %u", cn_hi.OEM); PrintAndLogEx(INFO, "ISSUE#........... %u", cn_hi.IssueLevel); PrintAndLogEx(INFO, "Facility#........ %u", cn_hi.FacilityCode); - PrintAndLogEx(INFO, "Card#............ %u", cn_hi.CardNumber); + PrintAndLogEx(INFO, "Card#............ %" PRIu64, cn_hi.CardNumber); switch( direction) { case 0: PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("BOTH")); break; - case 1: + case 1: PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("UP")); break; case 2: From 95b759a7997aa95edbbb892e067492530255d513 Mon Sep 17 00:00:00 2001 From: bosb <12600404+bosb@users.noreply.github.com> Date: Sun, 1 Mar 2020 22:48:49 +0100 Subject: [PATCH 057/298] removed duplicate code --- armsrc/hitagS.c | 596 +++++++++++++++--------------------------------- 1 file changed, 182 insertions(+), 414 deletions(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 50a96f178..38cb4d478 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -10,6 +10,7 @@ //----------------------------------------------------------------------------- // Some code was copied from Hitag2.c //----------------------------------------------------------------------------- +// bosb 2020 #include "hitagS.h" @@ -23,6 +24,7 @@ #include "string.h" #include "commonutil.h" #include "hitag2_crypto.h" +#include "lfadc.h" #define CRC_PRESET 0xFF #define CRC_POLYNOM 0x1D @@ -50,6 +52,22 @@ size_t blocknr; bool end = false; //#define SENDBIT_TEST +/* array index 3 2 1 0 // bytes in sim.bin file are 0 1 2 3 +// UID is 0 1 2 3 // tag.uid is 3210 +// datasheet HitagS_V11.pdf bytes in tables printed 3 2 1 0 + +#db# UID: 5F C2 11 84 +#db# conf0: C9 conf1: 00 conf2: 00 + 3 2 1 0 +#db# Page[ 0]: 84 11 C2 5F uid +#db# Page[ 1]: AA 00 00 C9 conf +#db# Page[ 2]: 4E 4F 54 48 +#db# Page[ 3]: 52 4B 49 4D +#db# Page[ 4]: 00 00 00 00 +#db# Page[ 5]: 00 00 00 00 +#db# Page[ 6]: 00 00 00 00 +#db# Page[ 7]: 4B 4F 5F 57 */ + #define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b)) #define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b))) #define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c)))) @@ -207,19 +225,17 @@ static void hitag_send_bit(int bit) { } static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { - // The beginning of the frame is hidden in some high level; pause until our bits come out + // The beginning of the frame is hidden in some high level; pause until our bits will have an effect AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; HIGH(GPIO_SSC_DOUT); switch (m) { case AC4K: + case MC8K: while (AT91C_BASE_TC0->TC_CV < T0 * 40) {}; //FADV break; case AC2K: - while (AT91C_BASE_TC0->TC_CV < T0 * 20) {}; //STD + ADV - break; case MC4K: - break; - case MC8K: + while (AT91C_BASE_TC0->TC_CV < T0 * 20) {}; //STD + ADV break; } @@ -315,6 +331,25 @@ static int check_select(uint8_t *rx, uint32_t uid) { return 0; } +void hitagS_set_frame_modulation() { + switch (tag.mode) { + case HT_STANDARD: + sof_bits = 1; + m = MC4K; + break; + case HT_ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case HT_FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } +} + /* * handles all commands from a reader */ @@ -368,27 +403,14 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, break; case 45: { //select command from reader received - DbpString("...select"); + if (DBGLEVEL >= DBG_EXTENDED) + DbpString("...select"); if (check_select(rx, tag.uid) == 1) { - DbpString("...select match"); + if (DBGLEVEL >= DBG_EXTENDED) + DbpString("...select match"); //if the right tag was selected *txlen = 32; - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + hitagS_set_frame_modulation(); //send configuration for (int i = 0; i < 4; i++) @@ -416,22 +438,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, Dbprintf(",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + hitagS_set_frame_modulation(); for (int i = 0; i < 4; i++) _hitag2_byte(&state); @@ -465,7 +472,8 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, */ } case 40: - Dbprintf("....write"); + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("....write"); //data received to be written if (tag.tstate == HT_WRITING_PAGE_DATA) { tag.tstate = HT_NO_OP; @@ -475,44 +483,14 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, *txlen = 2; tx[0] = 0x40; page_to_be_written = 0; - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + hitagS_set_frame_modulation(); } else if (tag.tstate == HT_WRITING_BLOCK_DATA) { tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0] << 24) + (rx[1] << 16) + (rx[2] << 8) + rx[3]; //send ack *txlen = 2; tx[0] = 0x40; - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + hitagS_set_frame_modulation(); page_to_be_written++; block_data_left--; if (block_data_left == 0) { @@ -522,35 +500,23 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } break; case 20: { - Dbprintf("....read"); + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("....read"); //write page, write block, read page or read block command received if ((rx[0] & 0xf0) == 0xc0) { //read page //send page data uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("....page %i", page); *txlen = 32; - tx[0] = (tag.pages[page / 4][page % 4]) & 0xff; - tx[1] = (tag.pages[page / 4][page % 4] >> 8) & 0xff; - tx[2] = (tag.pages[page / 4][page % 4] >> 16) & 0xff; - tx[3] = (tag.pages[page / 4][page % 4] >> 24) & 0xff; + tx[0] = tag.pages[page][0]; + tx[1] = tag.pages[page][1]; + tx[2] = tag.pages[page][2]; + tx[3] = tag.pages[page][3]; if (tag.LKP && page == 1) tx[3] = 0xff; - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + hitagS_set_frame_modulation(); if (tag.mode != HT_STANDARD) { //add crc8 @@ -568,32 +534,18 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } } else if ((rx[0] & 0xf0) == 0xd0) { //read block uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("....block %i", page); *txlen = 32 * 4; //send page,...,page+3 data for (int i = 0; i < 4; i++) { - tx[0 + i * 4] = (tag.pages[page / 4][page % 4]) & 0xff; - tx[1 + i * 4] = (tag.pages[page / 4][page % 4] >> 8) & 0xff; - tx[2 + i * 4] = (tag.pages[page / 4][page % 4] >> 16) & 0xff; - tx[3 + i * 4] = (tag.pages[page / 4][page % 4] >> 24) & 0xff; - page++; + tx[0 + i * 4] = tag.pages[page + 0 + i * 4][0]; + tx[1 + i * 4] = tag.pages[page + 1 + i * 4][1]; + tx[2 + i * 4] = tag.pages[page + 2 + i * 4][2]; + tx[3 + i * 4] = tag.pages[page + 3 + i * 4][3]; } - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + hitagS_set_frame_modulation(); if (tag.mode != HT_STANDARD) { //add crc8 @@ -604,29 +556,16 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, tx[16] = crc; } - if ((page - 4) % 4 != 0 || (tag.LKP && (page - 4) == 0)) { + if ((page) % 4 != 0 || (tag.LKP && (page) == 0)) { sof_bits = 0; *txlen = 0; } } else if ((rx[0] & 0xf0) == 0x80) { //write page uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("....write page: %i", page); - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + hitagS_set_frame_modulation(); if ((tag.LCON && page == 1) || (tag.LKP && (page == 2 || page == 3))) { //deny @@ -641,22 +580,9 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } else if ((rx[0] & 0xf0) == 0x90) { //write block uint8_t page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16); - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("....write block: %i", page); + hitagS_set_frame_modulation(); if (page % 4 != 0 || page == 0) { //deny *txlen = 0; @@ -672,11 +598,8 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } break; default: - if (DBGLEVEL >= DBG_EXTENDED) { - Dbprintf("rxlen: %i", rxlen); - for (int i = 0; i < 4; i++) - Dbprintf("%i: %02X",i,rx[i]); - } + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("unknown rxlen: (%i) %02X %02X %02X %02X", rxlen, rx[0], rx[1], rx[2], rx[3]); break; } } @@ -962,14 +885,16 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { tag.pstate = HT_READY; tag.tstate = HT_NO_OP; - for (i = 0; i < 16; i++) - for (j = 0; j < 4; j++) - tag.pages[i][j] = 0x0; - // read tag data into memory if (tag_mem_supplied) { + for (i = 0; i < 16; i++) + for (j = 0; j < 4; j++) + tag.pages[i][j] = 0x0; + DbpString("Loading hitagS memory..."); memcpy((uint8_t *)tag.pages, data, 4 * 64); + } else { + // use the last read tag } tag.uid = (tag.pages[0][3] << 24 | tag.pages[0][2] << 16 | tag.pages[0][1] << 8 | tag.pages[0][0]); @@ -981,9 +906,9 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { tag.pwdh0 = tag.pages[1][3]; //con0 tag.max_page = 64; - if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 1) + if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 1) tag.max_page = 8; - if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 0) + if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 0) tag.max_page = 0; if (DBGLEVEL >= DBG_EXTENDED) for (i = 0; i < tag.max_page; i++) @@ -994,41 +919,42 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { tag.pages[i][0] & 0xff); //con1 tag.auth = 0; - if ((tag.pages[1][2] & 0x80) == 0x80) + if ((tag.pages[1][1] & 0x80) == 0x80) tag.auth = 1; tag.LCON = 0; - if ((tag.pages[1][2] & 0x2) == 0x02) + if ((tag.pages[1][1] & 0x2) == 0x02) tag.LCON = 1; tag.LKP = 0; - if ((tag.pages[1][2] & 0x1) == 0x01) + if ((tag.pages[1][1] & 0x1) == 0x01) tag.LKP = 1; //con2 //0=read write 1=read only tag.LCK7 = 0; - if ((tag.pages[1][1] & 0x80) == 0x80) + if ((tag.pages[1][2] & 0x80) == 0x80) tag.LCK7 = 1; tag.LCK6 = 0; - if ((tag.pages[1][1] & 0x40) == 0x040) + if ((tag.pages[1][2] & 0x40) == 0x040) tag.LCK6 = 1; tag.LCK5 = 0; - if ((tag.pages[1][1] & 0x20) == 0x20) + if ((tag.pages[1][2] & 0x20) == 0x20) tag.LCK5 = 1; tag.LCK4 = 0; - if ((tag.pages[1][1] & 0x10) == 0x10) + if ((tag.pages[1][2] & 0x10) == 0x10) tag.LCK4 = 1; tag.LCK3 = 0; - if ((tag.pages[1][1] & 0x8) == 0x08) + if ((tag.pages[1][2] & 0x8) == 0x08) tag.LCK3 = 1; tag.LCK2 = 0; - if ((tag.pages[1][1] & 0x4) == 0x04) + if ((tag.pages[1][2] & 0x4) == 0x04) tag.LCK2 = 1; tag.LCK1 = 0; - if ((tag.pages[1][1] & 0x2) == 0x02) + if ((tag.pages[1][2] & 0x2) == 0x02) tag.LCK1 = 1; tag.LCK0 = 0; - if ((tag.pages[1][1] & 0x1) == 0x01) + if ((tag.pages[1][2] & 0x1) == 0x01) tag.LCK0 = 1; + // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaDownloadAndGo(FPGA_BITSTREAM_LF); @@ -1060,7 +986,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; + | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; // Enable and reset counter AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; @@ -1132,12 +1058,13 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { LogTrace(tx, nbytes(txlen), 0, 0, NULL, false); } + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Reset the received frame and response timing info memset(rx, 0x00, sizeof(rx)); response = 0; - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; LED_B_OFF(); } // Reset the frame length @@ -1149,20 +1076,89 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { } - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); set_tracing(false); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - + lf_finalize(); // release allocated memory from BigBuff. BigBuf_free(); - StartTicks(); - DbpString("Sim Stopped"); } +void hitagS_receive_frame(uint8_t *rx, size_t *rxlen, int *response) { + + // Reset values for receiving frames + memset(rx, 0x00, HITAG_FRAME_LEN * sizeof(uint8_t)); + *rxlen = 0; + int lastbit = 1; + bool bSkip = true; + int tag_sof = 1; + *response = 0; + uint32_t errorCount = 0; + + // Receive frame, watch for at most T0*EOF periods + while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { + // Check if falling edge in tag modulation is detected + if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA / T0); + + // Reset timer every frame, we have to capture the last edge for timing + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + + LED_B_ON(); + + // Capture tag frame (manchester decoding using only falling edges) + if (ra >= HITAG_T_EOF) { + if (*rxlen != 0) { + //DbpString("wierd1?"); + } + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always recieve a 'one' first, which has the falling edge after a half period |-_| + *response = ra - HITAG_T_TAG_HALF_PERIOD; + } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { + // Manchester coding example |-_|_-|-_| (101) + rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8)); + (*rxlen)++; + rx[(*rxlen) / 8] |= 1 << (7 - ((*rxlen) % 8)); + (*rxlen)++; + } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { + // Manchester coding example |_-|...|_-|-_| (0...01) + rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8)); + (*rxlen)++; + // We have to skip this half period at start and add the 'one' the second time + if (!bSkip) { + rx[(*rxlen) / 8] |= 1 << (7 - ((*rxlen) % 8)); + (*rxlen)++; + } + lastbit = !lastbit; + bSkip = !bSkip; + } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { + // Manchester coding example |_-|_-| (00) or |-_|-_| (11) + if (tag_sof) { + // Ignore bits that are transmitted during SOF + tag_sof--; + } else { + // bit is same as last bit + rx[(*rxlen) / 8] |= lastbit << (7 - ((*rxlen) % 8)); + (*rxlen)++; + } + } else { + // Ignore wierd value, is to small to mean anything + errorCount++; + } + } + + // if we saw over 100 wierd values break it probably isn't hitag... + if (errorCount > 100) break; + + // We can break this loop if we received the last bit from a frame + if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { + if ((*rxlen) > 0) + break; + } + } +} + /* * Authenticates to the Tag with the given key or challenge. * If the key was given the password will be decrypted. @@ -1182,7 +1178,6 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { uint8_t *tx = txbuf; size_t txlen = 0; int lastbit = 1; - int reset_sof = 1; int t_wait = HITAG_T_WAIT_MAX; bool bStop = false; int pageNum = 0; @@ -1271,10 +1266,8 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { // synchronized startup procedure while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero - // Reset the received frame, frame count and timing info t_wait = 200; - while (!bStop && !BUTTON_PRESS() && !data_available()) { WDT_HIT(); @@ -1414,85 +1407,12 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true); } - // Reset values for receiving frames - memset(rx, 0x00, sizeof(rx)); - rxlen = 0; - lastbit = 1; - bool bSkip = true; - int tag_sof = reset_sof; - response = 0; - - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { - // Check if falling edge in tag modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / T0); - - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - - LED_B_ON(); - - // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - if (rxlen != 0) { - //DbpString("wierd1?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always recieve a 'one' first, which has the falling edge after a half period |-_| - response = ra - HITAG_T_TAG_HALF_PERIOD; - } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { - // Manchester coding example |-_|_-|-_| (101) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { - // Manchester coding example |_-|...|_-|-_| (0...01) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - // We have to skip this half period at start and add the 'one' the second time - if (!bSkip) { - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } - lastbit = !lastbit; - bSkip = !bSkip; - } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { - // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); - rxlen++; - } - } else { - // Ignore wierd value, is to small to mean anything - } - } - - // We can break this loop if we received the last bit from a frame - if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { - if (rxlen > 0) - break; - } - } + hitagS_receive_frame(rx, &rxlen, &response); } end = false; - - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); set_tracing(false); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - - StartTicks(); - + lf_finalize(); reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0); } @@ -1512,7 +1432,6 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) { uint8_t *tx = txbuf; size_t txlen = 0; int lastbit; - int reset_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop; unsigned char crc; @@ -1604,7 +1523,6 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) { // Reset the received frame, frame count and timing info lastbit = 1; bStop = false; - reset_sof = 1; t_wait = 200; while (!bStop && !BUTTON_PRESS() && !data_available()) { @@ -1704,87 +1622,13 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) { LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true); } - // Reset values for receiving frames - memset(rx, 0x00, sizeof(rx)); - rxlen = 0; - lastbit = 1; - bool bSkip = true; - int tag_sof = reset_sof; - response = 0; - uint32_t errorCount = 0; + hitagS_receive_frame(rx, &rxlen, &response); - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { - // Check if falling edge in tag modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / T0); - - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - - LED_B_ON(); - - // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - if (rxlen != 0) { - //DbpString("wierd1?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always recieve a 'one' first, which has the falling edge after a half period |-_| - response = ra - HITAG_T_TAG_HALF_PERIOD; - } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { - // Manchester coding example |-_|_-|-_| (101) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { - // Manchester coding example |_-|...|_-|-_| (0...01) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - // We have to skip this half period at start and add the 'one' the second time - if (!bSkip) { - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } - lastbit = !lastbit; - bSkip = !bSkip; - } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { - // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); - rxlen++; - } - } else { - // Ignore wierd value, is to small to mean anything - errorCount++; - } - } - - // if we saw over 100 wierd values break it probably isn't hitag... - if (errorCount > 100) break; - - // We can break this loop if we received the last bit from a frame - if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { - if (rxlen > 0) - break; - } - } } end = false; - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); set_tracing(false); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - - StartTicks(); + lf_finalize(); reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0); } @@ -1807,7 +1651,7 @@ void check_challenges(bool file_given, uint8_t *data) { size_t rxlen = 0; uint8_t txbuf[HITAG_FRAME_LEN]; int t_wait = HITAG_T_WAIT_MAX; - int lastbit, reset_sof, STATE = 0;; + int lastbit, STATE = 0;; bool bStop; int response_bit[200]; unsigned char mask = 1; @@ -1868,7 +1712,6 @@ void check_challenges(bool file_given, uint8_t *data) { // Reset the received frame, frame count and timing info lastbit = 1; bStop = false; - reset_sof = 1; t_wait = 200; if (file_given) { @@ -2018,85 +1861,10 @@ void check_challenges(bool file_given, uint8_t *data) { LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true); } - // Reset values for receiving frames - memset(rx, 0x00, sizeof(rx)); - rxlen = 0; - lastbit = 1; - bool bSkip = true; - int tag_sof = reset_sof; - response = 0; - - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { - // Check if falling edge in tag modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / T0); - - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - - LED_B_ON(); - - // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - if (rxlen != 0) { - //DbpString("wierd1?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always recieve a 'one' first, which has the falling edge after a half period |-_| - response = ra - HITAG_T_TAG_HALF_PERIOD; - } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { - // Manchester coding example |-_|_-|-_| (101) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { - // Manchester coding example |_-|...|_-|-_| (0...01) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - // We have to skip this half period at start and add the 'one' the second time - if (!bSkip) { - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } - lastbit = !lastbit; - bSkip = !bSkip; - } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { - // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); - rxlen++; - } - } else { - // Ignore wierd value, is to small to mean anything - } - } - - // We can break this loop if we received the last bit from a frame - if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { - if (rxlen > 0) - break; - } - } + hitagS_receive_frame(rx, &rxlen, &response); } - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); set_tracing(false); - - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - - StartTicks(); - + lf_finalize(); reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0); } - - - From 9205b2d3906bcbb644a5e1364252f15218f1cf71 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 2 Mar 2020 11:12:13 +0100 Subject: [PATCH 058/298] text --- client/cmdscript.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/client/cmdscript.c b/client/cmdscript.c index 322fd6adb..4f4a372d8 100644 --- a/client/cmdscript.c +++ b/client/cmdscript.c @@ -59,11 +59,13 @@ static int CmdScriptRun(const char *Cmd) { if ((!str_endswith(preferredName, ".cmd")) && (searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", true) == PM3_SUCCESS)) { int error; if (luascriptfile_idx == MAX_NESTED_LUASCRIPT) { - PrintAndLogEx(ERR, "Too many nested scripts, skipping %s\n", script_path); + PrintAndLogEx(ERR, "too many nested scripts, skipping %s\n", script_path); free(script_path); return PM3_EMALLOC; } - PrintAndLogEx(SUCCESS, "Executing Lua script: %s, args '%s'\n", script_path, arguments); + PrintAndLogEx(SUCCESS, "executing lua " _YELLOW_("%s"), script_path); + PrintAndLogEx(SUCCESS, "args " _YELLOW_("'%s'"), arguments); + luascriptfile_idx++; // create new Lua state @@ -94,7 +96,7 @@ static int CmdScriptRun(const char *Cmd) { if (error) { // if non-0, then an error // the top of the stack should be the error string if (!lua_isstring(lua_state, lua_gettop(lua_state))) - PrintAndLogEx(FAILED, "Error - but no error (?!)"); + PrintAndLogEx(FAILED, "error - but no error (?!)"); // get the top of the stack as the error and pop it off const char *str = lua_tostring(lua_state, lua_gettop(lua_state)); @@ -106,17 +108,22 @@ static int CmdScriptRun(const char *Cmd) { // close the Lua state lua_close(lua_state); luascriptfile_idx--; - PrintAndLogEx(SUCCESS, "\nFinished %s\n", preferredName); + PrintAndLogEx(SUCCESS, "\nfinished " _YELLOW_("%s"), preferredName); return PM3_SUCCESS; } + if ((!str_endswith(preferredName, ".lua")) && (searchFile(&script_path, CMD_SCRIPTS_SUBDIR, preferredName, ".cmd", true) == PM3_SUCCESS)) { - PrintAndLogEx(SUCCESS, "Executing Cmd script: %s, args '%s'\n", script_path, arguments); + + PrintAndLogEx(SUCCESS, "executing Cmd " _YELLOW_("%s"), script_path); + PrintAndLogEx(SUCCESS, "args " _YELLOW_("'%s'"), arguments); + int ret = push_cmdscriptfile(script_path, true); if (ret != PM3_SUCCESS) PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", script_path); free(script_path); return ret; } + // file not found, let's search again to display the error messages int ret = PM3_EUNDEF; if (!str_endswith(preferredName, ".cmd")) ret = searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", false); @@ -141,7 +148,7 @@ static command_t CommandTable[] = { static int CmdHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far PrintAndLogEx(NORMAL, "This is a feature to run Lua-scripts. You can place Lua-scripts within the luascripts/-folder. "); - return 0; + return PM3_SUCCESS; } /** From 783d97bd09386057421e86948b3a2068735e3979 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 2 Mar 2020 13:59:41 +0100 Subject: [PATCH 059/298] Chg: added hint texts to lf clone commands --- client/cmdlf.c | 2 +- client/cmdlfawid.c | 5 ++++- client/cmdlfem4x.c | 12 +++++++++--- client/cmdlffdx.c | 5 ++++- client/cmdlfgallagher.c | 5 ++++- client/cmdlfhid.c | 3 ++- client/cmdlfindala.c | 5 ++++- client/cmdlfio.c | 5 ++++- client/cmdlfkeri.c | 5 ++++- client/cmdlfmotorola.c | 5 ++++- client/cmdlfnedap.c | 2 ++ client/cmdlfnexwatch.c | 6 ++++-- client/cmdlft55xx.c | 1 - 13 files changed, 46 insertions(+), 15 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index b83ed0c89..f153ba1c3 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -1339,10 +1339,10 @@ static command_t CommandTable[] = { {"io", CmdLFIO, AlwaysAvailable, "{ ioProx RFIDs... }"}, {"jablotron", CmdLFJablotron, AlwaysAvailable, "{ Jablotron RFIDs... }"}, {"keri", CmdLFKeri, AlwaysAvailable, "{ KERI RFIDs... }"}, + {"motorola", CmdLFMotorola, AlwaysAvailable, "{ Motorola RFIDs... }"}, {"nedap", CmdLFNedap, AlwaysAvailable, "{ Nedap RFIDs... }"}, {"nexwatch", CmdLFNEXWATCH, AlwaysAvailable, "{ NexWatch RFIDs... }"}, {"noralsy", CmdLFNoralsy, AlwaysAvailable, "{ Noralsy RFIDs... }"}, - {"motorola", CmdLFMotorola, AlwaysAvailable, "{ Motorola RFIDs... }"}, {"pac", CmdLFPac, AlwaysAvailable, "{ PAC/Stanley RFIDs... }"}, {"paradox", CmdLFParadox, AlwaysAvailable, "{ Paradox RFIDs... }"}, {"pcf7931", CmdLFPCF7931, AlwaysAvailable, "{ PCF7931 CHIPs... }"}, diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 38c3675d1..9bcf9e874 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -422,7 +422,10 @@ static int CmdAWIDClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone AWID %u to T55x7 with FC: %u, CN: %u", fmtlen, fc, cn); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf awid read`") "to verify"); + return res; } static int CmdAWIDBrute(const char *Cmd) { diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index a8d7e06e3..9b7fe51de 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -700,6 +700,8 @@ static int CmdEM410xWrite(const char *Cmd) { } SendCommandMIX(CMD_LF_EM410X_WRITE, card, (uint32_t)(id >> 32), (uint32_t)id, NULL, 0); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 410x_read`") "to verify"); return PM3_SUCCESS; } @@ -1037,6 +1039,9 @@ static int CmdEM4x50Write(const char *Cmd) { uint8_t ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 'h') return usage_lf_em4x50_write(); PrintAndLogEx(NORMAL, "no implemented yet"); +// +// PrintAndLogEx(SUCCESS, "Done"); +// PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x50_read`") "to verify"); return PM3_SUCCESS; } @@ -1434,9 +1439,10 @@ static int CmdEM4x05Write(const char *Cmd) { uint32_t dummy = 0; int status = demodEM4x05resp(&dummy); if (status == PM3_SUCCESS) - PrintAndLogEx(NORMAL, "Write " _GREEN_("Verified")); - else - PrintAndLogEx(NORMAL, "Write could " _RED_("not") "be verified"); + PrintAndLogEx(SUCCESS, "Success writing to tag"); + + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x05_read`") "to verify"); return status; } static int CmdEM4x05Wipe(const char *Cmd) { diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 2f3f81d1d..11ec2dd64 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -301,7 +301,10 @@ static int CmdFdxClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone FDX-B to T55x7 with animal ID: %04u-%"PRIu64, countryid, animalid); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf fdx read`") "to verify"); + return res; } static int CmdFdxSim(const char *Cmd) { diff --git a/client/cmdlfgallagher.c b/client/cmdlfgallagher.c index ef28f1326..e44682e2b 100644 --- a/client/cmdlfgallagher.c +++ b/client/cmdlfgallagher.c @@ -178,7 +178,10 @@ static int CmdGallagherClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Gallagher to T55x7 with raw hex"); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf gallagher read`") "to verify"); + return res; } static int CmdGallagherSim(const char *Cmd) { diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 3a4d16cf3..dbe027dc3 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -345,7 +345,8 @@ static int CmdHIDClone(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_LF_HID_CLONE, hi2, hi, lo, longid, sizeof(longid)); - PrintAndLogEx(INFO, "Clone command sent. Try "_YELLOW_("'lf hid read'") " to verify"); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf hid read`") "to verify"); return PM3_SUCCESS; } diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 9aa98524c..01eb4b8f8 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -620,7 +620,10 @@ static int CmdIndalaClone(const char *Cmd) { } print_blocks(blocks, max); - return clone_t55xx_tag(blocks, max); + int res = clone_t55xx_tag(blocks, max); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf indala read`") "to verify"); + return res; } static command_t CommandTable[] = { diff --git a/client/cmdlfio.c b/client/cmdlfio.c index 1a25fca17..994c69a7d 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -275,7 +275,10 @@ static int CmdIOProxClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone IOProx to T55x7 with Version: %u FC: %u, CN: %u", version, fc, cn); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf io read`") "to verify"); + return res; } static command_t CommandTable[] = { diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 4a0c3c8fd..3c7863361 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -280,7 +280,10 @@ static int CmdKeriClone(const char *Cmd) { print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf keri read`") "to verify"); + return res; } static int CmdKeriSim(const char *Cmd) { diff --git a/client/cmdlfmotorola.c b/client/cmdlfmotorola.c index 9f0ee1f41..c34b48d8e 100644 --- a/client/cmdlfmotorola.c +++ b/client/cmdlfmotorola.c @@ -177,7 +177,10 @@ static int CmdMotorolaClone(const char *Cmd) { blocks[2] = bytes_to_num(data + 4, 4); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf motorola read`") "to verify"); + return res; } static int CmdMotorolaSim(const char *Cmd) { diff --git a/client/cmdlfnedap.c b/client/cmdlfnedap.c index c3d6d1ace..a1d23cd91 100644 --- a/client/cmdlfnedap.c +++ b/client/cmdlfnedap.c @@ -475,6 +475,8 @@ static int CmdLFNedapClone(const char *Cmd) { } else { PrintAndLogEx(NORMAL, ""); } + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf nedap read`") "to verify"); return res; } diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index 68be0e0bc..d288eeadc 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -158,8 +158,10 @@ static int CmdNexWatchClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone NexWatch to T55x7 with raw hex"); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); - + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf nexwatch read`") "to verify"); + return res; } static int CmdNexWatchSim(const char *Cmd) { diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index f25626d94..c88b8a051 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1028,7 +1028,6 @@ void T55xx_Print_DownlinkMode(uint8_t downlink_mode) { PrintAndLogEx(NORMAL, msg); } - static int CmdT55xxDetect(const char *Cmd) { bool errors = false; From 61e6ff6991169fd072b31a82a7372d6902db4040 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 2 Mar 2020 14:15:51 +0100 Subject: [PATCH 060/298] chg: added hint text for lf clone part2 --- client/cmdlfnoralsy.c | 5 ++++- client/cmdlfpac.c | 5 ++++- client/cmdlfparadox.c | 5 ++++- client/cmdlfpcf7931.c | 47 ++++++++++++++++++++++------------------- client/cmdlfpresco.c | 5 ++++- client/cmdlfpyramid.c | 5 ++++- client/cmdlfsecurakey.c | 5 ++++- client/cmdlfti.c | 2 ++ client/cmdlfverichip.c | 5 ++++- client/cmdlfviking.c | 2 ++ client/cmdlfvisa2000.c | 5 ++++- 11 files changed, 61 insertions(+), 30 deletions(-) diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index d7728a3d9..bbb7de0c9 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -169,7 +169,10 @@ static int CmdNoralsyClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Noralsy to T55x7 with CardId: %u", id); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf noralsy read`") "to verify"); + return res; } static int CmdNoralsySim(const char *Cmd) { diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index 24c549a4b..9ac9aa511 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -239,7 +239,10 @@ static int CmdPacClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone PAC/Stanley tag to T55x7 with raw hex"); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf pac read`") "to verify"); + return res; } static int CmdPacSim(const char *Cmd) { diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index 29e247b59..12c1bc9b8 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -169,7 +169,10 @@ static int CmdParadoxClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Paradox to T55x7 with raw hex"); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf paradox read`") "to verify"); + return res; } static int CmdParadoxSim(const char *Cmd) { diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c index e4a14a47e..ddcad195d 100644 --- a/client/cmdlfpcf7931.c +++ b/client/cmdlfpcf7931.c @@ -11,6 +11,7 @@ #include "cmdlfpcf7931.h" #include +#include #include "cmdparser.h" // command_t #include "comms.h" @@ -36,7 +37,7 @@ int pcf7931_resetConfig() { configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY; configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH; configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION; - return 0; + return PM3_SUCCESS; } int pcf7931_printConfig() { @@ -44,7 +45,7 @@ int pcf7931_printConfig() { PrintAndLogEx(NORMAL, "Tag initialization delay : %d us", configPcf.InitDelay); PrintAndLogEx(NORMAL, "Offset low pulses width : %d us", configPcf.OffsetWidth); PrintAndLogEx(NORMAL, "Offset low pulses position : %d us", configPcf.OffsetPosition); - return 0; + return PM3_SUCCESS; } static int usage_pcf7931_read() { @@ -54,7 +55,7 @@ static int usage_pcf7931_read() { PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf pcf7931 read"); - return 0; + return PM3_SUCCESS; } static int usage_pcf7931_write() { @@ -67,7 +68,7 @@ static int usage_pcf7931_write() { PrintAndLogEx(NORMAL, " data one byte of data (hex)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf pcf7931 write 2 1 FF"); - return 0; + return PM3_SUCCESS; } static int usage_pcf7931_config() { @@ -87,30 +88,30 @@ static int usage_pcf7931_config() { PrintAndLogEx(NORMAL, " lf pcf7931 config r"); PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 20000"); PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 17500 -10 30"); - return 0; + return PM3_SUCCESS; } static int CmdLFPCF7931Read(const char *Cmd) { - uint8_t ctmp = param_getchar(Cmd, 0); - if (ctmp == 'H' || ctmp == 'h') return usage_pcf7931_read(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if (ctmp == 'h') return usage_pcf7931_read(); PacketResponseNG resp; clearCommandBuffer(); SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { PrintAndLogEx(WARNING, "command execution time out"); - return 1; + return PM3_ETIMEOUT; } - return 0; + return PM3_SUCCESS; } static int CmdLFPCF7931Config(const char *Cmd) { - uint8_t ctmp = param_getchar(Cmd, 0); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 0) return pcf7931_printConfig(); - if (ctmp == 'H' || ctmp == 'h') return usage_pcf7931_config(); - if (ctmp == 'R' || ctmp == 'r') return pcf7931_resetConfig(); + if (ctmp == 'h') return usage_pcf7931_config(); + if (ctmp == 'r') return pcf7931_resetConfig(); if (param_gethex(Cmd, 0, configPcf.Pwd, 14)) return usage_pcf7931_config(); @@ -119,13 +120,13 @@ static int CmdLFPCF7931Config(const char *Cmd) { configPcf.OffsetPosition = (int)(param_get32ex(Cmd, 3, 0, 10) & 0xFFFF); pcf7931_printConfig(); - return 0; + return PM3_SUCCESS; } static int CmdLFPCF7931Write(const char *Cmd) { - uint8_t ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_pcf7931_write(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_pcf7931_write(); uint8_t block = 0, bytepos = 0, data = 0; @@ -136,9 +137,9 @@ static int CmdLFPCF7931Write(const char *Cmd) { data = param_get8ex(Cmd, 2, 0, 16); - PrintAndLogEx(NORMAL, "Writing block: %d", block); - PrintAndLogEx(NORMAL, " pos: %d", bytepos); - PrintAndLogEx(NORMAL, " data: 0x%02X", data); + PrintAndLogEx(INFO, "Writing block: %d", block); + PrintAndLogEx(INFO, " pos: %d", bytepos); + PrintAndLogEx(INFO, " data: 0x%02X", data); uint32_t buf[10]; // TODO sparse struct, 7 *bytes* then words at offset 4*7! memcpy(buf, configPcf.Pwd, sizeof(configPcf.Pwd)); @@ -147,9 +148,11 @@ static int CmdLFPCF7931Write(const char *Cmd) { buf[9] = configPcf.InitDelay; clearCommandBuffer(); - SendCommandOLD(CMD_LF_PCF7931_WRITE, block, bytepos, data, buf, sizeof(buf)); - //no ack? - return 0; + SendCommandMIX(CMD_LF_PCF7931_WRITE, block, bytepos, data, buf, sizeof(buf)); + + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf pcf7931 read`") "to verify"); + return PM3_SUCCESS; } static command_t CommandTable[] = { @@ -163,7 +166,7 @@ static command_t CommandTable[] = { static int CmdHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandTable); - return 0; + return PM3_SUCCESS; } int CmdLFPCF7931(const char *Cmd) { diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index a0619d794..9f00dbdce 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -136,7 +136,10 @@ static int CmdPrescoClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf presco read`") "to verify"); + return res; } // takes base 12 ID converts to hex diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index 5737c87b9..14357201a 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -250,7 +250,10 @@ static int CmdPyramidClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf pyramid read`") "to verify"); + return res; } static int CmdPyramidSim(const char *Cmd) { diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c index ef4b5be8e..0061d56c4 100644 --- a/client/cmdlfsecurakey.c +++ b/client/cmdlfsecurakey.c @@ -168,7 +168,10 @@ static int CmdSecurakeyClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Securakey to T55x7 with raw hex"); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf securakey read`") "to verify"); + return res; } static int CmdSecurakeySim(const char *Cmd) { diff --git a/client/cmdlfti.c b/client/cmdlfti.c index cf01abb73..8507fa36a 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -296,6 +296,8 @@ static int CmdTIWrite(const char *Cmd) { } clearCommandBuffer(); SendCommandMIX(CMD_LF_TI_WRITE, arg0, arg1, arg2, NULL, 0); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf ti read`") "to verify"); return PM3_SUCCESS; } diff --git a/client/cmdlfverichip.c b/client/cmdlfverichip.c index fb2e4e777..91b49b8f4 100644 --- a/client/cmdlfverichip.c +++ b/client/cmdlfverichip.c @@ -121,7 +121,10 @@ static int CmdVerichipClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Verichip to T55x7 with raw hex"); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf verichip read`") "to verify"); + return res; } static int CmdVerichipSim(const char *Cmd) { diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 69d8aee65..407c28f7e 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -117,6 +117,8 @@ static int CmdVikingClone(const char *Cmd) { PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); return PM3_ETIMEOUT; } + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf viking read`") "to verify"); return resp.status; } diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 551a1efbb..1a628e51d 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -184,7 +184,10 @@ static int CmdVisa2kClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Visa2000 to T55x7 with CardId: %"PRIu64, id); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf visa2000 read`") "to verify"); + return res; } static int CmdVisa2kSim(const char *Cmd) { From ce88d8b3ae45ff9d1706ae3c3478214762a01e14 Mon Sep 17 00:00:00 2001 From: Joan Bono Date: Mon, 2 Mar 2020 16:02:48 +0100 Subject: [PATCH 061/298] Update cmdlfparadox.c --- client/cmdlfparadox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index 12c1bc9b8..c540290f8 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -36,7 +36,7 @@ static int usage_lf_paradox_clone(void) { PrintAndLogEx(NORMAL, " b : raw hex data. 12 bytes max"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf paradox clone 0f55555695596a6a9999a59a"); + PrintAndLogEx(NORMAL, " lf paradox clone b 0f55555695596a6a9999a59a"); return PM3_SUCCESS; } From 48971fdd5b276959cbb746e8f6c121d5d09aebda Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 2 Mar 2020 16:46:20 +0100 Subject: [PATCH 062/298] text --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8015a76f5..8896f223c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] - - Chnage `lf keri demod` - adjusted the internal id. (@mwalker33) + - Change - hint texts added to all lf clone commands (@iceman1001) + - Change `lf keri demod` - adjusted the internal id. (@mwalker33) - Added seamless integration with cryptohelper (@iceman1001) - Change `lf hid brute` - new params for direction (UP/DOWN); textual and main loop actually exit. (@capnkrunchy and @iceman1001) - Fix `lf hid brute` - made it work again (@capnkrunchy) From 1794acc65892c5ea33559452a4e65e56b0525ab3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 2 Mar 2020 16:47:55 +0100 Subject: [PATCH 063/298] #586 - ignore html files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 349ef5efb..1b352bcfe 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ .profile *.log *.eml +*.html *.o *.a *.d From 201f4acb8fb935a910d274e7388abc5a2526982f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 5 Mar 2020 09:24:11 +0530 Subject: [PATCH 064/298] highlight first doc to read --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 96a8d2693..e48802b81 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,10 @@ | FAQ's & Updates | Installation | Use of the Proxmark | | ------------------- |:-------------------:| -------------------:| -|[What has changed?](#what-has-changed) | [Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)| -|[Development](#development) | [Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) | -|[Why didn't you base it on official Proxmark3 Master?](#why-didnt-you-base-it-on-official-proxmark3-master)| [Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)| -|[Proxmark3 GUI](#proxmark3-gui)|[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)| +|[What has changed?](#what-has-changed) | **[Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md)** | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)| +|[Development](#development) | **[Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md)** | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) | +|[Why didn't you base it on official Proxmark3 Master?](#why-didnt-you-base-it-on-official-proxmark3-master)| **[Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md)** | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)| +|[Proxmark3 GUI](#proxmark3-gui)|**[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)**|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)| |[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) |[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)| |[Notes on UART](/doc/uart_notes.md)|[Maintainers](/doc/md/Development/Maintainers.md)|[Command Cheat sheet](/doc/cheatsheet.md)| |[Notes on frame format](/doc/new_frame_format.md)||[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)| From b6dcfbf078bb8595f0c03e079b058b2410381025 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 5 Mar 2020 11:16:05 +0100 Subject: [PATCH 065/298] =?UTF-8?q?chg:=20allow=20to=20download=20=C2=B4lf?= =?UTF-8?q?=20config=C2=B4=20settings=20to=20client?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- armsrc/appmain.c | 9 ++++++++- armsrc/lfsampling.c | 2 +- client/cmdlf.c | 21 ++++++++++++++++++++- client/cmdlf.h | 1 + include/pm3_cmd.h | 3 ++- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 415e03291..88c85ad57 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -721,10 +721,17 @@ static void PacketReceived(PacketCommandNG *packet) { setT55xxConfig(packet->oldarg[0], (t55xx_configurations_t *) packet->data.asBytes); break; } - case CMD_LF_SAMPLING_GET_CONFIG: { + case CMD_LF_SAMPLING_PRINT_CONFIG: { printConfig(); break; } + case CMD_LF_SAMPLING_GET_CONFIG: { + sample_config *c; + c = getSamplingConfig(); + Dbprintf("CMD_LF_SAMPLING_GET_CONFIG - before answer"); + reply_ng(CMD_LF_SAMPLING_GET_CONFIG, PM3_SUCCESS, (uint8_t *)c, sizeof(sample_config)); + break; + } case CMD_LF_SAMPLING_SET_CONFIG: { sample_config c; memcpy(&c, packet->data.asBytes, sizeof(sample_config)); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 2e33ec434..3ce7bc5da 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -81,7 +81,7 @@ void setSamplingConfig(sample_config *sc) { printConfig(); } -sample_config *getSamplingConfig() { +sample_config *getSamplingConfig(void) { return &config; } diff --git a/client/cmdlf.c b/client/cmdlf.c index f153ba1c3..c44764fd0 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -457,6 +457,25 @@ int CmdFlexdemod(const char *Cmd) { return PM3_SUCCESS; } +int lf_getconfig(sample_config *config) { + if (!session.pm3_present) return PM3_ENOTTY; + + if (config == NULL) + return PM3_EINVARG; + + clearCommandBuffer(); + + SendCommandNG(CMD_LF_SAMPLING_GET_CONFIG, NULL, 0); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_LF_SAMPLING_GET_CONFIG, &resp, 2000)) { + PrintAndLogEx(WARNING, "command execution time out"); + return PM3_ETIMEOUT; + } + + config = (sample_config *) resp.data.asBytes; + return PM3_SUCCESS; +} + int lf_config(sample_config *config) { if (!session.pm3_present) return PM3_ENOTTY; @@ -464,7 +483,7 @@ int lf_config(sample_config *config) { if (config != NULL) SendCommandNG(CMD_LF_SAMPLING_SET_CONFIG, (uint8_t *)config, sizeof(sample_config)); else - SendCommandNG(CMD_LF_SAMPLING_GET_CONFIG, NULL, 0); + SendCommandNG(CMD_LF_SAMPLING_PRINT_CONFIG, NULL, 0); return PM3_SUCCESS; } diff --git a/client/cmdlf.h b/client/cmdlf.h index 7393405ba..bb0628609 100644 --- a/client/cmdlf.h +++ b/client/cmdlf.h @@ -34,5 +34,6 @@ int CmdLFfind(const char *Cmd); int lf_read(bool verbose, uint32_t samples); int lf_config(sample_config *config); +int lf_getconfig(sample_config *config); #endif diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 32b2ba35c..cff1f891f 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -392,7 +392,8 @@ typedef struct { #define CMD_LF_T55XX_WAKEUP 0x0224 #define CMD_LF_COTAG_READ 0x0225 #define CMD_LF_T55XX_SET_CONFIG 0x0226 -#define CMD_LF_SAMPLING_GET_CONFIG 0x0227 +#define CMD_LF_SAMPLING_PRINT_CONFIG 0x0227 +#define CMD_LF_SAMPLING_GET_CONFIG 0x0228 #define CMD_LF_T55XX_CHK_PWDS 0x0230 #define CMD_LF_T55XX_DANGERRAW 0x0231 From 393d998ad95ec3a0460c144e89176b2bc4b67385 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 5 Mar 2020 11:27:42 +0100 Subject: [PATCH 066/298] fix downloading lf config --- armsrc/appmain.c | 6 ++---- client/cmdlf.c | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 88c85ad57..1c76fad7d 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -726,10 +726,8 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_SAMPLING_GET_CONFIG: { - sample_config *c; - c = getSamplingConfig(); - Dbprintf("CMD_LF_SAMPLING_GET_CONFIG - before answer"); - reply_ng(CMD_LF_SAMPLING_GET_CONFIG, PM3_SUCCESS, (uint8_t *)c, sizeof(sample_config)); + sample_config *config = getSamplingConfig(); + reply_ng(CMD_LF_SAMPLING_GET_CONFIG, PM3_SUCCESS, (uint8_t *)config, sizeof(sample_config)); break; } case CMD_LF_SAMPLING_SET_CONFIG: { diff --git a/client/cmdlf.c b/client/cmdlf.c index c44764fd0..7fa73818d 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -471,8 +471,7 @@ int lf_getconfig(sample_config *config) { PrintAndLogEx(WARNING, "command execution time out"); return PM3_ETIMEOUT; } - - config = (sample_config *) resp.data.asBytes; + memcpy(config, resp.data.asBytes, sizeof(sample_config)); return PM3_SUCCESS; } From df6bc7e9f3e75c13c7afb95f3eff17912849956d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marlin=20S=C3=B6=C3=B6se?= <30473690+msoose@users.noreply.github.com> Date: Fri, 6 Mar 2020 10:58:18 +0800 Subject: [PATCH 067/298] Update mfc_default_keys.dic add key --- client/dictionaries/mfc_default_keys.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 0d838d435..3001edb61 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1083,3 +1083,4 @@ fc9839273862 4D8B8B95FDEE 354A787087F1 4a306e62e9b6 +B9C874AE63D0 From 0cde69ee22bb05015865b9b0f1134f7441873b2c Mon Sep 17 00:00:00 2001 From: bosb <12600404+bosb@users.noreply.github.com> Date: Fri, 6 Mar 2020 17:08:08 +0100 Subject: [PATCH 068/298] cleanup --- armsrc/hitagS.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 38cb4d478..dc43c4cd3 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -60,7 +60,7 @@ bool end = false; #db# conf0: C9 conf1: 00 conf2: 00 3 2 1 0 #db# Page[ 0]: 84 11 C2 5F uid -#db# Page[ 1]: AA 00 00 C9 conf +#db# Page[ 1]: AA 00 00 C9 conf, HITAG S 256 #db# Page[ 2]: 4E 4F 54 48 #db# Page[ 3]: 52 4B 49 4D #db# Page[ 4]: 00 00 00 00 @@ -104,7 +104,7 @@ bool end = false; #define HITAG_T_TAG_CAPTURE_THREE_HALF 41 #define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 -#define DBGLEVEL 4 +#define DBGLEVEL 0 /* * Implementation of the crc8 calculation from Hitag S @@ -225,6 +225,8 @@ static void hitag_send_bit(int bit) { } static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { + if (DBGLEVEL >= DBG_EXTENDED) + Dbprintf("hitag_send_frame: (%i) %02X %02X %02X %02X", frame_len, frame[0], frame[1], frame[2], frame[3]); // The beginning of the frame is hidden in some high level; pause until our bits will have an effect AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; HIGH(GPIO_SSC_DOUT); @@ -370,7 +372,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, case 5: { //UID request with a selected response protocol mode if (DBGLEVEL >= DBG_EXTENDED) - Dbprintf("...UID req %i %02x", rxlen, rx[0]); + Dbprintf("UID request: length: %i first byte: %02x", rxlen, rx[0]); tag.pstate = HT_READY; tag.tstate = HT_NO_OP; if ((rx[0] & 0xf0) == 0x30) { @@ -404,10 +406,10 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, case 45: { //select command from reader received if (DBGLEVEL >= DBG_EXTENDED) - DbpString("...select"); + DbpString("SELECT"); if (check_select(rx, tag.uid) == 1) { if (DBGLEVEL >= DBG_EXTENDED) - DbpString("...select match"); + DbpString("SELECT match"); //if the right tag was selected *txlen = 32; hitagS_set_frame_modulation(); @@ -471,9 +473,10 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } */ } + break; case 40: if (DBGLEVEL >= DBG_EXTENDED) - Dbprintf("....write"); + Dbprintf("WRITE"); //data received to be written if (tag.tstate == HT_WRITING_PAGE_DATA) { tag.tstate = HT_NO_OP; @@ -500,14 +503,10 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } break; case 20: { - if (DBGLEVEL >= DBG_EXTENDED) - Dbprintf("....read"); //write page, write block, read page or read block command received if ((rx[0] & 0xf0) == 0xc0) { //read page //send page data uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); - if (DBGLEVEL >= DBG_EXTENDED) - Dbprintf("....page %i", page); *txlen = 32; tx[0] = tag.pages[page][0]; tx[1] = tag.pages[page][1]; @@ -534,8 +533,6 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } } else if ((rx[0] & 0xf0) == 0xd0) { //read block uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); - if (DBGLEVEL >= DBG_EXTENDED) - Dbprintf("....block %i", page); *txlen = 32 * 4; //send page,...,page+3 data for (int i = 0; i < 4; i++) { @@ -562,10 +559,6 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } } else if ((rx[0] & 0xf0) == 0x80) { //write page uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); - if (DBGLEVEL >= DBG_EXTENDED) - Dbprintf("....write page: %i", page); - - hitagS_set_frame_modulation(); if ((tag.LCON && page == 1) || (tag.LKP && (page == 2 || page == 3))) { //deny @@ -580,8 +573,6 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } else if ((rx[0] & 0xf0) == 0x90) { //write block uint8_t page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16); - if (DBGLEVEL >= DBG_EXTENDED) - Dbprintf("....write block: %i", page); hitagS_set_frame_modulation(); if (page % 4 != 0 || page == 0) { //deny @@ -599,7 +590,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, break; default: if (DBGLEVEL >= DBG_EXTENDED) - Dbprintf("unknown rxlen: (%i) %02X %02X %02X %02X", rxlen, rx[0], rx[1], rx[2], rx[3]); + Dbprintf("unknown rxlen: (%i) %02X %02X %02X %02X ...", rxlen, rx[0], rx[1], rx[2], rx[3]); break; } } @@ -1192,6 +1183,9 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { uint64_t NrAr = 0; uint8_t key_[6]; + tag.pstate = HT_READY; + tag.tstate = HT_NO_OP; + switch (htf) { case RHTSF_CHALLENGE: { DbpString("Authenticating using nr,ar pair:"); From 40f553ffdcdf4898679e47d7ddc4241e3869bf75 Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sun, 8 Mar 2020 02:03:24 +1100 Subject: [PATCH 069/298] Add Mifare Ultralight commands to cheatsheet.md --- doc/cheatsheet.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 3fc446ec8..b5ccd39b8 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -277,6 +277,19 @@ pm3 --> hf mf dump pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-data.bin ``` +Read Mifare Ultralight EV1 +``` +pm3 --> hf mfu info +``` + +Clone Mifare Ultralight EV1 Sequence +``` +pm3 --> hf mfu dump k FFFFFFFF +pm3 --> script run dumptoemul-mfu -i hf-mfu-XXXX-dump.bin -o hf-mfu-XXXX-dump.eml +pm3 --> hf mfu eload u hf-mfu-XXXX-dump.eml +pm3 --> hf mfu sim t 7 u hf-mfu-XXXX-dump.eml +``` + ## Wiegand manipulation ^[Top](#top) From 618925b15cd5c79834a668eccc1560dbacc1339f Mon Sep 17 00:00:00 2001 From: Artem Gnatyuk Date: Sat, 7 Mar 2020 23:25:24 +0700 Subject: [PATCH 070/298] Final version --- armsrc/Standalone/Makefile.hal | 12 +++++++++++- armsrc/Standalone/Makefile.inc | 14 +++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index 2dec4cfde..776ae3f0f 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -41,9 +41,19 @@ define KNOWN_STANDALONE_DEFINITIONS | LF_ICEHID | LF HID collector to flashmem | | (RDV4 only) | | +----------------------------------------------------------+ +| LF_EM4100EMULV1 | Simulate predefined em4100 tags only | +| | | ++----------------------------------------------------------+ +| LF_EM4100EMULV2 | Read/simulate em4100 tags | +| | | ++----------------------------------------------------------+ +| LF_EM4100EMULV3 | Read/simulate em4100 tags & clone it | +| | to T555x tags | ++----------------------------------------------------------+ + endef -STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_ICEHID +STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_ICEHID LF_EM4100EMULV1 LF_EM4100EMULV2 LF_EM4100EMULV3 STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG HF_14ASNIFF STANDALONE_MODES_REQ_SMARTCARD := STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG HF_14ASNIFF LF_ICEHID diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index d4de0411e..e7ca1bfe0 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -40,4 +40,16 @@ endif # WITH_STANDALONE_LF_ICEHID ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS))) SRC_STANDALONE = lf_icehid.c -endif \ No newline at end of file +endif +# WITH_STANDALONE_LF_EM4100EMULV1 +ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMULV1,$(APP_CFLAGS))) + SRC_STANDALONE = lf_em4100emulV1.c +endif +# WITH_STANDALONE_LF_EM4100EMULV2 +ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMULV2,$(APP_CFLAGS))) + SRC_STANDALONE = lf_em4100emulV2.c +endif +# WITH_STANDALONE_LF_EM4100EMULV3 +ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMULV3,$(APP_CFLAGS))) + SRC_STANDALONE = lf_em4100emulV3.c +endif From 4b07fecd6b8cdea074bea7ed6ec82266ae8049c6 Mon Sep 17 00:00:00 2001 From: Artem Gnatyuk Date: Sun, 8 Mar 2020 00:07:38 +0700 Subject: [PATCH 071/298] Add missed files --- armsrc/Standalone/lf_em4100emulV1.c | 107 +++++++++++++++ armsrc/Standalone/lf_em4100emulV2.c | 171 ++++++++++++++++++++++++ armsrc/Standalone/lf_em4100emulV3.c | 197 ++++++++++++++++++++++++++++ 3 files changed, 475 insertions(+) create mode 100644 armsrc/Standalone/lf_em4100emulV1.c create mode 100644 armsrc/Standalone/lf_em4100emulV2.c create mode 100644 armsrc/Standalone/lf_em4100emulV3.c diff --git a/armsrc/Standalone/lf_em4100emulV1.c b/armsrc/Standalone/lf_em4100emulV1.c new file mode 100644 index 000000000..d132f3650 --- /dev/null +++ b/armsrc/Standalone/lf_em4100emulV1.c @@ -0,0 +1,107 @@ +//----------------------------------------------------------------------------- +// Artyom Gnatyuk, 2020 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// LF emul V1 - Very simple mode. Simulate only predefined in low[] IDs +// Short click - change current slot +// Long press - simulate tag ID from current slot +//----------------------------------------------------------------------------- +#include "standalone.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "lfops.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "string.h" +#include "BigBuf.h" + +#define MAX_IND 16 // 4 LEDs - 2^4 combinations +#define CLOCK 64 //for 125kHz + +// low & high - array for storage IDs. Its length must be equal. +// Predefined IDs must be stored in low[]. +// In high[] must be nulls +uint64_t low[] = {0x565A1140BE,0x365A398149,0x5555555555,0xFFFFFFFFFF}; +uint32_t high[] = {0,0,0,0}; +uint8_t *bba,slots_count; +int buflen; + +void ModInfo(void) { + DbpString(" LF EM4100 simulate standalone V1"); +} + +uint64_t ReversQuads(uint64_t bits){ + uint64_t result = 0; + for (int i = 0; i < 16; i++){ + result += ((bits >> (60 - 4 *i)) & 0xf) << (4 * i); + } + return result >> 24; +} + +void FillBuff(uint8_t bit) { + memset (bba + buflen, bit, CLOCK / 2); + buflen += (CLOCK / 2); + memset (bba + buflen, bit^1,CLOCK / 2); + buflen += (CLOCK / 2); +} + +void ConstructEM410xEmulBuf(uint64_t id) { + + int i, j, binary[4], parity[4]; + buflen = 0; + for (i = 0; i < 9; i++) + FillBuff(1); + parity[0] = parity[1] = parity[2] = parity[3] = 0; + for (i = 0; i < 10; i++) { + for (j = 3; j >= 0; j--, id /= 2) + binary[j] = id % 2; + for (j = 0; j < 4; j++) + FillBuff(binary[j]); + FillBuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); + for (j = 0; j < 4; j++) + parity[j] ^= binary[j]; + } + for (j = 0; j < 4; j++) + FillBuff(parity[j]); + FillBuff(0); +} + +void LED_Slot(int i) { + if (slots_count > 4) { + LED(i % MAX_IND, 0); //binary indication for slots_count > 4 + } else { + LED(1 << i,0); //simple indication for slots_count <=4 + } +} + +void RunMod() { + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + int selected = 0; + slots_count = sizeof(low)/sizeof(low[0]); + bba = BigBuf_get_addr(); + LED_Slot(selected); + for (;;) { + WDT_HIT(); + if (data_available()) break; + int button_pressed = BUTTON_HELD(1000); + SpinDelay(300); + if (button_pressed == 1) { + SpinUp(100); + SpinOff(10); + LED_Slot(selected); + ConstructEM410xEmulBuf(ReversQuads(low[selected])); + SimulateTagLowFrequency(buflen, 0, true); + LED_Slot(selected); + } else if (button_pressed < 0) { + selected = (selected + 1) % slots_count; + LEDsoff(); + LED_Slot(selected); + } + } +} diff --git a/armsrc/Standalone/lf_em4100emulV2.c b/armsrc/Standalone/lf_em4100emulV2.c new file mode 100644 index 000000000..2b48aeced --- /dev/null +++ b/armsrc/Standalone/lf_em4100emulV2.c @@ -0,0 +1,171 @@ +//----------------------------------------------------------------------------- +// Artyom Gnatyuk, 2020 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// LF emul V2 - This mode can simulate tag ID from selected slot and read tag ID +// to selected slot and to flash (only RDV4). Also you can set +// predefined IDs in any slot. +// To recall stored ID from flash execute: +// mem dump o offset l 5 p +// where offset = 5 * selected slot +//----------------------------------------------------------------------------- +#include "standalone.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "lfops.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "string.h" +#include "BigBuf.h" + +#ifdef WITH_FLASH +#include "flashmem.h" +#endif + +#define MAX_IND 16 // 4 LEDs - 2^4 combinations +#define CLOCK 64 //for 125kHz + +// low & high - array for storage IDs. Its length must be equal. +// Predefined IDs must be stored in low[]. +// In high[] must be nulls +uint64_t low[] = {0x565AF781C7,0x540053E4E2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +uint32_t high[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +uint8_t *bba,slots_count; +int buflen; + +void ModInfo(void) { + DbpString(" LF EM4100 simulate standalone V2"); +} + +uint64_t ReversQuads(uint64_t bits){ + uint64_t result = 0; + for (int i = 0; i < 16; i++){ + result += ((bits >> (60 - 4 *i)) & 0xf) << (4 * i); + } + return result >> 24; +} + +void FillBuff(uint8_t bit) { + memset (bba + buflen, bit, CLOCK / 2); + buflen += (CLOCK / 2); + memset (bba + buflen, bit^1,CLOCK / 2); + buflen += (CLOCK / 2); +} + +void ConstructEM410xEmulBuf(uint64_t id) { + + int i, j, binary[4], parity[4]; + buflen = 0; + for (i = 0; i < 9; i++) + FillBuff(1); + parity[0] = parity[1] = parity[2] = parity[3] = 0; + for (i = 0; i < 10; i++) { + for (j = 3; j >= 0; j--, id /= 2) + binary[j] = id % 2; + for (j = 0; j < 4; j++) + FillBuff(binary[j]); + FillBuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); + for (j = 0; j < 4; j++) + parity[j] ^= binary[j]; + } + for (j = 0; j < 4; j++) + FillBuff(parity[j]); + FillBuff(0); +} + +void LED_Slot(int i) { + if (slots_count > 4) { + LED(i % MAX_IND, 0); //binary indication, usefully for slots_count > 4 + } else { + LED(1 << i,0); //simple indication for slots_count <=4 + } +} + +void FlashLEDs(uint32_t speed, uint8_t times) { + for (int i = 0; i < times * 2; i++) { + LED_A_INV(); + LED_B_INV(); + LED_C_INV(); + LED_D_INV(); + SpinDelay(speed); + } +} + +#ifdef WITH_FLASH +void SaveIDtoFlash (int addr, uint64_t id) { + uint8_t b, *ptr; + for (int i = 0; i < 5; i++) { + b = (uint8_t) (id >> 8 * i & 0xff); + ptr = &b; + Flash_WriteData(addr * 5 + 4 - i,ptr,1); + } +} +#endif + +void RunMod() { + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + int selected = 0; + //state 0 - select slot, + // 1 - read tag to selected slot, + // 2 - simulate tag from selected slot + uint8_t state = 0; + slots_count = sizeof(low)/sizeof(low[0]); + bba = BigBuf_get_addr(); + LED_Slot(selected); + for (;;) { + WDT_HIT(); + if (data_available()) break; + int button_pressed = BUTTON_HELD(1000); + SpinDelay(300); + switch (state){ + case 0: + // Select mode + if (button_pressed == 1) { + // Long press - switch to simulate mode + SpinUp(100); + SpinOff(100); + LED_Slot(selected); + state = 2; + } else if (button_pressed < 0) { + // Click - switch to next slot + selected = (selected + 1) % slots_count; + LEDsoff(); + LED_Slot(selected); + } + break; + case 1: + // Read mode. Click - exit to select mode + CmdEM410xdemod(1, &high[selected], &low[selected], 0); + FlashLEDs(100,5); + #ifdef WITH_FLASH + SaveIDtoFlash(selected, low[selected]); + #endif + state = 0; + break; + case 2: + // Simulate mode + if (button_pressed > 0) { + // Long press - switch to read mode + SpinDown(100); + SpinOff(10); + LED_Slot(selected); + state = 1; + } else if (button_pressed < 0) { + // Click - start simulating. Click again to exit from simelate mode + LED_Slot(selected); + ConstructEM410xEmulBuf(ReversQuads(low[selected])); + FlashLEDs(100,5); + SimulateTagLowFrequency(buflen, 0, 1); + LED_Slot(selected); + state = 0; // Switch to select mode + } + break; + } + } +} diff --git a/armsrc/Standalone/lf_em4100emulV3.c b/armsrc/Standalone/lf_em4100emulV3.c new file mode 100644 index 000000000..98247c390 --- /dev/null +++ b/armsrc/Standalone/lf_em4100emulV3.c @@ -0,0 +1,197 @@ +//----------------------------------------------------------------------------- +// Artyom Gnatyuk, 2020 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// LF emul V3 - This mode can simulate ID from selected slot, read ID to +// selected slot, write from selected slot to T5555 tag and store +// readed ID to flash (only RDV4). Also you can set predefined IDs +// in any slot. +// To recall stored ID from flash execute: +// mem dump o offset l 5 p +// where offset = 5 * selected slot +//----------------------------------------------------------------------------- +#include "standalone.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "lfops.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "string.h" +#include "BigBuf.h" + +#ifdef WITH_FLASH +#include "flashmem.h" +#endif + +#define MAX_IND 16 // 4 LEDs - 2^4 combinations +#define CLOCK 64 //for 125kHz + +// low & high - array for storage IDs. Its length must be equal. +// Predefined IDs must be stored in low[]. +// In high[] must be nulls +uint64_t low[] = {0x565AF781C7,0x540053E4E2,0x1234567890,0,0,0,0,0,0,0,0,0,0,0,0,0}; +uint32_t high[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +uint8_t *bba,slots_count; +int buflen; + +void ModInfo(void) { + DbpString(" LF EM4100 simulate standalone V2"); +} + +uint64_t ReversQuads(uint64_t bits){ + uint64_t result = 0; + for (int i = 0; i < 16; i++){ + result += ((bits >> (60 - 4 *i)) & 0xf) << (4 * i); + } + return result >> 24; +} + +void FillBuff(uint8_t bit) { + memset (bba + buflen, bit, CLOCK / 2); + buflen += (CLOCK / 2); + memset (bba + buflen, bit^1,CLOCK / 2); + buflen += (CLOCK / 2); +} + +void ConstructEM410xEmulBuf(uint64_t id) { + + int i, j, binary[4], parity[4]; + buflen = 0; + for (i = 0; i < 9; i++) + FillBuff(1); + parity[0] = parity[1] = parity[2] = parity[3] = 0; + for (i = 0; i < 10; i++) { + for (j = 3; j >= 0; j--, id /= 2) + binary[j] = id % 2; + for (j = 0; j < 4; j++) + FillBuff(binary[j]); + FillBuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); + for (j = 0; j < 4; j++) + parity[j] ^= binary[j]; + } + for (j = 0; j < 4; j++) + FillBuff(parity[j]); + FillBuff(0); +} + +void LED_Slot(int i) { + if (slots_count > 4) { + LED(i % MAX_IND, 0); //binary indication, usefully for slots_count > 4 + } else { + LED(1 << i,0); //simple indication for slots_count <=4 + } +} + +void FlashLEDs(uint32_t speed, uint8_t times) { + for (int i = 0; i < times * 2; i++) { + LED_A_INV(); + LED_B_INV(); + LED_C_INV(); + LED_D_INV(); + SpinDelay(speed); + } +} + +#ifdef WITH_FLASH +void SaveIDtoFlash (int addr, uint64_t id) { + uint8_t b, *ptr; + for (int i = 0; i < 5; i++) { + b = (uint8_t) (id >> 8 * i & 0xff); + ptr = &b; + Flash_WriteData(addr * 5 + 4 - i,ptr,1); + } +} +#endif + +void RunMod() { + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + int selected = 0; + //state 0 - select slot + // 1 - read tag to selected slot, + // 2 - simulate tag from selected slot + // 3 - write to T5555 tag + uint8_t state = 0; + slots_count = sizeof(low)/sizeof(low[0]); + bba = BigBuf_get_addr(); + LED_Slot(selected); + for (;;) { + WDT_HIT(); + if (data_available()) break; + int button_pressed = BUTTON_HELD(1000); + SpinDelay(300); + switch (state){ + case 0: + // Select mode + if (button_pressed == 1) { + // Long press - switch to simulate mode + SpinUp(100); + SpinOff(100); + LED_Slot(selected); + state = 2; + } else if (button_pressed < 0) { + // Click - switch to next slot + selected = (selected + 1) % slots_count; + LEDsoff(); + LED_Slot(selected); + } + break; + case 1: + // Read mode. + if (button_pressed > 0) { + // Long press - switch to read mode + SpinUp(100); + SpinOff(10); + LED_Slot(selected); + state = 3; + } else if (button_pressed < 0) { + // Click - exit to select mode + CmdEM410xdemod(1, &high[selected], &low[selected], 0); + FlashLEDs(100,5); + #ifdef WITH_FLASH + SaveIDtoFlash(selected, low[selected]); + #endif + state = 0; + } + break; + case 2: + // Simulate mode + if (button_pressed > 0) { + // Long press - switch to read mode + SpinDown(100); + SpinOff(10); + LED_Slot(selected); + state = 1; + } else if (button_pressed < 0) { + // Click - start simulating. Click again to exit from simelate mode + LED_Slot(selected); + ConstructEM410xEmulBuf(ReversQuads(low[selected])); + FlashLEDs(100,5); + SimulateTagLowFrequency(buflen, 0, 1); + LED_Slot(selected); + state = 0; // Switch to select mode + } + break; + case 3: + // Write tag mode + if (button_pressed > 0) { + // Long press - switch to select mode + SpinDown(100); + SpinOff(10); + LED_Slot(selected); + state = 0; + } else if (button_pressed < 0) { + // Click - write ID to tag + WriteEM410x(0, (uint32_t) (low[selected] >> 32), (uint32_t) (low[selected] & 0xffffffff)); + LED_Slot(selected); + state = 0; // Switch to select mode + } + break; + } + } +} From a4b8c14e1e559a32cd9c24be49c23a8cdf854c02 Mon Sep 17 00:00:00 2001 From: Artem Gnatyuk Date: Sun, 8 Mar 2020 00:13:13 +0700 Subject: [PATCH 072/298] Fix version number --- armsrc/Standalone/lf_em4100emulV3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/Standalone/lf_em4100emulV3.c b/armsrc/Standalone/lf_em4100emulV3.c index 98247c390..b1bf0d930 100644 --- a/armsrc/Standalone/lf_em4100emulV3.c +++ b/armsrc/Standalone/lf_em4100emulV3.c @@ -40,7 +40,7 @@ uint8_t *bba,slots_count; int buflen; void ModInfo(void) { - DbpString(" LF EM4100 simulate standalone V2"); + DbpString(" LF EM4100 simulate standalone V3"); } uint64_t ReversQuads(uint64_t bits){ From 074f6c374ee0122076476531df5a3bde4aa6ca7f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 11:02:26 +0100 Subject: [PATCH 073/298] add: hf mf personlize - Personalize the UID of a Mifare Classic EV1 card (@pwpiwi) see https://github.com/Proxmark/proxmark3/commit/0b4efbdef20ccf33ba7b5f6dbe36ab80cfe5477a --- armsrc/appmain.c | 12 ++++++ armsrc/mifarecmd.c | 66 +++++++++++++++++++++++++++++--- armsrc/mifarecmd.h | 2 + client/cmdhfmf.c | 91 ++++++++++++++++++++++++++++++++++++++++++++- include/pm3_cmd.h | 2 + include/protocols.h | 4 ++ 6 files changed, 171 insertions(+), 6 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 1c76fad7d..5464d7ddb 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -42,6 +42,7 @@ #include "Standalone/standalone.h" #include "util.h" #include "ticks.h" +#include "commonutil.h" #ifdef WITH_LCD #include "LCD.h" @@ -1247,6 +1248,17 @@ static void PacketReceived(PacketCommandNG *packet) { // SniffMifare(packet->oldarg[0]); // break; // } + case CMD_HF_MIFARE_PERSONALIZE_UID: { + struct p { + uint8_t keytype; + uint8_t pers_option; + uint8_t key[6]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + uint64_t authkey = bytes_to_num(payload->key, 6); + MifarePersonalizeUID(payload->keytype, payload->pers_option, authkey); + break; + } case CMD_HF_MIFARE_SETMOD: { MifareSetMod(packet->data.asBytes); break; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index b869489ab..3669e13ea 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1805,6 +1805,63 @@ void MifareChkKeys_file(uint8_t *fn) { #endif } +//----------------------------------------------------------------------------- +// MIFARE Personalize UID. Only for Mifare Classic EV1 7Byte UID +//----------------------------------------------------------------------------- +void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key) { + + uint16_t isOK = PM3_EUNDEF; + uint8_t uid[10]; + uint32_t cuid; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); + + LED_A_ON(); + + while (true) { + if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); + break; + } + + uint8_t block_number = 0; + if (mifare_classic_auth(pcs, cuid, block_number, keyType, key, AUTH_FIRST)) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error"); + break; + } + + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + int len = mifare_sendcmd_short(pcs, true, MIFARE_EV1_PERSONAL_UID, perso_option, receivedAnswer, receivedAnswerPar, NULL); + if (len != 1 || receivedAnswer[0] != CARD_ACK) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + break;; + } + + if (mifare_classic_halt(pcs, cuid)) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error"); + break; + } + isOK = PM3_SUCCESS; + break; + } + + crypto1_deinit(pcs); + + LED_B_ON(); + reply_ng(CMD_HF_MIFARE_PERSONALIZE_UID, isOK, NULL, 0); + LED_B_OFF(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} + + //----------------------------------------------------------------------------- // Work with emulator memory // @@ -2276,23 +2333,23 @@ void MifareSetMod(uint8_t *datain) { while (true) { if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); break; } if (mifare_classic_auth(pcs, cuid, 0, 0, ui64Key, AUTH_FIRST)) { - if (DBGLEVEL >= 1) Dbprintf("Auth error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error"); break; } int respLen; if (((respLen = mifare_sendcmd_short(pcs, CRYPT_ALL, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) { - if (DBGLEVEL >= 1) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen); break; } if (mifare_classic_halt(pcs, cuid)) { - if (DBGLEVEL >= 1) Dbprintf("Halt error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error"); break; } @@ -2304,7 +2361,6 @@ void MifareSetMod(uint8_t *datain) { LED_B_ON(); reply_ng(CMD_HF_MIFARE_SETMOD, isOK, NULL, 0); - LED_B_OFF(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 1f5ee63a4..91adba3b1 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -45,6 +45,8 @@ void MifareCIdent(); // is "magic chinese" card? void MifareHasStaticNonce(); // Has the tag a static nonce? void MifareSetMod(uint8_t *datain); +void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key); + void MifareUSetPwd(uint8_t arg0, uint8_t *datain); void OnSuccessMagic(); void OnErrorMagic(uint8_t reason); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 24296b31d..6a57491fc 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -4798,6 +4798,95 @@ static int CmdHFMFNDEF(const char *Cmd) { return PM3_SUCCESS; } +int CmdHFMFPersonalize(const char *cmd) { + + CLIParserInit("hf mf personalize", + "Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.", + "Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n" + "\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n" + "\thf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n" + "\thf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n" + "\thf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A\n"); + + void *argtable[] = { + arg_param_begin, + arg_str0("tT", "keytype", "", "key type (A or B) to authenticate sector 0 (default: A)"), + arg_str0("kK", "key", "", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"), + arg_str1(NULL, NULL, "", "Personalization Option"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + char keytypestr[2] = "a"; + uint8_t keytype = 0x00; + int keytypestr_len; + int res = CLIParamStrToBuf(arg_get_str(1), (uint8_t*)keytypestr, 1, &keytypestr_len); + str_lower(keytypestr); + + if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'b')) { + PrintAndLogEx(ERR, "ERROR: not a valid key type. Key type must be A or B"); + CLIParserFree(); + return PM3_EINVARG; + } + if (keytypestr[0] == 'b') { + keytype = 0x01; + } + + uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + int key_len; + res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len); + if (res || (!res && key_len > 0 && key_len != 6)) { + PrintAndLogEx(ERR, "ERROR: not a valid key. Key must be 12 hex digits"); + CLIParserFree(); + return PM3_EINVARG; + } + + char pers_optionstr[6]; + int opt_len; + uint8_t pers_option; + res = CLIParamStrToBuf(arg_get_str(3), (uint8_t*)pers_optionstr, 5, &opt_len); + str_lower(pers_optionstr); + + if (res || (!res && opt_len > 0 && opt_len != 5) + || (strncmp(pers_optionstr, "uidf0", 5) && strncmp(pers_optionstr, "uidf1", 5) && strncmp(pers_optionstr, "uidf2", 5) && strncmp(pers_optionstr, "uidf3", 5))) { + PrintAndLogEx(ERR, "ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3"); + CLIParserFree(); + return PM3_EINVARG; + } + if (!strncmp(pers_optionstr, "uidf0", 5)) { + pers_option = MIFARE_EV1_UIDF0; + } else if (!strncmp(pers_optionstr, "uidf1", 5)) { + pers_option = MIFARE_EV1_UIDF1; + } else if (!strncmp(pers_optionstr, "uidf2", 5)) { + pers_option = MIFARE_EV1_UIDF2; + } else { + pers_option = MIFARE_EV1_UIDF3; + } + + CLIParserFree(); + + clearCommandBuffer(); + + struct { + uint8_t keytype; + uint8_t pers_option; + uint8_t key[6]; + } PACKED payload; + payload.keytype = keytype; + payload.pers_option = pers_option; + + memcpy(payload.key, key, 6); + + SendCommandNG(CMD_HF_MIFARE_PERSONALIZE_UID, (uint8_t *)&payload, sizeof(payload)); + + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_HF_MIFARE_PERSONALIZE_UID, &resp, 2500)) return PM3_ETIMEOUT; + + PrintAndLogEx(SUCCESS, "Personalization %s", resp.status == PM3_SUCCESS ? "SUCCEEDED" : "FAILED"); + + return PM3_SUCCESS; +} + static int CmdHF14AMfList(const char *Cmd) { (void)Cmd; // Cmd is not used so far return CmdTraceList("mf"); @@ -4845,7 +4934,7 @@ static command_t CommandTable[] = { {"-----------", CmdHelp, IfPm3Iso14443a, ""}, {"mad", CmdHF14AMfMAD, IfPm3Iso14443a, "Checks and prints MAD"}, {"ndef", CmdHFMFNDEF, IfPm3Iso14443a, "Prints NDEF records from card"}, - + {"personalize", CmdHFMFPersonalize, IfPm3Iso14443a, "Personalize UID (Mifare Classic EV1 only)"}, {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, {NULL, NULL, NULL, NULL} }; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index cff1f891f..8cffa892a 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -505,6 +505,8 @@ typedef struct { #define CMD_HF_MIFARE_SNIFF 0x0630 #define CMD_HF_MIFARE_MFKEY 0x0631 +#define CMD_HF_MIFARE_PERSONALIZE_UID 0x0632 + //ultralightC #define CMD_HF_MIFAREUC_AUTH 0x0724 //0x0725 and 0x0726 no longer used diff --git a/include/protocols.h b/include/protocols.h index e1d898d53..e992a97ee 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -163,6 +163,10 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MIFARE_EV1_PERSONAL_UID 0x40 #define MIFARE_EV1_SETMODE 0x43 +#define MIFARE_EV1_UIDF0 0x00 +#define MIFARE_EV1_UIDF1 0x40 +#define MIFARE_EV1_UIDF2 0x20 +#define MIFARE_EV1_UIDF3 0x60 #define MIFARE_ULC_WRITE 0xA2 #define MIFARE_ULC_COMP_WRITE 0xA0 From 0f16070c0913948b6aec7d5973ab687c759c2320 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 11:04:32 +0100 Subject: [PATCH 074/298] text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8896f223c..a0391fdf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added `hf mf personlize` - personalize the UID of a Mifare Classic EV1 card (@pwpiwi) - Change - hint texts added to all lf clone commands (@iceman1001) - Change `lf keri demod` - adjusted the internal id. (@mwalker33) - Added seamless integration with cryptohelper (@iceman1001) From 111af2bacba142fff7daa9caf17fa7a3dc608cc1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 16:39:52 +0100 Subject: [PATCH 075/298] Chg: 'lf indala clone' - now can use FC/CN for 26b format. Checksum is still not known. --- client/cmdlfindala.c | 130 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 19 deletions(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 01eb4b8f8..08b869378 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -28,6 +28,8 @@ #include "protocols.h" // t55 defines #include "cmdlft55xx.h" // verifywrite +#define INDALA_ARR_LEN 64 + static int CmdHelp(const char *Cmd); //large 224 bit indala formats (different preamble too...) @@ -140,7 +142,7 @@ static void decodeHeden2L(uint8_t *bits) { if (bits[offset + 7]) cardnumber += 16384; if (bits[offset + 23]) cardnumber += 32768; - PrintAndLogEx(SUCCESS, "\tHeden-2L | %u", cardnumber); + PrintAndLogEx(SUCCESS, "\tHeden-2L | " _YELLOW_("%u"), cardnumber); } // Indala 26 bit decode @@ -192,7 +194,7 @@ static int CmdIndalaDemod(const char *Cmd) { if (DemodBufferLen == 64) { PrintAndLogEx( SUCCESS - , "Indala Found - bitlength %zu, Raw %x%08x" + , "Indala Found - bitlength %zu, Raw " _YELLOW_("%x%08x") , DemodBufferLen , uid1 , uid2 @@ -244,14 +246,18 @@ static int CmdIndalaDemod(const char *Cmd) { checksum |= DemodBuffer[63] << 0; // b1 PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Fmt 26 bit FC " _YELLOW_("%u") ", CN " _YELLOW_("%u") ", checksum %1d%1d" + , fc + , csn + , checksum >> 1 & 0x01 + , checksum & 0x01 + ); + PrintAndLogEx(SUCCESS, "Possible de-scramble patterns"); PrintAndLogEx(SUCCESS, "\tPrinted | __%04d__ [0x%X]", p1, p1); PrintAndLogEx(SUCCESS, "\tInternal ID | %" PRIu64, foo); decodeHeden2L(DemodBuffer); - PrintAndLogEx(SUCCESS, "Fmt 26 bit FC %u , CSN %u , checksum %1d%1d", fc, csn, checksum >> 1 & 0x01, checksum & 0x01); - - } else { uint32_t uid3 = bytebits_to_byte(DemodBuffer + 64, 32); uint32_t uid4 = bytebits_to_byte(DemodBuffer + 96, 32); @@ -542,49 +548,62 @@ static int CmdIndalaSim(const char *Cmd) { static int CmdIndalaClone(const char *Cmd) { - bool is_long_uid = false, got_cn = false; + bool is_long_uid = false, got_cn = false, got_26 = false; bool is_t5555 = false; int32_t cardnumber; uint32_t blocks[8] = {0}; uint8_t max = 0; uint8_t data[7 * 4]; int datalen = 0; + uint8_t fc = 0; + uint16_t cn = 0; CLIParserInit("lf indala clone", "clone INDALA tag to T55x7 (or to q5/T5555)", "Examples:\n" "\tlf indala clone -c 888\n" + "\tlf indala clone -fc 123 -csn 1337\n" "\tlf indala clone -r a0000000a0002021\n" "\tlf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"); void *argtable[] = { arg_param_begin, - arg_lit0("lL", "long", "optional - long UID 224 bits"), - arg_int0("cC", "cn", "", "Cardnumber for Heden 2L format"), - arg_strx0("rR", "raw", "", "raw bytes"), - arg_lit0("qQ", "Q5", "optional - specify write to Q5 (t5555 instead of t55x7)"), + arg_lit0("lL", "long", "optional - long UID 224 bits"), + arg_int0("cC", "heden", "", "Cardnumber for Heden 2L format"), + arg_strx0("rR", "raw", "", "raw bytes"), + arg_lit0("qQ", "Q5", "optional - specify write to Q5 (t5555 instead of t55x7)"), + arg_int0("", "fc", "", "Facility Code (26 bit format)"), + arg_int0("", "cn", "", "Cardnumber (26 bit format)"), arg_param_end }; CLIExecWithReturn(Cmd, argtable, false); is_long_uid = arg_get_lit(1); - if (is_long_uid == false) { - cardnumber = arg_get_int_def(2, -1); - got_cn = (cardnumber != -1); - } - if (got_cn == false) { - CLIGetHexWithReturn(3, data, &datalen); - } + // raw param + CLIGetHexWithReturn(3, data, &datalen); is_t5555 = arg_get_lit(4); + if (is_long_uid == false) { + + // Heden param + cardnumber = arg_get_int_def(2, -1); + got_cn = (cardnumber != -1); + + // 26b FC/CN param + fc = arg_get_int_def(5, 0); + cn = arg_get_int_def(6, 0); + got_26 = (fc != 0 && cn != 0); + } + CLIParserFree(); if (is_long_uid) { // 224 BIT UID // config for Indala (RF/32;PSK2 with RF/2;Maxblock=7) - PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with RawID %s", sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag"); + PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen)); if (is_t5555) blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT); @@ -602,12 +621,41 @@ static int CmdIndalaClone(const char *Cmd) { } else { // 64 BIT UID if (got_cn) { + PrintAndLogEx(INFO, "Using Indala HEDEN cardnumber %u", cardnumber); encodeHeden2L(data, cardnumber); datalen = 8; + } else if (got_26) { + + PrintAndLogEx(INFO, "Using Indala 26b FC %u CN %u", fc, cn); + + // Used with the 26bit FC/CSN + uint8_t *bits = calloc(INDALA_ARR_LEN, sizeof(uint8_t)); + if (bits == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); + return PM3_EMALLOC; + } + + if (getIndalaBits(fc, cn, bits) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Error with tag bitstream generation."); + return PM3_ESOFT; + } + + data[0] = bytebits_to_byte(bits, 8); + data[1] = bytebits_to_byte(bits + 8, 8); + data[2] = bytebits_to_byte(bits + 16, 8); + data[3] = bytebits_to_byte(bits + 24, 8); + data[4] = bytebits_to_byte(bits + 32, 8); + data[5] = bytebits_to_byte(bits + 40, 8); + data[6] = bytebits_to_byte(bits + 48, 8); + data[7] = bytebits_to_byte(bits + 56, 8); + datalen = 8; + + free(bits); } // config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2) - PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with RawID %s", sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag"); + PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen)); if (is_t5555) blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | (2 << T5555_MAXBLOCK_SHIFT); @@ -647,6 +695,50 @@ int CmdLFINDALA(const char *Cmd) { return CmdsParse(CommandTable, Cmd); } +int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits) { + // preamble + // is there a preamble? + bits[0] = 1; + bits[2] = 1; + bits[32] = 1; + + // add fc + bits[57] = ((fc >> 7) & 1); // b8 + bits[49] = ((fc >> 6) & 1); // b7 + bits[44] = ((fc >> 5) & 1); // b6 + bits[47] = ((fc >> 4) & 1); // b5 + bits[48] = ((fc >> 3) & 1); // b4 + bits[53] = ((fc >> 2) & 1); // b3 + bits[39] = ((fc >> 1) & 1); // b2 + bits[58] = (fc & 1); // b1 + + // add cn + bits[42] = ((cn >> 15) & 1); // b16 + bits[45] = ((cn >> 14) & 1); // b15 + bits[43] = ((cn >> 13) & 1); // b14 + bits[40] = ((cn >> 12) & 1); // b13 + bits[52] = ((cn >> 11) & 1); // b12 + bits[36] = ((cn >> 10) & 1); // b11 + bits[35] = ((cn >> 9) & 1); // b10 + bits[51] = ((cn >> 8) & 1); // b9 + bits[46] = ((cn >> 7) & 1); // b8 + bits[33] = ((cn >> 6) & 1); // b7 + bits[37] = ((cn >> 5) & 1); // b6 + bits[54] = ((cn >> 4) & 1); // b5 + bits[56] = ((cn >> 3) & 1); // b4 + bits[59] = ((cn >> 2) & 1); // b3 + bits[50] = ((cn >> 1) & 1); // b2 + bits[41] = (cn & 1); // b1 + + // checksum + // ICEMAN: todo: needs to calc + uint8_t chk = 3; + bits[62] = ((chk >> 1) & 1); // b2 + bits[63] = (chk & 1); // b1 + + return PM3_SUCCESS; +} + // redesigned by marshmellow adjusted from existing decode functions // indala id decoding int detectIndala(uint8_t *dest, size_t *size, uint8_t *invert) { From b485461fba132633931d8cfc185e54521039edf6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 16:43:14 +0100 Subject: [PATCH 076/298] style --- tools/hitag2crack/crack2/HardwareProfile.h | 8 +- tools/hitag2crack/crack2/hitagcrypto.c | 32 ++++---- tools/hitag2crack/crack2/hitagcrypto.h | 4 +- .../hitag2crack/crack2/ht2crack2buildtable.c | 79 ++++++++----------- tools/hitag2crack/crack2/ht2crack2gentest.c | 12 ++- tools/hitag2crack/crack2/ht2crack2search.c | 53 ++++++------- tools/hitag2crack/crack2/ht2crack2utils.c | 67 ++++++---------- tools/hitag2crack/crack2/rfidler.h | 2 +- tools/hitag2crack/crack2/util.h | 2 +- tools/hitag2crack/crack2/utilpart.c | 29 +++---- 10 files changed, 121 insertions(+), 167 deletions(-) diff --git a/tools/hitag2crack/crack2/HardwareProfile.h b/tools/hitag2crack/crack2/HardwareProfile.h index a2f804be6..bce139042 100644 --- a/tools/hitag2crack/crack2/HardwareProfile.h +++ b/tools/hitag2crack/crack2/HardwareProfile.h @@ -142,11 +142,11 @@ typedef int rtccDate; #ifndef __PIC32MX__ - #define __PIC32MX__ +#define __PIC32MX__ #endif - + #define GetSystemClock() (80000000ul) -#define GetPeripheralClock() (GetSystemClock()) +#define GetPeripheralClock() (GetSystemClock()) #define GetInstructionClock() (GetSystemClock()) //#define USE_SELF_POWER_SENSE_IO @@ -322,7 +322,7 @@ typedef int rtccDate; // spi for SD card #define SD_CARD_DET LATFbits.LATF0 #define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it - // (held LOW by default - cut solder bridge to GND to free pin if required) +// (held LOW by default - cut solder bridge to GND to free pin if required) #define SPI_SD SPI_CHANNEL1 #define SPI_SD_BUFF SPI1BUF #define SPI_SD_STAT SPI1STATbits diff --git a/tools/hitag2crack/crack2/hitagcrypto.c b/tools/hitag2crack/crack2/hitagcrypto.c index 2334f8288..5ebfc5ae9 100644 --- a/tools/hitag2crack/crack2/hitagcrypto.c +++ b/tools/hitag2crack/crack2/hitagcrypto.c @@ -229,17 +229,16 @@ static uint32_t hitag2_crypt(uint64_t x); ((S >> (C - 3)) & 8) ) -static uint32_t hitag2_crypt(uint64_t s) -{ +static uint32_t hitag2_crypt(uint64_t s) { const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 uint32_t bitindex; - bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1; - bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02; - bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04; - bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08; + bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08; bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); @@ -253,13 +252,12 @@ static uint32_t hitag2_crypt(uint64_t s) * uint32_t serialnum - 32 bit tag serial number * uint32_t initvector - 32 bit random IV from reader, part of tag authentication */ -void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) -{ +void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) { // init state, from serial number and lowest 16 bits of shared key uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum; // mix the initialisation vector and highest 32 bits of the shared key - initvector ^= (uint32_t) (sharedkey >> 16); + initvector ^= (uint32_t)(sharedkey >> 16); // move 16 bits from (IV xor Shared Key) to top of uint64_t state // these will be XORed in turn with output of the crypto function @@ -320,9 +318,9 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui // optimise with one 64-bit intermediate uint64_t temp = state ^ (state >> 1); pstate->lfsr = state ^ (state >> 6) ^ (state >> 16) - ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) - ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) - ^ (temp >> 42) ^ (temp >> 46); + ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) + ^ (temp >> 42) ^ (temp >> 46); } } @@ -338,8 +336,7 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui * Hitag_State* pstate - in/out, internal cipher state after initialisation * uint32_t steps - number of bits requested, (capped at 32) */ -uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps) -{ +uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps) { uint64_t state = pstate->shiftreg; uint32_t result = 0; uint64_t lfsr = pstate->lfsr; @@ -448,7 +445,7 @@ unsigned hitag2_verifytest() const uint64_t key = rev64 (0x524B494D4E4FUL); const uint32_t serial = rev32 (0x69574349); const uint32_t initvec = rev32 (0x72456E65); - + uint32_t i; Hitag_State state; @@ -471,11 +468,10 @@ unsigned hitag2_verifytest() #ifdef UNIT_TEST -int main(int argc, char* argv[]) -{ +int main(int argc, char *argv[]) { unsigned pass = hitag2_verifytest(); - printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); + printf("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); if (pass) { hitag2_benchtest(10000); diff --git a/tools/hitag2crack/crack2/hitagcrypto.h b/tools/hitag2crack/crack2/hitagcrypto.h index d5aa9104c..46d447370 100644 --- a/tools/hitag2crack/crack2/hitagcrypto.h +++ b/tools/hitag2crack/crack2/hitagcrypto.h @@ -159,9 +159,9 @@ typedef struct { uint64_t lfsr; // fast lfsr, used to make software faster } Hitag_State; -void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector); +void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector); -uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); +uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps); unsigned int hitag2_benchtest_gen32(); unsigned int hitag2_benchtest(uint32_t count); diff --git a/tools/hitag2crack/crack2/ht2crack2buildtable.c b/tools/hitag2crack/crack2/ht2crack2buildtable.c index 402c5b245..ffabd8f2e 100644 --- a/tools/hitag2crack/crack2/ht2crack2buildtable.c +++ b/tools/hitag2crack/crack2/ht2crack2buildtable.c @@ -18,7 +18,7 @@ // // If sorting fails with a 'bus error' then that is likely because your disk I/O can't keep up with // the read/write demands of the multi-threaded sorting. In this case, reduce the number of sorting -// threads. This will most likely only be a problem with network disks; SATA should be okay; +// threads. This will most likely only be a problem with network disks; SATA should be okay; // USB2/3 should keep up. // // These MUST be a power of 2 for the maths to work - you have been warned! @@ -53,8 +53,7 @@ uint64_t d2[48]; int nsteps2; // create table entry -void create_table(struct table *t, int d1, int d2) -{ +void create_table(struct table *t, int d1, int d2) { if (!t) { printf("create_table: t is NULL\n"); exit(1); @@ -83,8 +82,7 @@ void create_table(struct table *t, int d1, int d2) // create all table entries -void create_tables(struct table *t) -{ +void create_tables(struct table *t) { int i, j; if (!t) { @@ -92,8 +90,8 @@ void create_tables(struct table *t) exit(1); } - for (i=0; i<0x100; i++) { - for (j=0; j<0x100; j++) { + for (i = 0; i < 0x100; i++) { + for (j = 0; j < 0x100; j++) { create_table(t + ((i * 0x100) + j), i, j); } } @@ -101,8 +99,7 @@ void create_tables(struct table *t) // free the table memory -void free_tables(struct table *t) -{ +void free_tables(struct table *t) { int i; struct table *ttmp; @@ -111,7 +108,7 @@ void free_tables(struct table *t) exit(1); } - for (i=0; i<0x10000; i++) { + for (i = 0; i < 0x10000; i++) { ttmp = t + i; free(ttmp->data); } @@ -120,8 +117,7 @@ void free_tables(struct table *t) // write (partial) table to file -void writetable(struct table *t1) -{ +void writetable(struct table *t1) { int fd; if (debug) printf("writetable %s\n", t1->path); @@ -146,8 +142,7 @@ void writetable(struct table *t1) // store value in table -void store(unsigned char *data) -{ +void store(unsigned char *data) { unsigned char d1, d2; int offset; struct table *t1; @@ -171,7 +166,7 @@ void store(unsigned char *data) if (debug) printf("store, offset = %d, got lock\n", offset); // store the entry - memcpy(t1->ptr, data+2, 10); + memcpy(t1->ptr, data + 2, 10); if (debug) printf("store, offset = %d, copied data\n", offset); @@ -199,14 +194,13 @@ void store(unsigned char *data) } // writes the ks (keystream) and s (state) -void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg) -{ +void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg) { unsigned char buf[16]; // create buffer writebuf(buf, ks1, 3); - writebuf(buf+3, ks2, 3); - writebuf(buf+6, shiftreg, 6); + writebuf(buf + 3, ks2, 3); + writebuf(buf + 6, shiftreg, 6); // store buffer store(buf); @@ -215,8 +209,7 @@ void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg) // builds the di table for jumping -void builddi(int steps, int table) -{ +void builddi(int steps, int table) { uint64_t statemask; int i; Hitag_State mystate; @@ -237,7 +230,7 @@ void builddi(int steps, int table) } // build di states - for (i=0; i<48; i++) { + for (i = 0; i < 48; i++) { mystate.shiftreg = statemask; buildlfsr(&mystate); hitag2_nstep(&mystate, steps); @@ -248,8 +241,7 @@ void builddi(int steps, int table) } // jump function - quickly jumps a load of steps -void jumpnsteps(Hitag_State *hstate, int table) -{ +void jumpnsteps(Hitag_State *hstate, int table) { uint64_t output = 0; uint64_t bitmask; int i; @@ -271,7 +263,7 @@ void jumpnsteps(Hitag_State *hstate, int table) // if si is 1, di.si = di; if si is 0, di.si = 0 bitmask = 1; - for (i=0; i<48; i++) { + for (i = 0; i < 48; i++) { if (hstate->shiftreg & bitmask) { output = output ^ thisd[i]; } @@ -281,12 +273,11 @@ void jumpnsteps(Hitag_State *hstate, int table) hstate->shiftreg = output; buildlfsr(hstate); -} +} // thread to build a part of the table -void *buildtable(void *d) -{ +void *buildtable(void *d) { Hitag_State hstate; Hitag_State hstate2; unsigned long i; @@ -301,7 +292,7 @@ void *buildtable(void *d) buildlfsr(&hstate); /* jump to offset using jump table 2 (2048) */ - for (i=0; iptr > t1->data) { writetable(t1); @@ -531,7 +518,7 @@ int main(int argc, char *argv[]) // start the threads - for (i=0; ilen); i++) { + for (i = 0; (i < filestat.st_size) && (j < r->len); i++) { if ((data[i] != 0x0a) && (data[i] != 0x0d) && (data[i] != 0x20)) { if (!nibble) { r->data[j] = hex2bin(data[i]) << 4; @@ -93,8 +91,7 @@ int loadrngdata(struct rngdata *r, char *file) return 1; } -int makecand(unsigned char *c, struct rngdata *r, int bitoffset) -{ +int makecand(unsigned char *c, struct rngdata *r, int bitoffset) { int bytenum; int bitnum; int i; @@ -107,7 +104,7 @@ int makecand(unsigned char *c, struct rngdata *r, int bitoffset) bytenum = bitoffset / 8; bitnum = bitoffset % 8; - for (i=0; i<6; i++) { + for (i = 0; i < 6; i++) { if (!bitnum) { c[i] = r->data[bytenum + i]; } else { @@ -120,8 +117,7 @@ int makecand(unsigned char *c, struct rngdata *r, int bitoffset) // test the candidate against the next or previous rng data -int testcand(unsigned char *f, unsigned char *rt, int fwd) -{ +int testcand(unsigned char *f, unsigned char *rt, int fwd) { Hitag_State hstate; int i; uint32_t ks1; @@ -130,8 +126,8 @@ int testcand(unsigned char *f, unsigned char *rt, int fwd) // build the prng state at the candidate hstate.shiftreg = 0; - for (i=0; i<6; i++) { - hstate.shiftreg = (hstate.shiftreg << 8) | f[i+4]; + for (i = 0; i < 6; i++) { + hstate.shiftreg = (hstate.shiftreg << 8) | f[i + 4]; } buildlfsr(&hstate); @@ -149,7 +145,7 @@ int testcand(unsigned char *f, unsigned char *rt, int fwd) ks2 = hitag2_nstep(&hstate, 24); writebuf(buf, ks1, 3); - writebuf(buf+3, ks2, 3); + writebuf(buf + 3, ks2, 3); // compare them if (!memcmp(buf, rt, 6)) { @@ -159,8 +155,7 @@ int testcand(unsigned char *f, unsigned char *rt, int fwd) } } -int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, unsigned char *s) -{ +int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, unsigned char *s) { int fd; struct stat filestat; char file[64]; @@ -193,7 +188,7 @@ int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, u exit(1); } - memcpy(item, c+2, 4); + memcpy(item, c + 2, 4); found = (unsigned char *)bsearch(item, data, filestat.st_size / DATASIZE, DATASIZE, datacmp); @@ -209,13 +204,13 @@ int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, u while (((found - data) <= (filestat.st_size - DATASIZE)) && (!memcmp(found, item, 4))) { if (testcand(found, rt, fwd)) { memcpy(m, c, 2); - memcpy(m+2, found, 4); - memcpy(s, found+4, 6); + memcpy(m + 2, found, 4); + memcpy(s, found + 4, 6); munmap(data, filestat.st_size); close(fd); return 1; - } + } found = found + DATASIZE; } @@ -228,8 +223,7 @@ int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, u } -int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstate, int *bitoffset) -{ +int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstate, int *bitoffset) { int i; int bitlen; unsigned char cand[6]; @@ -243,7 +237,7 @@ int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstat bitlen = r->len * 8; - for (i=0; i<=bitlen - 48; i++) { + for (i = 0; i <= bitlen - 48; i++) { // print progress if ((i % 100) == 0) { printf("searching on bit %d\n", i); @@ -283,8 +277,7 @@ int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstat -void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset) -{ +void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset) { int i; if (!s) { @@ -294,7 +287,7 @@ void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset) // build prng at recovered offset hstate->shiftreg = 0; - for (i=0; i<6; i++) { + for (i = 0; i < 6; i++) { hstate->shiftreg = (hstate->shiftreg << 8) | s[i]; } @@ -313,8 +306,7 @@ void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset) } -uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) -{ +uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) { uint64_t key; uint64_t keyupper; uint32_t uid; @@ -333,7 +325,7 @@ uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) uidtmp = uid; // rollback and extract bits b - for (i=0; i<32; i++) { + for (i = 0; i < 32; i++) { hstate->shiftreg = ((hstate->shiftreg) << 1) | ((uidtmp >> 31) & 0x1); uidtmp = uidtmp << 1; b = (b << 1) | fnf(hstate->shiftreg); @@ -364,8 +356,7 @@ uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) } -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { Hitag_State hstate; struct rngdata rng; int bitoffset = 0; @@ -420,7 +411,7 @@ int main(int argc, char *argv[]) printf("\n"); printf("KEY:\t\t"); - for (i=0; i<6; i++) { + for (i = 0; i < 6; i++) { printf("%02X", (int)(key & 0xff)); key = key >> 8; } diff --git a/tools/hitag2crack/crack2/ht2crack2utils.c b/tools/hitag2crack/crack2/ht2crack2utils.c index 2152f8ef3..75d4c27a9 100644 --- a/tools/hitag2crack/crack2/ht2crack2utils.c +++ b/tools/hitag2crack/crack2/ht2crack2utils.c @@ -1,13 +1,11 @@ #include "ht2crack2utils.h" // writes a value into a buffer as a series of bytes -void writebuf(unsigned char *buf, uint64_t val, unsigned int len) -{ +void writebuf(unsigned char *buf, uint64_t val, unsigned int len) { int i; char c; - for (i=len-1; i>=0; i--) - { + for (i = len - 1; i >= 0; i--) { c = val & 0xff; buf[i] = c; val = val >> 8; @@ -17,18 +15,17 @@ void writebuf(unsigned char *buf, uint64_t val, unsigned int len) /* simple hexdump for testing purposes */ -void shexdump(unsigned char *data, int data_len) -{ +void shexdump(unsigned char *data, int data_len) { int i; if (!data || (data_len <= 0)) { printf("shexdump: invalid parameters\n"); return; } - + printf("Hexdump from %p:\n", data); - for (i=0; i> 7); x = x << 1; } @@ -60,14 +56,13 @@ void printbin(unsigned char *c) } -void printbin2(uint64_t val, unsigned int size) -{ +void printbin2(uint64_t val, unsigned int size) { int i; uint64_t mask = 1; mask = mask << (size - 1); - for (i=0; ishiftreg, 48); printf("\n"); @@ -89,8 +83,7 @@ void printstate(Hitag_State *hstate) // convert hex char to binary -unsigned char hex2bin(unsigned char c) -{ +unsigned char hex2bin(unsigned char c) { if ((c >= '0') && (c <= '9')) { return (c - '0'); } else if ((c >= 'a') && (c <= 'f')) { @@ -103,8 +96,7 @@ unsigned char hex2bin(unsigned char c) } // return a single bit from a value -int bitn(uint64_t x, int bit) -{ +int bitn(uint64_t x, int bit) { uint64_t bitmask = 1; bitmask = bitmask << bit; @@ -118,20 +110,18 @@ int bitn(uint64_t x, int bit) // the sub-function R that rollback depends upon -int fnR(uint64_t x) -{ +int fnR(uint64_t x) { // renumbered bits because my state is 0-47, not 1-48 return (bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^ bitn(x, 6) ^ bitn(x, 7) ^ - bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^ - bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47)); + bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^ + bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47)); } // the rollback function that lets us go backwards in time -void rollback(Hitag_State *hstate, unsigned int steps) -{ +void rollback(Hitag_State *hstate, unsigned int steps) { int i; - for (i=0; ishiftreg = ((hstate->shiftreg << 1) & 0xffffffffffff) | fnR(hstate->shiftreg); } @@ -139,24 +129,20 @@ void rollback(Hitag_State *hstate, unsigned int steps) // the three filter sub-functions that feed fnf -int fa(unsigned int i) -{ +int fa(unsigned int i) { return bitn(0x2C79, i); } -int fb(unsigned int i) -{ +int fb(unsigned int i) { return bitn(0x6671, i); } -int fc(unsigned int i) -{ +int fc(unsigned int i) { return bitn(0x7907287B, i); } // the filter function that generates a bit of output from the prng state -int fnf(uint64_t s) -{ +int fnf(uint64_t s) { unsigned int x1, x2, x3, x4, x5, x6; x1 = (bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3); @@ -171,16 +157,15 @@ int fnf(uint64_t s) } // builds the lfsr for the prng (quick calcs for hitag2_nstep()) -void buildlfsr(Hitag_State *hstate) -{ +void buildlfsr(Hitag_State *hstate) { uint64_t state = hstate->shiftreg; uint64_t temp; temp = state ^ (state >> 1); hstate->lfsr = state ^ (state >> 6) ^ (state >> 16) - ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) - ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) - ^ (temp >> 42) ^ (temp >> 46); + ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) + ^ (temp >> 42) ^ (temp >> 46); } diff --git a/tools/hitag2crack/crack2/rfidler.h b/tools/hitag2crack/crack2/rfidler.h index c8ce90396..933547e6b 100644 --- a/tools/hitag2crack/crack2/rfidler.h +++ b/tools/hitag2crack/crack2/rfidler.h @@ -336,7 +336,7 @@ extern rtccDate RTC_date; // date structure #define TAG_TYPE_AWID_26 17 #define TAG_TYPE_EM4X05 18 #define TAG_TYPE_TAMAGOTCHI 19 -#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram +#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram // various diff --git a/tools/hitag2crack/crack2/util.h b/tools/hitag2crack/crack2/util.h index c0d4c156a..c20fdf3c2 100644 --- a/tools/hitag2crack/crack2/util.h +++ b/tools/hitag2crack/crack2/util.h @@ -182,7 +182,7 @@ unsigned char getbit(unsigned char byte, unsigned char bit); void bytestohex(unsigned char *target, unsigned char *source, unsigned int length); unsigned int manchester_encode(unsigned char *target, unsigned char *source, unsigned int length); unsigned int manchester_decode(unsigned char *target, unsigned char *source, unsigned int length); -char * strip_newline(char *buff); +char *strip_newline(char *buff); BOOL command_ack(BOOL data); BOOL command_nack(BYTE *reason); BOOL command_unknown(void); diff --git a/tools/hitag2crack/crack2/utilpart.c b/tools/hitag2crack/crack2/utilpart.c index 210853ec1..c46148491 100644 --- a/tools/hitag2crack/crack2/utilpart.c +++ b/tools/hitag2crack/crack2/utilpart.c @@ -142,19 +142,17 @@ rtccTime RTC_time; // time structure rtccDate RTC_date; // date structure // convert byte-reversed 8 digit hex to unsigned long -unsigned long hexreversetoulong(BYTE *hex) -{ - unsigned long ret= 0L; +unsigned long hexreversetoulong(BYTE *hex) { + unsigned long ret = 0L; unsigned int x; BYTE i; - if(strlen(hex) != 8) + if (strlen(hex) != 8) return 0L; - for(i= 0 ; i < 4 ; ++i) - { - if(sscanf(hex, "%2X", &x) != 1) - return 0L; + for (i = 0 ; i < 4 ; ++i) { + if (sscanf(hex, "%2X", &x) != 1) + return 0L; ret += ((unsigned long) x) << i * 8; hex += 2; } @@ -162,18 +160,17 @@ unsigned long hexreversetoulong(BYTE *hex) } // convert byte-reversed 12 digit hex to unsigned long -unsigned long long hexreversetoulonglong(BYTE *hex) -{ - unsigned long long ret= 0LL; +unsigned long long hexreversetoulonglong(BYTE *hex) { + unsigned long long ret = 0LL; BYTE tmp[9]; - - // this may seem an odd way to do it, but weird compiler issues were + + // this may seem an odd way to do it, but weird compiler issues were // breaking direct conversion! - - tmp[8]= '\0'; + + tmp[8] = '\0'; memset(tmp + 4, '0', 4); memcpy(tmp, hex + 8, 4); - ret= hexreversetoulong(tmp); + ret = hexreversetoulong(tmp); ret <<= 32; memcpy(tmp, hex, 8); ret += hexreversetoulong(tmp); From c73517b64db3c00ca50e8fedd8c6281ea9ad7af9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 16:44:07 +0100 Subject: [PATCH 077/298] style --- tools/hitag2crack/crack3/HardwareProfile.h | 8 +- tools/hitag2crack/crack3/hitagcrypto.c | 32 ++- tools/hitag2crack/crack3/hitagcrypto.h | 4 +- tools/hitag2crack/crack3/ht2crack3.c | 70 +++--- tools/hitag2crack/crack3/ht2test.c | 5 +- tools/hitag2crack/crack3/rfidler.h | 2 +- tools/hitag2crack/crack3/utilpart.c | 29 ++- tools/hitag2crack/crack4/HardwareProfile.h | 8 +- tools/hitag2crack/crack4/hitagcrypto.c | 32 ++- tools/hitag2crack/crack4/hitagcrypto.h | 4 +- tools/hitag2crack/crack4/ht2crack2utils.c | 67 +++--- tools/hitag2crack/crack4/ht2crack4.c | 234 ++++++++++----------- tools/hitag2crack/crack4/rfidler.h | 2 +- tools/hitag2crack/crack4/utilpart.c | 29 ++- 14 files changed, 233 insertions(+), 293 deletions(-) diff --git a/tools/hitag2crack/crack3/HardwareProfile.h b/tools/hitag2crack/crack3/HardwareProfile.h index a2f804be6..bce139042 100644 --- a/tools/hitag2crack/crack3/HardwareProfile.h +++ b/tools/hitag2crack/crack3/HardwareProfile.h @@ -142,11 +142,11 @@ typedef int rtccDate; #ifndef __PIC32MX__ - #define __PIC32MX__ +#define __PIC32MX__ #endif - + #define GetSystemClock() (80000000ul) -#define GetPeripheralClock() (GetSystemClock()) +#define GetPeripheralClock() (GetSystemClock()) #define GetInstructionClock() (GetSystemClock()) //#define USE_SELF_POWER_SENSE_IO @@ -322,7 +322,7 @@ typedef int rtccDate; // spi for SD card #define SD_CARD_DET LATFbits.LATF0 #define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it - // (held LOW by default - cut solder bridge to GND to free pin if required) +// (held LOW by default - cut solder bridge to GND to free pin if required) #define SPI_SD SPI_CHANNEL1 #define SPI_SD_BUFF SPI1BUF #define SPI_SD_STAT SPI1STATbits diff --git a/tools/hitag2crack/crack3/hitagcrypto.c b/tools/hitag2crack/crack3/hitagcrypto.c index 422efbe92..23b88228d 100644 --- a/tools/hitag2crack/crack3/hitagcrypto.c +++ b/tools/hitag2crack/crack3/hitagcrypto.c @@ -229,17 +229,16 @@ static uint32_t hitag2_crypt(uint64_t x); ((S >> (C - 3)) & 8) ) -static uint32_t hitag2_crypt(uint64_t s) -{ +static uint32_t hitag2_crypt(uint64_t s) { const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 uint32_t bitindex; - bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1; - bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02; - bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04; - bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08; + bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08; bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); @@ -253,13 +252,12 @@ static uint32_t hitag2_crypt(uint64_t s) * uint32_t serialnum - 32 bit tag serial number * uint32_t initvector - 32 bit random IV from reader, part of tag authentication */ -void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) -{ +void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) { // init state, from serial number and lowest 16 bits of shared key uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum; // mix the initialisation vector and highest 32 bits of the shared key - initvector ^= (uint32_t) (sharedkey >> 16); + initvector ^= (uint32_t)(sharedkey >> 16); // move 16 bits from (IV xor Shared Key) to top of uint64_t state // these will be XORed in turn with output of the crypto function @@ -320,9 +318,9 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui // optimise with one 64-bit intermediate uint64_t temp = state ^ (state >> 1); pstate->lfsr = state ^ (state >> 6) ^ (state >> 16) - ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) - ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) - ^ (temp >> 42) ^ (temp >> 46); + ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) + ^ (temp >> 42) ^ (temp >> 46); } } @@ -338,8 +336,7 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui * Hitag_State* pstate - in/out, internal cipher state after initialisation * uint32_t steps - number of bits requested, (capped at 32) */ -uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps) -{ +uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps) { uint64_t state = pstate->shiftreg; uint32_t result = 0; uint64_t lfsr = pstate->lfsr; @@ -446,7 +443,7 @@ unsigned hitag2_verifytest() const uint64_t key = rev64 (0x524B494D4E4FUL); const uint32_t serial = rev32 (0x69574349); const uint32_t initvec = rev32 (0x72456E65); - + uint32_t i; Hitag_State state; @@ -469,11 +466,10 @@ unsigned hitag2_verifytest() #ifdef UNIT_TEST -int main(int argc, char* argv[]) -{ +int main(int argc, char *argv[]) { unsigned pass = hitag2_verifytest(); - printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); + printf("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); if (pass) { hitag2_benchtest(10000); diff --git a/tools/hitag2crack/crack3/hitagcrypto.h b/tools/hitag2crack/crack3/hitagcrypto.h index d5aa9104c..46d447370 100644 --- a/tools/hitag2crack/crack3/hitagcrypto.h +++ b/tools/hitag2crack/crack3/hitagcrypto.h @@ -159,9 +159,9 @@ typedef struct { uint64_t lfsr; // fast lfsr, used to make software faster } Hitag_State; -void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector); +void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector); -uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); +uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps); unsigned int hitag2_benchtest_gen32(); unsigned int hitag2_benchtest(uint32_t count); diff --git a/tools/hitag2crack/crack3/ht2crack3.c b/tools/hitag2crack/crack3/ht2crack3.c index 190f8197d..747f7785c 100644 --- a/tools/hitag2crack/crack3/ht2crack3.c +++ b/tools/hitag2crack/crack3/ht2crack3.c @@ -34,11 +34,10 @@ struct threaddata { uint64_t klowerrange; }; -void printbin(uint64_t val) -{ +void printbin(uint64_t val) { int i; - for (i=0; i<64; i++) { + for (i = 0; i < 64; i++) { if (val & 0x8000000000000000) { printf("1"); } else { @@ -48,8 +47,7 @@ void printbin(uint64_t val) } } -void printstate(Hitag_State *hstate) -{ +void printstate(Hitag_State *hstate) { printf("shiftreg =\t"); printbin(hstate->shiftreg); printf("\n"); @@ -70,17 +68,16 @@ void printstate(Hitag_State *hstate) ((S >> (C - 3)) & 8) ) -static uint32_t hitag2_crypt(uint64_t s) -{ +static uint32_t hitag2_crypt(uint64_t s) { const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 uint32_t bitindex; - bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1; - bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02; - bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04; - bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08; + bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08; bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; return (ht2_function5c >> bitindex) & 1; @@ -89,17 +86,16 @@ static uint32_t hitag2_crypt(uint64_t s) // this function is a modification of the filter function f, based heavily // on the hitag2_crypt function in Rfidler -int fnP(uint64_t klowery) -{ +int fnP(uint64_t klowery) { const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 const uint32_t ht2_function4p = 0xAE83; // 1010 1110 1000 0011 uint32_t i; - i = (ht2_function4a >> pickbits2_2 (klowery, 2, 5)) & 1; - i |= ((ht2_function4b << 1) >> pickbits1_1_2 (klowery, 8, 12, 14)) & 0x02; - i |= ((ht2_function4b << 2) >> pickbits1x4 (klowery, 17, 21, 23, 26)) & 0x04; - i |= ((ht2_function4b << 3) >> pickbits2_1_1 (klowery, 28, 31, 33)) & 0x08; + i = (ht2_function4a >> pickbits2_2(klowery, 2, 5)) & 1; + i |= ((ht2_function4b << 1) >> pickbits1_1_2(klowery, 8, 12, 14)) & 0x02; + i |= ((ht2_function4b << 2) >> pickbits1x4(klowery, 17, 21, 23, 26)) & 0x04; + i |= ((ht2_function4b << 3) >> pickbits2_1_1(klowery, 28, 31, 33)) & 0x08; // modified to use reference implementation approach // orig fc table is 0x7907287B = 0111 1001 0000 0111 0010 1000 0111 1011 @@ -109,8 +105,7 @@ int fnP(uint64_t klowery) } // comparison function for sorting/searching Tklower entries -int Tk_cmp(const void *v1, const void *v2) -{ +int Tk_cmp(const void *v1, const void *v2) { const struct Tklower *Tk1 = (struct Tklower *)v1; const struct Tklower *Tk2 = (struct Tklower *)v2; @@ -148,8 +143,7 @@ int is_kmiddle_badguess(uint64_t z, struct Tklower *Tk, int max, int aR0) { } // function to test if a partial key is valid -int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR) -{ +int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR) { uint64_t kupper; uint64_t key; Hitag_State hstate; @@ -162,7 +156,7 @@ int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR normaR = ((revaR >> 24) | ((revaR >> 8) & 0xff00) | ((revaR << 8) & 0xff0000) | (revaR << 24)); // search for remaining 14 bits - for (kupper=0; kupper < 0x3fff; kupper++) { + for (kupper = 0; kupper < 0x3fff; kupper++) { key = (kupper << 34) | pkey; hitag2_init(&hstate, key, uid, nR); b = hitag2_nstep(&hstate, 32); @@ -170,7 +164,7 @@ int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR *out = key; return 1; } - } + } return 0; } @@ -205,8 +199,7 @@ int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR // effectively work out candidates for the lower 34 bits of the key. -void *crack(void *d) -{ +void *crack(void *d) { struct threaddata *data = (struct threaddata *)d; uint64_t uid; struct nRaR *TnRaR; @@ -249,11 +242,11 @@ void *crack(void *d) } // find keys - for (klower=data->klowerstart; klower < (data->klowerstart + data->klowerrange); klower++) { + for (klower = data->klowerstart; klower < (data->klowerstart + data->klowerrange); klower++) { printf("trying klower = 0x%05lx\n", klower); // build table count = 0; - for (y=0; y<0x40000; y++) { + for (y = 0; y < 0x40000; y++) { // create klowery klowery = (y << 16) | klower; // check for cases where right most bit of fc doesn't matter @@ -268,9 +261,9 @@ void *crack(void *d) // insert y into shiftreg and extract keystream, reversed order b = 0; ytmp = y; - for (j=0; j<2; j++) { + for (j = 0; j < 2; j++) { hstate.shiftreg = hstate.shiftreg | ((ytmp & 0xffff) << 48); - for (i=0; i<16; i++) { + for (i = 0; i < 16; i++) { hstate.shiftreg = hstate.shiftreg >> 1; bit = hitag2_crypt(hstate.shiftreg); b = (b >> 1) | (bit << 31); @@ -295,11 +288,11 @@ void *crack(void *d) qsort(Tk, count, sizeof(struct Tklower), Tk_cmp); // look for matches - for (kmiddle=0; kmiddle<0x40000; kmiddle++) { + for (kmiddle = 0; kmiddle < 0x40000; kmiddle++) { // loop over nRaR pairs badguess = 0; found = 0; - for (i=0; (i> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000); @@ -331,8 +324,7 @@ void *crack(void *d) return NULL; } -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { FILE *fp; int i; pthread_t threads[NUM_THREADS]; @@ -401,8 +393,8 @@ int main(int argc, char *argv[]) } *buft2 = 0x00; if (!strncmp(buf, "0x", 2)) { - TnRaR[numnrar].nR = rev32(hexreversetoulong(buf+2)); - TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1+2)); + TnRaR[numnrar].nR = rev32(hexreversetoulong(buf + 2)); + TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1 + 2)); } else { TnRaR[numnrar].nR = rev32(hexreversetoulong(buf)); TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1)); @@ -423,7 +415,7 @@ int main(int argc, char *argv[]) exit(1); } - for (i=0; i> (C - 3)) & 8) ) -static uint32_t hitag2_crypt(uint64_t s) -{ +static uint32_t hitag2_crypt(uint64_t s) { const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 uint32_t bitindex; - bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1; - bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02; - bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04; - bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08; + bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08; bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); @@ -253,13 +252,12 @@ static uint32_t hitag2_crypt(uint64_t s) * uint32_t serialnum - 32 bit tag serial number * uint32_t initvector - 32 bit random IV from reader, part of tag authentication */ -void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) -{ +void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) { // init state, from serial number and lowest 16 bits of shared key uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum; // mix the initialisation vector and highest 32 bits of the shared key - initvector ^= (uint32_t) (sharedkey >> 16); + initvector ^= (uint32_t)(sharedkey >> 16); // move 16 bits from (IV xor Shared Key) to top of uint64_t state // these will be XORed in turn with output of the crypto function @@ -320,9 +318,9 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui // optimise with one 64-bit intermediate uint64_t temp = state ^ (state >> 1); pstate->lfsr = state ^ (state >> 6) ^ (state >> 16) - ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) - ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) - ^ (temp >> 42) ^ (temp >> 46); + ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) + ^ (temp >> 42) ^ (temp >> 46); } } @@ -338,8 +336,7 @@ void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, ui * Hitag_State* pstate - in/out, internal cipher state after initialisation * uint32_t steps - number of bits requested, (capped at 32) */ -uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps) -{ +uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps) { uint64_t state = pstate->shiftreg; uint32_t result = 0; uint64_t lfsr = pstate->lfsr; @@ -446,7 +443,7 @@ unsigned hitag2_verifytest() const uint64_t key = rev64 (0x524B494D4E4FUL); const uint32_t serial = rev32 (0x69574349); const uint32_t initvec = rev32 (0x72456E65); - + uint32_t i; Hitag_State state; @@ -469,11 +466,10 @@ unsigned hitag2_verifytest() #ifdef UNIT_TEST -int main(int argc, char* argv[]) -{ +int main(int argc, char *argv[]) { unsigned pass = hitag2_verifytest(); - printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); + printf("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); if (pass) { hitag2_benchtest(10000); diff --git a/tools/hitag2crack/crack4/hitagcrypto.h b/tools/hitag2crack/crack4/hitagcrypto.h index d5aa9104c..46d447370 100644 --- a/tools/hitag2crack/crack4/hitagcrypto.h +++ b/tools/hitag2crack/crack4/hitagcrypto.h @@ -159,9 +159,9 @@ typedef struct { uint64_t lfsr; // fast lfsr, used to make software faster } Hitag_State; -void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector); +void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector); -uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); +uint32_t hitag2_nstep(Hitag_State *pstate, uint32_t steps); unsigned int hitag2_benchtest_gen32(); unsigned int hitag2_benchtest(uint32_t count); diff --git a/tools/hitag2crack/crack4/ht2crack2utils.c b/tools/hitag2crack/crack4/ht2crack2utils.c index 2152f8ef3..75d4c27a9 100644 --- a/tools/hitag2crack/crack4/ht2crack2utils.c +++ b/tools/hitag2crack/crack4/ht2crack2utils.c @@ -1,13 +1,11 @@ #include "ht2crack2utils.h" // writes a value into a buffer as a series of bytes -void writebuf(unsigned char *buf, uint64_t val, unsigned int len) -{ +void writebuf(unsigned char *buf, uint64_t val, unsigned int len) { int i; char c; - for (i=len-1; i>=0; i--) - { + for (i = len - 1; i >= 0; i--) { c = val & 0xff; buf[i] = c; val = val >> 8; @@ -17,18 +15,17 @@ void writebuf(unsigned char *buf, uint64_t val, unsigned int len) /* simple hexdump for testing purposes */ -void shexdump(unsigned char *data, int data_len) -{ +void shexdump(unsigned char *data, int data_len) { int i; if (!data || (data_len <= 0)) { printf("shexdump: invalid parameters\n"); return; } - + printf("Hexdump from %p:\n", data); - for (i=0; i> 7); x = x << 1; } @@ -60,14 +56,13 @@ void printbin(unsigned char *c) } -void printbin2(uint64_t val, unsigned int size) -{ +void printbin2(uint64_t val, unsigned int size) { int i; uint64_t mask = 1; mask = mask << (size - 1); - for (i=0; ishiftreg, 48); printf("\n"); @@ -89,8 +83,7 @@ void printstate(Hitag_State *hstate) // convert hex char to binary -unsigned char hex2bin(unsigned char c) -{ +unsigned char hex2bin(unsigned char c) { if ((c >= '0') && (c <= '9')) { return (c - '0'); } else if ((c >= 'a') && (c <= 'f')) { @@ -103,8 +96,7 @@ unsigned char hex2bin(unsigned char c) } // return a single bit from a value -int bitn(uint64_t x, int bit) -{ +int bitn(uint64_t x, int bit) { uint64_t bitmask = 1; bitmask = bitmask << bit; @@ -118,20 +110,18 @@ int bitn(uint64_t x, int bit) // the sub-function R that rollback depends upon -int fnR(uint64_t x) -{ +int fnR(uint64_t x) { // renumbered bits because my state is 0-47, not 1-48 return (bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^ bitn(x, 6) ^ bitn(x, 7) ^ - bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^ - bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47)); + bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^ + bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47)); } // the rollback function that lets us go backwards in time -void rollback(Hitag_State *hstate, unsigned int steps) -{ +void rollback(Hitag_State *hstate, unsigned int steps) { int i; - for (i=0; ishiftreg = ((hstate->shiftreg << 1) & 0xffffffffffff) | fnR(hstate->shiftreg); } @@ -139,24 +129,20 @@ void rollback(Hitag_State *hstate, unsigned int steps) // the three filter sub-functions that feed fnf -int fa(unsigned int i) -{ +int fa(unsigned int i) { return bitn(0x2C79, i); } -int fb(unsigned int i) -{ +int fb(unsigned int i) { return bitn(0x6671, i); } -int fc(unsigned int i) -{ +int fc(unsigned int i) { return bitn(0x7907287B, i); } // the filter function that generates a bit of output from the prng state -int fnf(uint64_t s) -{ +int fnf(uint64_t s) { unsigned int x1, x2, x3, x4, x5, x6; x1 = (bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3); @@ -171,16 +157,15 @@ int fnf(uint64_t s) } // builds the lfsr for the prng (quick calcs for hitag2_nstep()) -void buildlfsr(Hitag_State *hstate) -{ +void buildlfsr(Hitag_State *hstate) { uint64_t state = hstate->shiftreg; uint64_t temp; temp = state ^ (state >> 1); hstate->lfsr = state ^ (state >> 6) ^ (state >> 16) - ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) - ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) - ^ (temp >> 42) ^ (temp >> 46); + ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) + ^ (temp >> 42) ^ (temp >> 46); } diff --git a/tools/hitag2crack/crack4/ht2crack4.c b/tools/hitag2crack/crack4/ht2crack4.c index da439692f..44952f4b7 100644 --- a/tools/hitag2crack/crack4/ht2crack4.c +++ b/tools/hitag2crack/crack4/ht2crack4.c @@ -93,8 +93,7 @@ uint64_t uid; int maxtablesize = 800000; uint64_t supplied_testkey = 0; -void usage() -{ +void usage() { printf("ht2crack4 - K Sheldrake, based on the work of Garcia et al\n\n"); printf("Cracks a HiTag2 key using a small number (4 to 16) of encrypted\n"); printf("nonce and challenge response pairs, using a fast correlation\n"); @@ -130,46 +129,44 @@ const uint64_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 011 * a known least-sig pattern. first index is num bits in known part, second is the * bit pattern of the known part. */ double pfna[][8] = { -{0.50000, 0.50000, }, -{0.50000, 0.50000, 0.50000, 0.50000, }, -{0.50000, 0.00000, 0.50000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, }, + {0.50000, 0.50000, }, + {0.50000, 0.50000, 0.50000, 0.50000, }, + {0.50000, 0.00000, 0.50000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, }, }; double pfnb[][8] = { -{0.62500, 0.37500, }, -{0.50000, 0.75000, 0.75000, 0.00000, }, -{0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 1.00000, 1.00000, 0.00000, }, + {0.62500, 0.37500, }, + {0.50000, 0.75000, 0.75000, 0.00000, }, + {0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 1.00000, 1.00000, 0.00000, }, }; double pfnc[][16] = { -{0.50000, 0.50000, }, -{0.62500, 0.62500, 0.37500, 0.37500, }, -{0.75000, 0.50000, 0.25000, 0.75000, 0.50000, 0.75000, 0.50000, 0.00000, }, -{1.00000, 1.00000, 0.50000, 0.50000, 0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 0.00000, 0.00000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, }, + {0.50000, 0.50000, }, + {0.62500, 0.62500, 0.37500, 0.37500, }, + {0.75000, 0.50000, 0.25000, 0.75000, 0.50000, 0.75000, 0.50000, 0.00000, }, + {1.00000, 1.00000, 0.50000, 0.50000, 0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 0.00000, 0.00000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, }, }; /* hitag2_crypt works on the post-shifted form of the lfsr; this is the ref in rfidler code */ -static uint32_t hitag2_crypt(uint64_t s) -{ +static uint32_t hitag2_crypt(uint64_t s) { uint32_t bitindex; - bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1; - bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02; - bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04; - bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08; + bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08; bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; return (ht2_function5c >> bitindex) & 1; } /* ht2crypt works on the pre-shifted form of the lfsr; this is the ref in the paper */ -uint64_t ht2crypt(uint64_t s) -{ +uint64_t ht2crypt(uint64_t s) { uint64_t bitindex; - bitindex = (ht2_function4a >> pickbits2_2 (s, 2, 5)) & 1; - bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 8, 12, 14)) & 0x02; - bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 17, 21, 23, 26)) & 0x04; - bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 28, 31, 33)) & 0x08; + bitindex = (ht2_function4a >> pickbits2_2(s, 2, 5)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 8, 12, 14)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 17, 21, 23, 26)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 28, 31, 33)) & 0x08; bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 34, 43, 46)) & 0x10; return (ht2_function5c >> bitindex) & 1; @@ -177,11 +174,10 @@ uint64_t ht2crypt(uint64_t s) /* fnL is the feedback function for the reference code */ -uint64_t fnL(uint64_t x) -{ +uint64_t fnL(uint64_t x) { return (bitn(x, 0) ^ bitn(x, 2) ^ bitn(x, 3) ^ bitn(x, 6) ^ bitn(x, 7) ^ bitn(x, 8) ^ - bitn(x, 16) ^ bitn(x, 22) ^ bitn(x, 23) ^ bitn(x, 26) ^ bitn(x, 30) ^ bitn(x, 41) ^ - bitn(x, 42) ^ bitn(x, 43) ^ bitn(x, 46) ^ bitn(x, 47)); + bitn(x, 16) ^ bitn(x, 22) ^ bitn(x, 23) ^ bitn(x, 26) ^ bitn(x, 30) ^ bitn(x, 41) ^ + bitn(x, 42) ^ bitn(x, 43) ^ bitn(x, 46) ^ bitn(x, 47)); } @@ -189,18 +185,18 @@ uint64_t fnL(uint64_t x) * the number of relevant bits. * e.g. if there are 16 confirmed bits in a state, then packed_size[16] = 8 relevant bits. * this is for pre-shifted lfsr */ -unsigned int packed_size[] = { 0, 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, +unsigned int packed_size[] = { 0, 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 14, 14, 15, - 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 20, 20 }; + 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 20, 20 + }; /* f20 is the same as hitag2_crypt except it works on the packed version * of the state where all 20 relevant bits are squashed together */ -uint64_t f20(uint64_t y) -{ +uint64_t f20(uint64_t y) { uint64_t bitindex; - bitindex = (ht2_function4a >> (y & 0xf)) & 1; + bitindex = (ht2_function4a >> (y & 0xf)) & 1; bitindex |= ((ht2_function4b << 1) >> ((y >> 4) & 0xf)) & 0x02; bitindex |= ((ht2_function4b << 2) >> ((y >> 8) & 0xf)) & 0x04; bitindex |= ((ht2_function4b << 3) >> ((y >> 12) & 0xf)) & 0x08; @@ -211,14 +207,13 @@ uint64_t f20(uint64_t y) /* packstate packs the relevant bits from LFSR state into 20 bits for pre-shifted lfsr */ -uint64_t packstate(uint64_t s) -{ +uint64_t packstate(uint64_t s) { uint64_t packed; - packed = pickbits2_2 (s, 2, 5); - packed |= (pickbits1_1_2 (s, 8, 12, 14) << 4); - packed |= (pickbits1x4 (s, 17, 21, 23, 26) << 8); - packed |= (pickbits2_1_1 (s, 28, 31, 33) << 12); + packed = pickbits2_2(s, 2, 5); + packed |= (pickbits1_1_2(s, 8, 12, 14) << 4); + packed |= (pickbits1x4(s, 17, 21, 23, 26) << 8); + packed |= (pickbits2_1_1(s, 28, 31, 33) << 12); packed |= (pickbits1_2_1(s, 34, 43, 46) << 16); return packed; @@ -226,8 +221,7 @@ uint64_t packstate(uint64_t s) /* create_guess_table mallocs the tables */ -void create_guess_table() -{ +void create_guess_table() { guesses = (struct guess *)malloc(sizeof(struct guess) * maxtablesize); if (!guesses) { printf("cannot malloc guess table\n"); @@ -238,8 +232,7 @@ void create_guess_table() /* init the guess table by reading in the encrypted nR,aR values and * setting the first 2^16 key guesses */ -void init_guess_table(char *filename, char *uidstr) -{ +void init_guess_table(char *filename, char *uidstr) { unsigned int i, j; FILE *fp; char *buf = NULL; @@ -289,8 +282,8 @@ void init_guess_table(char *filename, char *uidstr) } *buft2 = 0x00; if (!strncmp(buf, "0x", 2)) { - nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf+2)); - nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1+2)) ^ 0xffffffff; + nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf + 2)); + nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1 + 2)) ^ 0xffffffff; } else { nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf)); nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1)) ^ 0xffffffff; @@ -303,12 +296,12 @@ void init_guess_table(char *filename, char *uidstr) fprintf(stderr, "Loaded %d nRaR pairs\n", num_nRaR); - // set key and copy in enc_nR and ks values + // set key and copy in enc_nR and ks values // set score to -1.0 to distinguish them from 0 scores - for (i=0; i<65536; i++) { + for (i = 0; i < 65536; i++) { guesses[i].key = i; guesses[i].score = -1.0; - for (j=0; j> (packed & 0xf)) & 1; + fncinput = (ht2_function4a >> (packed & 0xf)) & 1; fncinput |= ((ht2_function4b << 1) >> ((packed >> 4) & 0xf)) & 0x02; fncinput |= ((ht2_function4b << 2) >> ((packed >> 8) & 0xf)) & 0x04; fncinput |= ((ht2_function4b << 3) >> ((packed >> 12) & 0xf)) & 0x08; @@ -404,8 +396,7 @@ double bit_score(uint64_t s, uint64_t size, uint64_t b) * bit_scores together until no bits remain. bit_scores are * multiplied by the number of relevant bits in the scored state * to give weight to more complete states. */ -double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize) -{ +double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize) { double sc, sc2; if ((size == 1) || (kssize == 1)) { @@ -436,8 +427,7 @@ double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize) /* score_traces runs score for each encrypted nonce */ -void score_traces(struct guess *g, unsigned int size) -{ +void score_traces(struct guess *g, unsigned int size) { uint64_t lfsr; unsigned int i; double sc; @@ -448,13 +438,13 @@ void score_traces(struct guess *g, unsigned int size) return; } - for (i=0; i> (size - 16)) | ((g->key << (48 - size)) ^ - ((nonces[i].enc_nR ^ g->b0to31[i]) << (64 - size))); + ((nonces[i].enc_nR ^ g->b0to31[i]) << (64 - size))); g->b0to31[i] = g->b0to31[i] | (ht2crypt(lfsr) << (size - 16)); // create lfsr - lower 16 bits are lower 16 bits of key @@ -491,12 +481,11 @@ void score_all_traces(unsigned int size) */ /* score_some_traces runs score_traces for every key guess in a section of the table */ -void *score_some_traces(void *data) -{ +void *score_some_traces(void *data) { unsigned int i; struct thread_data *tdata = (struct thread_data *)data; - for (i=tdata->start; iend; i++) { + for (i = tdata->start; i < tdata->end; i++) { score_traces(&(guesses[i]), tdata->size); } @@ -505,8 +494,7 @@ void *score_some_traces(void *data) /* score_all_traces runs score_traces for every key guess in the table */ -void score_all_traces(unsigned int size) -{ +void score_all_traces(unsigned int size) { pthread_t threads[NUM_THREADS]; void *status; struct thread_data tdata[NUM_THREADS]; @@ -516,9 +504,9 @@ void score_all_traces(unsigned int size) chunk_size = num_guesses / NUM_THREADS; // create thread data - for (i=0; i> 1) | (hitag2_nstep(&hstate, 1) << 31); } printf("ks = 0x%08" PRIx64 ", enc_aR = 0x%08" PRIx64 ", aR = 0x%08" PRIx64 "\n", b0to31, nonces[0].ks ^ 0xffffffff, nonces[0].ks ^ 0xffffffff ^ b0to31); @@ -679,7 +661,7 @@ void testkey(uint64_t key) // xor upper part of key with encrypted nonce nRxorkey = nonces[0].enc_nR ^ (key >> 16); // insert keyupper xor encrypted nonce xor ks - for (i=0; i<32; i++) { + for (i = 0; i < 32; i++) { // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31 b0to31 = (b0to31 >> 1) | (ht2crypt(lfsr) << 31); // insert new bit @@ -693,7 +675,7 @@ void testkey(uint64_t key) printf("\n"); // iterate lfsr with fnL, extracting ks - for (i=0; i<32; i++) { + for (i = 0; i < 32; i++) { // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31 ks = (ks >> 1) | (ht2crypt(lfsr) << 31); // insert new bit @@ -710,38 +692,37 @@ void testkey(uint64_t key) /* test function to generate test data */ -void gen_bitstreams_testks(struct guess *g, uint64_t key) -{ - unsigned int i, j; - uint64_t nRxorkey, lfsr, ks; +void gen_bitstreams_testks(struct guess *g, uint64_t key) { + unsigned int i, j; + uint64_t nRxorkey, lfsr, ks; - for (j=0; jb0to31[j] = 0; - // xor upper part of key with encrypted nonce - nRxorkey = nonces[j].enc_nR ^ (key >> 16); - // insert keyupper xor encrypted nonce xor ks - for (i=0; i<32; i++) { - // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31 - g->b0to31[j] = (g->b0to31[j] >> 1) | (ht2crypt(lfsr) << 31); - // insert new bit - lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((g->b0to31[j] >> 31) & 0x1)) << 48); - // shift lfsr - lfsr = lfsr >> 1; - } + // build initial lfsr + lfsr = uid | ((key & 0xffff) << 32); + g->b0to31[j] = 0; + // xor upper part of key with encrypted nonce + nRxorkey = nonces[j].enc_nR ^ (key >> 16); + // insert keyupper xor encrypted nonce xor ks + for (i = 0; i < 32; i++) { + // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31 + g->b0to31[j] = (g->b0to31[j] >> 1) | (ht2crypt(lfsr) << 31); + // insert new bit + lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((g->b0to31[j] >> 31) & 0x1)) << 48); + // shift lfsr + lfsr = lfsr >> 1; + } ks = 0; - // iterate lfsr with fnL, extracting ks - for (i=0; i<32; i++) { - // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31 - ks = (ks >> 1) | (ht2crypt(lfsr) << 31); - // insert new bit - lfsr = lfsr | (fnL(lfsr) << 48); - // shift lfsr - lfsr = lfsr >> 1; - } + // iterate lfsr with fnL, extracting ks + for (i = 0; i < 32; i++) { + // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31 + ks = (ks >> 1) | (ht2crypt(lfsr) << 31); + // insert new bit + lfsr = lfsr | (fnL(lfsr) << 48); + // shift lfsr + lfsr = lfsr >> 1; + } printf("orig ks = 0x%08" PRIx64 ", gen ks = 0x%08" PRIx64 ", b0to31 = 0x%08" PRIx64 "\n", nonces[j].ks, ks, g->b0to31[j]); if (nonces[j].ks != ks) { @@ -752,15 +733,14 @@ void gen_bitstreams_testks(struct guess *g, uint64_t key) /* test function */ -void test() -{ +void test() { uint64_t lfsr; uint64_t packed; uint64_t i; - for (i=0; i<1000; i++) { + for (i = 0; i < 1000; i++) { lfsr = ((uint64_t)rand() << 32) | rand(); packed = packstate(lfsr); @@ -774,15 +754,14 @@ void test() /* check_key tests the potential key against an encrypted nonce, ks pair */ -int check_key(uint64_t key, uint64_t enc_nR, uint64_t ks) -{ +int check_key(uint64_t key, uint64_t enc_nR, uint64_t ks) { Hitag_State hstate; uint64_t bits; int i; hitag2_init(&hstate, key, uid, enc_nR); bits = 0; - for (i=0; i<32; i++) { + for (i = 0; i < 32; i++) { bits = (bits >> 1) | (hitag2_nstep(&hstate, 1) << 31); } if (ks == bits) { @@ -794,8 +773,7 @@ int check_key(uint64_t key, uint64_t enc_nR, uint64_t ks) /* start up */ -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { unsigned int i; uint64_t revkey; uint64_t foundkey; @@ -808,7 +786,7 @@ int main(int argc, char *argv[]) // exit(0); while ((c = getopt(argc, argv, "u:n:N:t:T:h")) != -1) { - switch(c) { + switch (c) { case 'u': uidstr = optarg; break; @@ -848,7 +826,7 @@ int main(int argc, char *argv[]) crack(); // test all key guesses and stop if one works - for (i=0; i Date: Mon, 9 Mar 2020 16:54:42 +0100 Subject: [PATCH 078/298] style --- include/protocols.h | 4 ++-- tools/fpga_compress/Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/protocols.h b/include/protocols.h index e992a97ee..de38e1aea 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -312,7 +312,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define PROTO_HITAG1 10 #define THINFILM 11 #define LTO 12 -#define PROTO_HITAG2 13 +#define PROTO_HITAG2 13 #define PROTO_HITAGS 14 //-- Picopass fuses @@ -599,7 +599,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define HITAG2_READ_PAGE 0x3 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits #define HITAG2_READ_PAGE_INVERTED 0x1 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits -#define HITAG2_WRITE_PAGE 0x2 // page number in bits 5 to 3, page number +#define HITAG2_WRITE_PAGE 0x2 // page number in bits 5 to 3, page number // HITAG S commands diff --git a/tools/fpga_compress/Makefile b/tools/fpga_compress/Makefile index 47f3c278c..5452f9083 100644 --- a/tools/fpga_compress/Makefile +++ b/tools/fpga_compress/Makefile @@ -22,4 +22,4 @@ $(OBJDIR)/libz.a: tarbin: $(BINS) $(info [=] TAR ../proxmark3-$(platform)-bin.tar) - $(Q)$(TAR) $(TARFLAGS) ../../proxmark3-$(platform)-bin.tar $(BINS:%=fpga_compress/%) $(WINBINS:%=fpga_compress/%) \ No newline at end of file + $(Q)$(TAR) $(TARFLAGS) ../../proxmark3-$(platform)-bin.tar $(BINS:%=fpga_compress/%) $(WINBINS:%=fpga_compress/%) From 59bae5000c582778707b04d2bce20707537014d9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 16:57:13 +0100 Subject: [PATCH 079/298] style --- armsrc/Standalone/hf_14asniff.c | 6 +-- armsrc/Standalone/lf_icehid.c | 72 ++++++++++++++++----------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/armsrc/Standalone/hf_14asniff.c b/armsrc/Standalone/hf_14asniff.c index d8bf6ab82..706a41b8b 100644 --- a/armsrc/Standalone/hf_14asniff.c +++ b/armsrc/Standalone/hf_14asniff.c @@ -45,7 +45,7 @@ * This module emits debug strings during normal operation -- so try it out in * the lab connected to PM3 client before taking it into the field. * - * To delete the trace data from flash: + * To delete the trace data from flash: * * Caveats / notes: * - Trace buffer will be cleared on starting stand-alone mode. Data in flash @@ -97,7 +97,7 @@ void RunMod() { if (trace_len > 0) { Dbprintf("[!] Trace length (bytes) = %u", trace_len); - uint8_t* trace_buffer = BigBuf_get_addr(); + uint8_t *trace_buffer = BigBuf_get_addr(); if (!exists_in_spiffs(HF_14ASNIFF_LOGFILE)) { rdv40_spiffs_write( HF_14ASNIFF_LOGFILE, trace_buffer, trace_len, RDV40_SPIFFS_SAFETY_SAFE); @@ -117,7 +117,7 @@ void RunMod() { SpinErr(LED_A, 200, 5); SpinDelay(100); - + LEDsoff(); SpinDelay(300); DownloadTraceInstructions(); diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index 77f04024e..d66186c9d 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -63,7 +63,7 @@ void DownloadLogInstructions() { bool log_exists; -void append(uint8_t* entry, size_t entry_len) { +void append(uint8_t *entry, size_t entry_len) { LED_B_ON(); if (log_exists == false) { @@ -106,22 +106,22 @@ uint32_t IceEM410xdemod() { if (size == 128) { sprintf((char *)entry, "EM XL TAG ID: %06lx%08lx%08lx - (%05ld_%03ld_%08ld)\n", - hi, - (uint32_t)(lo >> 32), - (uint32_t)lo, - (uint32_t)(lo & 0xFFFF), - (uint32_t)((lo >> 16LL) & 0xFF), - (uint32_t)(lo & 0xFFFFFF)); + hi, + (uint32_t)(lo >> 32), + (uint32_t)lo, + (uint32_t)(lo & 0xFFFF), + (uint32_t)((lo >> 16LL) & 0xFF), + (uint32_t)(lo & 0xFFFFFF)); } else { sprintf((char *)entry, "EM TAG ID: %02lx%08lx - (%05ld_%03ld_%08ld)\n", - (uint32_t)(lo >> 32), - (uint32_t)lo, - (uint32_t)(lo & 0xFFFF), - (uint32_t)((lo >> 16LL) & 0xFF), - (uint32_t)(lo & 0xFFFFFF)); + (uint32_t)(lo >> 32), + (uint32_t)lo, + (uint32_t)(lo & 0xFFFF), + (uint32_t)((lo >> 16LL) & 0xFF), + (uint32_t)(lo & 0xFFFFFF)); } - append(entry, strlen((char*)entry)); + append(entry, strlen((char *)entry)); Dbprintf("%s", entry); BigBuf_free(); return PM3_SUCCESS; @@ -173,7 +173,7 @@ uint32_t IceAWIDdemod() { } } - append(entry, strlen((char*)entry)); + append(entry, strlen((char *)entry)); Dbprintf("%s", entry); BigBuf_free(); return PM3_SUCCESS; @@ -210,14 +210,14 @@ uint32_t IceIOdemod() { memset(entry, 0, sizeof(entry)); sprintf((char *)entry, "IO Prox XSF(%02d)%02x:%05d (%08lx%08lx)\n" - , version - , facilitycode - , number - , hi - , lo - ); + , version + , facilitycode + , number + , hi + , lo + ); - append(entry, strlen((char*)entry)); + append(entry, strlen((char *)entry)); Dbprintf("%s", entry); BigBuf_free(); return PM3_SUCCESS; @@ -250,13 +250,13 @@ uint32_t IceHIDDemod() { if (hi2 != 0) { //extra large HID tags 88/192 bits sprintf((char *)entry, "HID large: %lx%08lx%08lx (%ld)\n", - hi2, - hi, - lo, - (lo >> 1) & 0xFFFF - ); + hi2, + hi, + lo, + (lo >> 1) & 0xFFFF + ); - append(entry, strlen((char*)entry)); + append(entry, strlen((char *)entry)); } else { //standard HID tags 44/96 bits uint8_t bitlen = 0; @@ -297,15 +297,15 @@ uint32_t IceHIDDemod() { } sprintf((char *)entry, "HID: %lx%08lx (%ld) Format: %d bit FC: %ld Card: %ld\n", - hi, - lo, - (lo >> 1) & 0xFFFF, - bitlen, - fac, - cardnum - ); + hi, + lo, + (lo >> 1) & 0xFFFF, + bitlen, + fac, + cardnum + ); - append(entry, strlen((char*)entry)); + append(entry, strlen((char *)entry)); } Dbprintf("%s", entry); @@ -349,7 +349,7 @@ void RunMod() { uint32_t res; - // since we steal 12800 from bigbuffer, no need to sample it. + // since we steal 12800 from bigbuffer, no need to sample it. DoAcquisition_config(false, 28000); res = IceHIDDemod(); if (res == PM3_SUCCESS) { From e1490f62240c113aa7e391161de5299902ee252c Mon Sep 17 00:00:00 2001 From: bosb <12600404+bosb@users.noreply.github.com> Date: Mon, 9 Mar 2020 17:02:03 +0100 Subject: [PATCH 080/298] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index af8b073ca..afa16fec6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -420,6 +420,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `hf mf mad` and `hf mfp mad` MAD decode, check and print commands (@merlokk) - Added `script run luxeodump` (@0xdrrb) - Fix `lf hitag reader 02` - print all bytes (@bosb) + - Fix hitag S simulation (still not working), write, add example HITAG S 256 (@bosb) ### Fixed From c28a71b58688683999e1ce0cd82c4e6a8340ca5e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 17:07:25 +0100 Subject: [PATCH 081/298] header --- client/cmdlfindala.h | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdlfindala.h b/client/cmdlfindala.h index 830017117..1d0762f5f 100644 --- a/client/cmdlfindala.h +++ b/client/cmdlfindala.h @@ -19,5 +19,6 @@ int detectIndala26(uint8_t *bitStream, size_t *size, uint8_t *invert); int detectIndala64(uint8_t *bitStream, size_t *size, uint8_t *invert); int detectIndala224(uint8_t *bitStream, size_t *size, uint8_t *invert); int demodIndala(void); +int getIndalaBits(uint8_t fc, uint16_t csn, uint8_t *bits); #endif From 9a921d6944cb5485c20ed40dab47bac37b571032 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 17:09:07 +0100 Subject: [PATCH 082/298] style --- common/lfdemod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 4dcd46172..bc753f45d 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -206,7 +206,7 @@ void getHiLo(int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) { *low = signalprop.low; } - // prnt("getHiLo fuzzed: High %d | Low %d", *high, *low); + // prnt("getHiLo fuzzed: High %d | Low %d", *high, *low); } // by marshmellow From cef1f21a34bd6855b5b4b6d5e93154a37d45c83a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 17:09:41 +0100 Subject: [PATCH 083/298] style --- common/cardhelper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/cardhelper.c b/common/cardhelper.c index 93e361f60..5cebf4322 100644 --- a/common/cardhelper.c +++ b/common/cardhelper.c @@ -29,7 +29,7 @@ bool IsCryptoHelperPresent(void) { uint8_t resp[20] = {0}; ExchangeAPDUSC(true, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len); - if (strstr("CryptoHelper", (char*)resp) == 0) { + if (strstr("CryptoHelper", (char *)resp) == 0) { PrintAndLogEx(INFO, "Found smart card helper"); return true; } else { @@ -56,11 +56,11 @@ static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) { return false; } -bool Decrypt(uint8_t *src, uint8_t *dest){ +bool Decrypt(uint8_t *src, uint8_t *dest) { return executeCrypto(CARD_INS_DECRYPT, src, dest); } -bool Encrypt(uint8_t *src, uint8_t *dest){ +bool Encrypt(uint8_t *src, uint8_t *dest) { return executeCrypto(CARD_INS_ENCRYPT, src, dest); } From a751684a31c6b457a536023bf2a8a7d5c087d6e1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 17:11:11 +0100 Subject: [PATCH 084/298] style --- armsrc/appmain.c | 8 +++--- armsrc/mifarecmd.c | 62 +++++++++++++++++++++++----------------------- armsrc/mifaresim.c | 4 +-- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 5464d7ddb..5bec32364 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -549,7 +549,7 @@ void ListenReaderField(uint8_t limit) { // iceman, useless, since we are measuring readerfield, not our field. My tests shows a max of 20v from a reader. hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40); #else - hf_av = hf_max = AvgAdc(ADC_CHAN_HF); + hf_av = hf_max = AvgAdc(ADC_CHAN_HF); #endif Dbprintf("HF 13.56MHz Baseline: %dmV", (MAX_ADC_HF_VOLTAGE * hf_av) >> 10); hf_baseline = hf_av; @@ -1248,7 +1248,7 @@ static void PacketReceived(PacketCommandNG *packet) { // SniffMifare(packet->oldarg[0]); // break; // } - case CMD_HF_MIFARE_PERSONALIZE_UID: { + case CMD_HF_MIFARE_PERSONALIZE_UID: { struct p { uint8_t keytype; uint8_t pers_option; @@ -1256,8 +1256,8 @@ static void PacketReceived(PacketCommandNG *packet) { } PACKED; struct p *payload = (struct p *) packet->data.asBytes; uint64_t authkey = bytes_to_num(payload->key, 6); - MifarePersonalizeUID(payload->keytype, payload->pers_option, authkey); - break; + MifarePersonalizeUID(payload->keytype, payload->pers_option, authkey); + break; } case CMD_HF_MIFARE_SETMOD: { MifareSetMod(packet->data.asBytes); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 3669e13ea..0136ed6c9 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1811,54 +1811,54 @@ void MifareChkKeys_file(uint8_t *fn) { void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key) { uint16_t isOK = PM3_EUNDEF; - uint8_t uid[10]; - uint32_t cuid; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; + uint8_t uid[10]; + uint32_t cuid; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); set_tracing(true); - - LED_A_ON(); - while (true) { - if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); - break; - } + LED_A_ON(); - uint8_t block_number = 0; - if (mifare_classic_auth(pcs, cuid, block_number, keyType, key, AUTH_FIRST)) { - if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error"); - break; - } + while (true) { + if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); + break; + } - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - int len = mifare_sendcmd_short(pcs, true, MIFARE_EV1_PERSONAL_UID, perso_option, receivedAnswer, receivedAnswerPar, NULL); - if (len != 1 || receivedAnswer[0] != CARD_ACK) { - if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - break;; - } + uint8_t block_number = 0; + if (mifare_classic_auth(pcs, cuid, block_number, keyType, key, AUTH_FIRST)) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error"); + break; + } + + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + int len = mifare_sendcmd_short(pcs, true, MIFARE_EV1_PERSONAL_UID, perso_option, receivedAnswer, receivedAnswerPar, NULL); + if (len != 1 || receivedAnswer[0] != CARD_ACK) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + break;; + } if (mifare_classic_halt(pcs, cuid)) { if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error"); break; } - isOK = PM3_SUCCESS; - break; - } + isOK = PM3_SUCCESS; + break; + } - crypto1_deinit(pcs); + crypto1_deinit(pcs); LED_B_ON(); reply_ng(CMD_HF_MIFARE_PERSONALIZE_UID, isOK, NULL, 0); LED_B_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 0dcbe404a..0fbfecb85 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -537,13 +537,13 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 // find reader field if (cardSTATE == MFEMUL_NOFIELD) { - + #if defined RDV4 vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; #else vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; #endif - + if (vHf > MF_MINFIELDV) { cardSTATE_TO_IDLE(); LED_A_ON(); From c27d84b06c85b663f910eb85ebec1a073bd6710e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 9 Mar 2020 19:00:27 +0100 Subject: [PATCH 085/298] text --- client/cmdlfindala.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 08b869378..8cfdfebd3 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -561,8 +561,8 @@ static int CmdIndalaClone(const char *Cmd) { CLIParserInit("lf indala clone", "clone INDALA tag to T55x7 (or to q5/T5555)", "Examples:\n" - "\tlf indala clone -c 888\n" - "\tlf indala clone -fc 123 -csn 1337\n" + "\tlf indala clone --heden 888\n" + "\tlf indala clone --fc 123 --cn 1337\n" "\tlf indala clone -r a0000000a0002021\n" "\tlf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"); @@ -732,9 +732,19 @@ int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits) { // checksum // ICEMAN: todo: needs to calc - uint8_t chk = 3; - bits[62] = ((chk >> 1) & 1); // b2 - bits[63] = (chk & 1); // b1 + uint8_t chk = 0; + //sum(y2, y4, y7, y8, y10, y11, y14, y16 + chk += 0; //y == 75 + + if ((chk & 1) == 0) { + bits[62] = 1; + bits[63] = 0; + } else { + bits[62] = 0; + bits[63] = 1; + } + // 92 = 62 + // 93 = 63 return PM3_SUCCESS; } From 8b1482d72d10985bc4b3eb149a93bd9acef081ac Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Mar 2020 10:26:33 +0100 Subject: [PATCH 086/298] fix: hf 14a sim x - above 16 sectors.. --- client/cmdhfmf.c | 124 +++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 6a57491fc..77278ee9a 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3129,7 +3129,7 @@ out: } sector_t *k_sector = NULL; -uint8_t k_sectorsCount = 16; +uint8_t k_sectorsCount = 40; void showSectorTable() { if (k_sector != NULL) { @@ -4800,72 +4800,72 @@ static int CmdHFMFNDEF(const char *Cmd) { int CmdHFMFPersonalize(const char *cmd) { - CLIParserInit("hf mf personalize", - "Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.", - "Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n" - "\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n" - "\thf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n" - "\thf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n" - "\thf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A\n"); + CLIParserInit("hf mf personalize", + "Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.", + "Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n" + "\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n" + "\thf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n" + "\thf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n" + "\thf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A\n"); - void *argtable[] = { - arg_param_begin, - arg_str0("tT", "keytype", "", "key type (A or B) to authenticate sector 0 (default: A)"), - arg_str0("kK", "key", "", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"), - arg_str1(NULL, NULL, "", "Personalization Option"), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void *argtable[] = { + arg_param_begin, + arg_str0("tT", "keytype", "", "key type (A or B) to authenticate sector 0 (default: A)"), + arg_str0("kK", "key", "", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"), + arg_str1(NULL, NULL, "", "Personalization Option"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - char keytypestr[2] = "a"; - uint8_t keytype = 0x00; - int keytypestr_len; - int res = CLIParamStrToBuf(arg_get_str(1), (uint8_t*)keytypestr, 1, &keytypestr_len); + char keytypestr[2] = "a"; + uint8_t keytype = 0x00; + int keytypestr_len; + int res = CLIParamStrToBuf(arg_get_str(1), (uint8_t *)keytypestr, 1, &keytypestr_len); str_lower(keytypestr); - - if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'b')) { - PrintAndLogEx(ERR, "ERROR: not a valid key type. Key type must be A or B"); - CLIParserFree(); - return PM3_EINVARG; - } - if (keytypestr[0] == 'b') { - keytype = 0x01; - } - uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - int key_len; - res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len); - if (res || (!res && key_len > 0 && key_len != 6)) { - PrintAndLogEx(ERR, "ERROR: not a valid key. Key must be 12 hex digits"); - CLIParserFree(); - return PM3_EINVARG; - } + if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'b')) { + PrintAndLogEx(ERR, "ERROR: not a valid key type. Key type must be A or B"); + CLIParserFree(); + return PM3_EINVARG; + } + if (keytypestr[0] == 'b') { + keytype = 0x01; + } - char pers_optionstr[6]; - int opt_len; - uint8_t pers_option; - res = CLIParamStrToBuf(arg_get_str(3), (uint8_t*)pers_optionstr, 5, &opt_len); + uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + int key_len; + res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len); + if (res || (!res && key_len > 0 && key_len != 6)) { + PrintAndLogEx(ERR, "ERROR: not a valid key. Key must be 12 hex digits"); + CLIParserFree(); + return PM3_EINVARG; + } + + char pers_optionstr[6]; + int opt_len; + uint8_t pers_option; + res = CLIParamStrToBuf(arg_get_str(3), (uint8_t *)pers_optionstr, 5, &opt_len); str_lower(pers_optionstr); - if (res || (!res && opt_len > 0 && opt_len != 5) - || (strncmp(pers_optionstr, "uidf0", 5) && strncmp(pers_optionstr, "uidf1", 5) && strncmp(pers_optionstr, "uidf2", 5) && strncmp(pers_optionstr, "uidf3", 5))) { - PrintAndLogEx(ERR, "ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3"); - CLIParserFree(); - return PM3_EINVARG; - } - if (!strncmp(pers_optionstr, "uidf0", 5)) { - pers_option = MIFARE_EV1_UIDF0; - } else if (!strncmp(pers_optionstr, "uidf1", 5)) { - pers_option = MIFARE_EV1_UIDF1; - } else if (!strncmp(pers_optionstr, "uidf2", 5)) { - pers_option = MIFARE_EV1_UIDF2; - } else { - pers_option = MIFARE_EV1_UIDF3; - } + if (res || (!res && opt_len > 0 && opt_len != 5) + || (strncmp(pers_optionstr, "uidf0", 5) && strncmp(pers_optionstr, "uidf1", 5) && strncmp(pers_optionstr, "uidf2", 5) && strncmp(pers_optionstr, "uidf3", 5))) { + PrintAndLogEx(ERR, "ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3"); + CLIParserFree(); + return PM3_EINVARG; + } + if (!strncmp(pers_optionstr, "uidf0", 5)) { + pers_option = MIFARE_EV1_UIDF0; + } else if (!strncmp(pers_optionstr, "uidf1", 5)) { + pers_option = MIFARE_EV1_UIDF1; + } else if (!strncmp(pers_optionstr, "uidf2", 5)) { + pers_option = MIFARE_EV1_UIDF2; + } else { + pers_option = MIFARE_EV1_UIDF3; + } - CLIParserFree(); + CLIParserFree(); - clearCommandBuffer(); + clearCommandBuffer(); struct { uint8_t keytype; @@ -4875,16 +4875,16 @@ int CmdHFMFPersonalize(const char *cmd) { payload.keytype = keytype; payload.pers_option = pers_option; - memcpy(payload.key, key, 6); + memcpy(payload.key, key, 6); SendCommandNG(CMD_HF_MIFARE_PERSONALIZE_UID, (uint8_t *)&payload, sizeof(payload)); - PacketResponseNG resp; + PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_HF_MIFARE_PERSONALIZE_UID, &resp, 2500)) return PM3_ETIMEOUT; PrintAndLogEx(SUCCESS, "Personalization %s", resp.status == PM3_SUCCESS ? "SUCCEEDED" : "FAILED"); - return PM3_SUCCESS; + return PM3_SUCCESS; } static int CmdHF14AMfList(const char *Cmd) { @@ -4934,7 +4934,7 @@ static command_t CommandTable[] = { {"-----------", CmdHelp, IfPm3Iso14443a, ""}, {"mad", CmdHF14AMfMAD, IfPm3Iso14443a, "Checks and prints MAD"}, {"ndef", CmdHFMFNDEF, IfPm3Iso14443a, "Prints NDEF records from card"}, - {"personalize", CmdHFMFPersonalize, IfPm3Iso14443a, "Personalize UID (Mifare Classic EV1 only)"}, + {"personalize", CmdHFMFPersonalize, IfPm3Iso14443a, "Personalize UID (Mifare Classic EV1 only)"}, {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, {NULL, NULL, NULL, NULL} }; From e749174d79174f81cf70aebedb38cb4dfc36e658 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Mar 2020 10:41:16 +0100 Subject: [PATCH 087/298] text --- client/cmdlf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 7fa73818d..29854c6b6 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -1351,7 +1351,7 @@ static command_t CommandTable[] = { {"fdx", CmdLFFdx, AlwaysAvailable, "{ FDX-B RFIDs... }"}, {"gallagher", CmdLFGallagher, AlwaysAvailable, "{ GALLAGHER RFIDs... }"}, {"gproxii", CmdLFGuard, AlwaysAvailable, "{ Guardall Prox II RFIDs... }"}, - {"hid", CmdLFHID, AlwaysAvailable, "{ HID RFIDs... }"}, + {"hid", CmdLFHID, AlwaysAvailable, "{ HID Prox RFIDs... }"}, {"hitag", CmdLFHitag, AlwaysAvailable, "{ Hitag CHIPs... }"}, {"indala", CmdLFINDALA, AlwaysAvailable, "{ Indala RFIDs... }"}, {"io", CmdLFIO, AlwaysAvailable, "{ ioProx RFIDs... }"}, From 66d3abafb2e3f41ba99c84fb68c8528f59e48d3a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Mar 2020 10:45:01 +0100 Subject: [PATCH 088/298] chg: checksum test --- client/cmdlfindala.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 8cfdfebd3..52640fb9f 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -714,27 +714,33 @@ int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits) { // add cn bits[42] = ((cn >> 15) & 1); // b16 - bits[45] = ((cn >> 14) & 1); // b15 + bits[45] = ((cn >> 14) & 1); // b15 - c bits[43] = ((cn >> 13) & 1); // b14 - bits[40] = ((cn >> 12) & 1); // b13 + bits[40] = ((cn >> 12) & 1); // b13 - c bits[52] = ((cn >> 11) & 1); // b12 bits[36] = ((cn >> 10) & 1); // b11 - bits[35] = ((cn >> 9) & 1); // b10 - bits[51] = ((cn >> 8) & 1); // b9 + bits[35] = ((cn >> 9) & 1); // b10 - c + bits[51] = ((cn >> 8) & 1); // b9 - c bits[46] = ((cn >> 7) & 1); // b8 - bits[33] = ((cn >> 6) & 1); // b7 - bits[37] = ((cn >> 5) & 1); // b6 + bits[33] = ((cn >> 6) & 1); // b7 - c + bits[37] = ((cn >> 5) & 1); // b6 - c bits[54] = ((cn >> 4) & 1); // b5 bits[56] = ((cn >> 3) & 1); // b4 - bits[59] = ((cn >> 2) & 1); // b3 + bits[59] = ((cn >> 2) & 1); // b3 - c bits[50] = ((cn >> 1) & 1); // b2 - bits[41] = (cn & 1); // b1 + bits[41] = (cn & 1); // b1 - c // checksum - // ICEMAN: todo: needs to calc uint8_t chk = 0; //sum(y2, y4, y7, y8, y10, y11, y14, y16 - chk += 0; //y == 75 + chk += ((cn >> 14) & 1); //y2 == 75 - 30 = 45 + chk += ((cn >> 12) & 1); //y4 == 70 - 30 = 40 + chk += ((cn >> 9) & 1); //y7 == 65 - 30 = 35 + chk += ((cn >> 8) & 1); //y8 == 81 - 30 = 51 + chk += ((cn >> 6) & 1); //y10 == 63 - 30 = 33 + chk += ((cn >> 5) & 1); //y11 == 67 - 30 = 37 + chk += ((cn >> 2) & 1); //y14 == 89 - 30 = 59 + chk += (cn & 1); //y16 == 71 - 30 = 41 if ((chk & 1) == 0) { bits[62] = 1; From f6940f1d8e8678fe68403bc7212a189780a1fc7d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Mar 2020 10:53:02 +0100 Subject: [PATCH 089/298] chg: checksum test2 --- client/cmdlfindala.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 52640fb9f..6da2aa8f2 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -741,13 +741,13 @@ int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits) { chk += ((cn >> 5) & 1); //y11 == 67 - 30 = 37 chk += ((cn >> 2) & 1); //y14 == 89 - 30 = 59 chk += (cn & 1); //y16 == 71 - 30 = 41 - + if ((chk & 1) == 0) { - bits[62] = 1; - bits[63] = 0; - } else { bits[62] = 0; bits[63] = 1; + } else { + bits[62] = 1; + bits[63] = 0; } // 92 = 62 // 93 = 63 From adee34083e1ef8a5c8430c67e569651b22736f47 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Mar 2020 17:00:59 +0100 Subject: [PATCH 090/298] whitespace --- client/flash.c | 6 +++--- client/mifare/mifarehost.c | 26 +++++++++++++------------- client/proxguiqt.cpp | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/client/flash.c b/client/flash.c index 698e39187..ad3d8fd93 100644 --- a/client/flash.c +++ b/client/flash.c @@ -529,7 +529,7 @@ const char ice[] = " !!: :!! !!: !!: !!: !!: !!! !!: !!!\n : :: :: : : :: ::: : : : : : :: : \n" _RED_(" . .. .. . . .. ... . . . . . .. . ") "\n...................................................................\n" -; + ; // Write a file's segments to Flash int flash_write(flash_file_t *ctx) { @@ -566,8 +566,8 @@ int flash_write(flash_file_t *ctx) { baddr += block_size; length -= block_size; block++; - if ( len < strlen(ice) ) { - if (filter_ansi && !isalpha(ice[len]) ) { + if (len < strlen(ice)) { + if (filter_ansi && !isalpha(ice[len])) { len++; } else { fprintf(stdout, "%c", ice[len++]); diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 388cc029e..6ab6943cf 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -546,8 +546,8 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, float bruteforce_per_second = (float)KEYS_IN_BLOCK / (msclock() - start_time) * 1000.0; - if ( i + 1 % 10 == 0) - PrintAndLogEx(INFO, " %6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt , bruteforce_per_second, (keycnt-i) / bruteforce_per_second); + if (i + 1 % 10 == 0) + PrintAndLogEx(INFO, " %6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second); } @@ -653,7 +653,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl uint32_t maxkeysinblock = IfPm3Flash() ? 1000 : KEYS_IN_BLOCK; uint32_t max_keys_chunk = keycnt > maxkeysinblock ? maxkeysinblock : keycnt; - uint8_t *mem = calloc( (maxkeysinblock * 6) + 5, sizeof(uint8_t)); + uint8_t *mem = calloc((maxkeysinblock * 6) + 5, sizeof(uint8_t)); if (mem == NULL) { free(statelists[0].head.slhead); return PM3_EMALLOC; @@ -667,7 +667,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl mem[4] = (max_keys_chunk & 0xFF); uint8_t destfn[32]; - strncpy((char*)destfn, "static_nested_000.bin", sizeof(destfn) - 1); + strncpy((char *)destfn, "static_nested_000.bin", sizeof(destfn) - 1); uint64_t start_time = msclock(); for (uint32_t i = 0; i < keycnt; i += max_keys_chunk) { @@ -691,8 +691,8 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl // check a block of generated candidate keys. if (IfPm3Flash()) { - // upload to flash. - res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6) ); + // upload to flash. + res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6)); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, "SPIFFS upload failed"); free(mem); @@ -705,13 +705,13 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl } if (res == PM3_SUCCESS) { - p_keyblock = NULL; - free(statelists[0].head.slhead); - free(mem); + p_keyblock = NULL; + free(statelists[0].head.slhead); + free(mem); - num_to_bytes(key64, 6, resultKey); + num_to_bytes(key64, 6, resultKey); - PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", package->block, package->keytype ? 'B' : 'A', sprint_hex_inrow(resultKey, 6) @@ -723,8 +723,8 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl } // if (i%10 == 0) { - float bruteforce_per_second = (float)i + max_keys_chunk / (msclock() - start_time) * 1000.0; - PrintAndLogEx(INFO, "Chunk %6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); + float bruteforce_per_second = (float)i + max_keys_chunk / (msclock() - start_time) * 1000.0; + PrintAndLogEx(INFO, "Chunk %6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second); // } } diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index a481f31d2..dc67953e6 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -199,7 +199,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { setLayout(layout); // plot window title - QString pt = QString("[*]Plot [ %1 ]").arg((char*)gui_serial_port_name); + QString pt = QString("[*]Plot [ %1 ]").arg((char *)gui_serial_port_name); setWindowTitle(pt); // shows plot window on the screen. @@ -210,7 +210,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { controlWidget->resize(size().width(), 200); // Olverlays / slider window title - QString ct = QString("[*]Slider [ %1 ]").arg((char*)gui_serial_port_name); + QString ct = QString("[*]Slider [ %1 ]").arg((char *)gui_serial_port_name); controlWidget->setWindowTitle(ct); controlWidget->show(); From 107b474b8a56380bd4fdde9ba8aeea718e6aa011 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Mar 2020 17:05:45 +0100 Subject: [PATCH 091/298] whitespace --- client/cmdhflto.c | 45 ++++++++++++++++++++++---------------------- client/cmdhfmfhard.c | 4 ++-- client/cmdlfem4x.c | 6 +++--- client/cmdlfhid.c | 14 ++++++++------ 4 files changed, 36 insertions(+), 33 deletions(-) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index 7057fab36..dfbca68c1 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -218,15 +218,15 @@ static int lto_rdbl(uint8_t blk, uint8_t *block_responce, uint8_t *block_cnt_res uint16_t resp_len = 18; uint8_t rdbl_cmd[] = {0x30, blk}; - uint8_t rdbl_cnt_cmd[] ={0x80}; + uint8_t rdbl_cnt_cmd[] = {0x80}; int status = lto_send_cmd_raw(rdbl_cmd, sizeof(rdbl_cmd), block_responce, &resp_len, true, false, verbose); - if (status == PM3_ETIMEOUT || status == PM3_ESOFT ) { + if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { return PM3_EWRONGANSVER; // READ BLOCK failed } status = lto_send_cmd_raw(rdbl_cnt_cmd, sizeof(rdbl_cnt_cmd), block_cnt_responce, &resp_len, false, false, verbose); - if (status == PM3_ETIMEOUT || status == PM3_ESOFT ) { + if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { return PM3_EWRONGANSVER; // READ BLOCK CONTINUE failed } @@ -252,7 +252,7 @@ int rdblLTO(uint8_t st_blk, uint8_t end_blk, bool verbose) { uint8_t block_data_d16_d31[18]; uint8_t block_data[32]; - for(uint8_t i = st_blk; i < end_blk + 1; i++) { + for (uint8_t i = st_blk; i < end_blk + 1; i++) { ret_val = lto_rdbl(i, block_data_d00_d15, block_data_d16_d31, verbose); @@ -286,8 +286,8 @@ static int CmdHfLTOReadBlock(const char *Cmd) { case 'h': return usage_lto_rdbl(); case 's': - st_blk = param_get8(Cmd, cmdp+1); - if ( end_blk < st_blk ) { + st_blk = param_get8(Cmd, cmdp + 1); + if (end_blk < st_blk) { errors = true; break; } @@ -295,10 +295,11 @@ static int CmdHfLTOReadBlock(const char *Cmd) { break; case 'e': - end_blk = param_get8(Cmd, cmdp+1); - if ( end_blk < st_blk ) { + end_blk = param_get8(Cmd, cmdp + 1); + if (end_blk < st_blk) { errors = true; - break; } + break; + } cmdp += 2; break; @@ -328,7 +329,7 @@ static int lto_wrbl(uint8_t blk, uint8_t *data, bool verbose) { for (int i = 0; i < 16; i++) { wrbl_d00_d15[i] = data[i]; - wrbl_d16_d31[i] = data[i+16]; + wrbl_d16_d31[i] = data[i + 16]; } int status = lto_send_cmd_raw(wrbl_cmd, sizeof(wrbl_cmd), resp, &resp_len, true, false, verbose); @@ -390,15 +391,15 @@ static int CmdHfLTOWriteBlock(const char *Cmd) { case 'h': return usage_lto_wrbl(); case 'b': - blk = param_get8(Cmd, cmdp+1); + blk = param_get8(Cmd, cmdp + 1); b_opt_selected = true; cmdp += 2; break; case 'd': - if (param_gethex(Cmd, cmdp+1, blkData, 64)) { + if (param_gethex(Cmd, cmdp + 1, blkData, 64)) { PrintAndLogEx(WARNING, "block data must include 64 HEX symbols"); errors = true; - break; + break; } d_opt_selected = true; cmdp += 2; @@ -409,7 +410,7 @@ static int CmdHfLTOWriteBlock(const char *Cmd) { break; } } - + //Validations if (errors) { usage_lto_wrbl(); @@ -440,7 +441,7 @@ int dumpLTO(uint8_t *dump, bool verbose) { uint8_t block_data_d00_d15[18]; uint8_t block_data_d16_d31[18]; - for(uint8_t i = 0; i < 255; i++) { + for (uint8_t i = 0; i < 255; i++) { ret_val = lto_rdbl(i, block_data_d00_d15, block_data_d16_d31, verbose); @@ -504,10 +505,10 @@ static int CmdHfLTODump(const char *Cmd) { int ret_val = dumpLTO(dump, true); if (ret_val != PM3_SUCCESS) { free(dump); - return ret_val; + return ret_val; } - // save to file + // save to file if (filename[0] == '\0') { memcpy(serial_number, sprint_hex_inrow(dump, sizeof(serial_number)), sizeof(serial_number)); char tmp_name[17] = "hf_lto_"; @@ -538,10 +539,10 @@ int restoreLTO(uint8_t *dump_data, bool verbose) { return ret_val; } - uint8_t blkData[32] = {0}; + uint8_t blkData[32] = {0}; //Block address 0 and 1 are read-only - for(uint8_t blk = 2; blk < 255; blk++) { + for (uint8_t blk = 2; blk < 255; blk++) { for (int i = 0; i < 32; i++) { blkData[i] = dump_data[i + blk * 32]; @@ -550,7 +551,7 @@ int restoreLTO(uint8_t *dump_data, bool verbose) { ret_val = lto_wrbl(blk, blkData, verbose); if (ret_val == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "BLK %03d: " _YELLOW_("write success"), blk); + PrintAndLogEx(SUCCESS, "BLK %03d: " _YELLOW_("write success"), blk); } else { lto_switch_off_field(); return ret_val; @@ -566,7 +567,7 @@ static int CmdHfLTRestore(const char *Cmd) { uint8_t cmdp = 0; bool errors = false; int is_data_loaded = PM3_ESOFT; - + char filename[FILE_PATH_SIZE] = {0}; char extension[FILE_PATH_SIZE] = {0}; @@ -623,7 +624,7 @@ static int CmdHfLTRestore(const char *Cmd) { } else { return PM3_EFILE; } - + } static command_t CommandTable[] = { diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index beb85df5b..9f6c458ae 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1505,7 +1505,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0); return 1; } - + // error during nested_hard if (resp.oldarg[0]) { if (nonce_file_write) { @@ -2034,7 +2034,7 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) { // create mutexes for accessing the statelist cache and our "book of work" pthread_mutex_init(&statelist_cache_mutex, NULL); pthread_mutex_init(&book_of_work_mutex, NULL); - + init_statelist_cache(); init_book_of_work(); diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 9b7fe51de..02a86c2da 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -1039,9 +1039,9 @@ static int CmdEM4x50Write(const char *Cmd) { uint8_t ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 'h') return usage_lf_em4x50_write(); PrintAndLogEx(NORMAL, "no implemented yet"); -// +// // PrintAndLogEx(SUCCESS, "Done"); -// PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x50_read`") "to verify"); +// PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x50_read`") "to verify"); return PM3_SUCCESS; } @@ -1440,7 +1440,7 @@ static int CmdEM4x05Write(const char *Cmd) { int status = demodEM4x05resp(&dummy); if (status == PM3_SUCCESS) PrintAndLogEx(SUCCESS, "Success writing to tag"); - + PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x05_read`") "to verify"); return status; diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index dbe027dc3..eb388faa6 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -346,7 +346,7 @@ static int CmdHIDClone(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_LF_HID_CLONE, hi2, hi, lo, longid, sizeof(longid)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf hid read`") "to verify"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf hid read`") "to verify"); return PM3_SUCCESS; } @@ -450,7 +450,7 @@ static int CmdHIDBrute(const char *Cmd) { PrintAndLogEx(INFO, "ISSUE#........... %u", cn_hi.IssueLevel); PrintAndLogEx(INFO, "Facility#........ %u", cn_hi.FacilityCode); PrintAndLogEx(INFO, "Card#............ %" PRIu64, cn_hi.CardNumber); - switch( direction) { + switch (direction) { case 0: PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("BOTH")); break; @@ -460,7 +460,8 @@ static int CmdHIDBrute(const char *Cmd) { case 2: PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("DOWN")); break; - default: break; + default: + break; } } PrintAndLogEx(INFO, "Brute-forcing HID reader"); @@ -495,7 +496,7 @@ static int CmdHIDBrute(const char *Cmd) { fin_hi = true; } } - + // do one down if (direction != 1) { if (cn_low.CardNumber > 0) { @@ -507,7 +508,7 @@ static int CmdHIDBrute(const char *Cmd) { } switch (direction) { - case 0: + case 0: if (fin_hi && fin_low) { exitloop = true; } @@ -518,7 +519,8 @@ static int CmdHIDBrute(const char *Cmd) { case 2: exitloop = fin_low; break; - default: break; + default: + break; } } while (exitloop == false); From bccad7b9d5a776dd0113daa4084064098855830c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Mar 2020 17:06:00 +0100 Subject: [PATCH 092/298] hint message --- client/cmdlfguard.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index 8597f4759..ba9023c21 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -187,7 +187,10 @@ static int CmdGuardClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Guardall to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber); print_blocks(blocks, ARRAYLEN(blocks)); - return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf gprox read`") "to verify"); + return res; } static int CmdGuardSim(const char *Cmd) { From f805e5c7c747f3b7ee70f4cf9a0d3f7d073a6d14 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Mar 2020 17:10:05 +0100 Subject: [PATCH 093/298] whitespace --- armsrc/lfsampling.c | 8 ++++---- client/Makefile | 2 +- client/cmdflashmemspiffs.c | 18 +++++++++--------- client/cmdhficlass.c | 38 +++++++++++++++++++------------------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 3ce7bc5da..3769e3565 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -117,8 +117,8 @@ void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) { if (use_malloc) { - if (sample_size == NULL || *sample_size == 0 ) { - *sample_size = BigBuf_max_traceLen(); + if (sample_size == NULL || *sample_size == 0) { + *sample_size = BigBuf_max_traceLen(); data.buffer = BigBuf_get_addr(); } else { *sample_size = MIN(*sample_size, BigBuf_max_traceLen()); @@ -127,7 +127,7 @@ void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) { } } else { - if (sample_size == NULL || *sample_size == 0 ) { + if (sample_size == NULL || *sample_size == 0) { *sample_size = BigBuf_max_traceLen(); } data.buffer = BigBuf_get_addr(); @@ -221,7 +221,7 @@ void LFSetupFPGAForADC(int divisor, bool reader_field) { SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // 50ms for the resonant antenna to settle. if (reader_field) - SpinDelay(50); + SpinDelay(50); // Now set up the SSC to get the ADC samples that are now streaming at us. FpgaSetupSsc(); diff --git a/client/Makefile b/client/Makefile index fae411a52..a09a033d9 100644 --- a/client/Makefile +++ b/client/Makefile @@ -130,7 +130,7 @@ CORESRCS = uart_posix.c \ util_posix.c \ scandir.c \ crc16.c \ - comms.c + comms.c CMDSRCS = crapto1/crapto1.c \ crapto1/crypto1.c \ diff --git a/client/cmdflashmemspiffs.c b/client/cmdflashmemspiffs.c index bdc51dc5d..fa8cdbf16 100644 --- a/client/cmdflashmemspiffs.c +++ b/client/cmdflashmemspiffs.c @@ -315,7 +315,7 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) { } int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { - + int ret_val = PM3_SUCCESS; // We want to mount before multiple operation so the lazy writes/append will not @@ -349,7 +349,7 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { bytes_sent += bytes_in_packet; PacketResponseNG resp; - + uint8_t retry = 3; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); @@ -377,7 +377,7 @@ out: // We want to unmount after these to set things back to normal but more than this // unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); - + return ret_val; } @@ -400,8 +400,8 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { cmdp += 2; break; case 'o': - param_getstr(Cmd, cmdp + 1, (char*)destfilename, 32); - if (strlen((char*)destfilename) == 0) { + param_getstr(Cmd, cmdp + 1, (char *)destfilename, 32); + if (strlen((char *)destfilename) == 0) { PrintAndLogEx(FAILED, "Destination Filename missing or invalid"); errors = true; } @@ -429,12 +429,12 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { } res = flashmem_spiffs_load(destfilename, data, datalen); - + free(data); - - if ( res == PM3_SUCCESS ) + + if (res == PM3_SUCCESS) PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename); - + return res; } diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index d69efd475..4e944c178 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -861,7 +861,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { getMemConfig(mem, chip, &max_blk, &app_areas, &kb); uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - + BLOCK79ENCRYPTION aa1_encryption = (decrypted[(6 * 8) + 7] & 0x03); for (uint16_t blocknum = 0; blocknum < applimit; ++blocknum) { @@ -894,36 +894,36 @@ static int CmdHFiClassDecrypt(const char *Cmd) { saveFileJSON(fptr, jsfIclass, decrypted, decryptedlen); printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen); - + // decode block 6 - if (memcmp(decrypted + (8*6), empty, 8) != 0 ) { + if (memcmp(decrypted + (8 * 6), empty, 8) != 0) { if (use_sc) { - DecodeBlock6(decrypted + (8*6)); + DecodeBlock6(decrypted + (8 * 6)); } } - // decode block 7-8-9 - if (memcmp(decrypted + (8*7), empty, 8) != 0 ) { - + // decode block 7-8-9 + if (memcmp(decrypted + (8 * 7), empty, 8) != 0) { + //todo: remove preamble/sentinal uint32_t top = 0, mid, bot; - mid = bytes_to_num(decrypted + (8*7), 4); - bot = bytes_to_num(decrypted + (8*7) + 4, 4); + mid = bytes_to_num(decrypted + (8 * 7), 4); + bot = bytes_to_num(decrypted + (8 * 7) + 4, 4); - PrintAndLogEx(INFO, "Block 7 binary"); + PrintAndLogEx(INFO, "Block 7 binary"); - char hexstr[8+1] = {0}; - hex_to_buffer((uint8_t *)hexstr, decrypted + (8*7), 8, sizeof(hexstr) - 1, 0, 0, true); - - char binstr[8*8+1] = {0}; + char hexstr[8 + 1] = {0}; + hex_to_buffer((uint8_t *)hexstr, decrypted + (8 * 7), 8, sizeof(hexstr) - 1, 0, 0, true); + + char binstr[8 * 8 + 1] = {0}; hextobinstring(binstr, hexstr); - uint8_t i=0; - while (iblockdata, sizeof(result->blockdata))); - + if (blockno == 6) { if (IsCryptoHelperPresent()) { DecodeBlock6(result->blockdata); From 57788d57516539a832f2b0598ffd7ea0f03fec48 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Mar 2020 17:11:57 +0100 Subject: [PATCH 094/298] whitespace --- armsrc/hitag2.c | 65 +++--- armsrc/hitag2crack.c | 458 +++++++++++++++++-------------------------- armsrc/hitagS.c | 10 +- armsrc/iso14443a.c | 18 +- 4 files changed, 230 insertions(+), 321 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 87d6bf221..2df49ac3d 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -408,7 +408,7 @@ void fix_ac_decoding(uint8_t *input, size_t len) { */ -// looks at number of received bits. +// looks at number of received bits. // 0 = collision? // 32 = good response bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool hitag_s) { @@ -582,15 +582,15 @@ bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *t Dbhexdump(4, logdata_1, false); bSuccessful = true; return false; -/* - // read next page of card until done - tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE - tx[1] = blocknr << 4; - crc = hitag_crc(tx, 12); - tx[1] |= crc >> 4; - tx[2] = crc << 4; - *txlen = 20; -*/ + /* + // read next page of card until done + tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE + tx[1] = blocknr << 4; + crc = hitag_crc(tx, 12); + tx[1] |= crc >> 4; + tx[2] = crc << 4; + *txlen = 20; + */ } } break; @@ -1091,7 +1091,7 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { uint32_t block = 0; for (size_t i = 0; i < 12; i++) { - // num2bytes? + // num2bytes? for (size_t j = 0; j < 4; j++) { block <<= 8; block |= tag.sectors[i][j]; @@ -1105,30 +1105,30 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { size_t nrzs = 0, periods = 0; // uint32_t command_start = 0, command_duration = 0; - // int16_t checked = 0; + // int16_t checked = 0; // SIMULATE while (!BUTTON_PRESS()) { LED_D_ON(); - + // lf_reset_counter(); LED_A_OFF(); WDT_HIT(); -/* - // only every 1000th times, in order to save time when collecting samples. - if (checked == 100) { - if (data_available()) { - checked = -1; - break; - } else { - checked = 0; - } - } - ++checked; -*/ + /* + // only every 1000th times, in order to save time when collecting samples. + if (checked == 100) { + if (data_available()) { + checked = -1; + break; + } else { + checked = 0; + } + } + ++checked; + */ rxlen = 0; @@ -1220,8 +1220,8 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { if (nrzs < 5) { Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs); continue; - } else { - for (size_t i = 0; i < 5; i++){ + } else { + for (size_t i = 0; i < 5; i++) { if (nrz_samples[i] != 1) { Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one", i); } @@ -1229,7 +1229,7 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { } // Pack the response into a byte array - for (size_t i = 5; i < 37; i++){ + for (size_t i = 5; i < 37; i++) { uint8_t bit = nrz_samples[i]; rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); rxlen++; @@ -1401,7 +1401,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // hitagS settings t_wait_1 = 204; t_wait_2 = 128; - /*tag_size = 256;*/ flipped_bit = 0; tag_size = 8; DBG DbpString("Configured for hitagS reader"); @@ -1657,7 +1656,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { uint32_t command_start = 0; uint32_t command_duration = 0; uint32_t response_start = 0; - uint32_t response_duration = 0; + uint32_t response_duration = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t txbuf[HITAG_FRAME_LEN]; @@ -1731,14 +1730,14 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { tag_size = 8; DbpString("Configured for hitagS writer"); } else if (htf < 20) { - // hitag1 settings + // hitag1 settings t_wait_1 = 204; t_wait_2 = 128; tag_size = 256; flipped_bit = 0; DbpString("Configured for hitag1 writer"); } else if (htf < 30) { - // hitag2 settings + // hitag2 settings t_wait_1 = HITAG_T_WAIT_1_MIN; t_wait_2 = HITAG_T_WAIT_2_MIN; tag_size = 48; @@ -1783,7 +1782,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { } } - // Wait for t_wait_2 carrier periods after the last tag bit before transmitting, + // Wait for t_wait_2 carrier periods after the last tag bit before transmitting, lf_wait_periods(t_wait_2); command_start += t_wait_2; diff --git a/armsrc/hitag2crack.c b/armsrc/hitag2crack.c index c6b61b019..2d0d868b9 100644 --- a/armsrc/hitag2crack.c +++ b/armsrc/hitag2crack.c @@ -38,70 +38,60 @@ bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) { uint8_t temp[20]; int i; uint8_t *spaceptr = NULL; - + // get uid as hexstring - if(!hitag2_get_uid(uidhex)) - { + if (!hitag2_get_uid(uidhex)) { UserMessage("Cannot get UID\r\n"); return false; } // convert uid hexstring to binarray hextobinarray(uid, uidhex); - + // convert nR and aR hexstrings to binarray spaceptr = strchr(nrarhex, ' '); - if (!spaceptr) - { + if (!spaceptr) { UserMessage("Please supply a valid nR aR pair\r\n"); return false; } *spaceptr = 0x00; - - if (hextobinarray(nrar, nrarhex) != 32) - { + + if (hextobinarray(nrar, nrarhex) != 32) { UserMessage("nR is not 32 bits long\r\n"); return false; } - - if (hextobinarray(nrar + 32, spaceptr + 1) != 32) - { + + if (hextobinarray(nrar + 32, spaceptr + 1) != 32) { UserMessage("aR is not 32 bits long\r\n"); return false; } // find a valid encrypted command - if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) - { + if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) { UserMessage("Cannot find a valid encrypted command\r\n"); return false; } - + // find the 'read page 0' command and recover key stream - if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) - { + if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) { UserMessage("Cannot find encrypted 'read page0' command\r\n"); return false; } - + // empty the response string response[0] = 0x00; - + // read all pages using key stream - for (i=0; i<8; i++) - { - if (hitag2crack_read_page(pagehex, i, nrar, keybits)) - { + for (i = 0; i < 8; i++) { + if (hitag2crack_read_page(pagehex, i, nrar, keybits)) { sprintf(temp, "%1d: %s\r\n", i, pagehex); - } - else - { + } else { sprintf(temp, "%1d:\r\n", i); } // add page string to response strcat(response, temp); } - + return true; } @@ -113,16 +103,16 @@ bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) { bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) { uint8_t guess[10]; uint8_t responsestr[9]; - + // UserMessage("Finding valid encrypted command:"); // we're going to hold bits 5, 7, 8 and 9 and brute force the rest // e.g. x x x x x 0 x 0 0 0 - for (uint8_t a=0; a<2; a++) { - for (uint8_t b=0; b<2; b++) { - for (uint8_t c=0; c<2; c++) { - for (uint8_t d=0; d<2; d++) { - for (uint8_t e=0; e<2; e++) { - for (uint8_t g=0; g<2; g++) { + for (uint8_t a = 0; a < 2; a++) { + for (uint8_t b = 0; b < 2; b++) { + for (uint8_t c = 0; c < 2; c++) { + for (uint8_t d = 0; d < 2; d++) { + for (uint8_t e = 0; e < 2; e++) { + for (uint8_t g = 0; g < 2; g++) { // build binarray guess[0] = a; guess[1] = b; @@ -175,65 +165,50 @@ bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8 UserMessage("Finding 'read page 0' command:"); // we're going to brute the missing 4 bits of the valid encrypted command - for (a=0; a<2; a++) - { - for (b=0; b<2; b++) - { - for (c=0; c<2; c++) - { - for (d=0; d<2; d++) - { + for (a = 0; a < 2; a++) { + for (b = 0; b < 2; b++) { + for (c = 0; c < 2; c++) { + for (d = 0; d < 2; d++) { // create our guess by bit flipping the pattern of bits // representing the inverted bit and the 3 page bits // in both the non-inverted and inverted parts of the // encrypted command. memcpy(guess, e_firstcmd, 10); - if (a) - { + if (a) { guess[5] = !guess[5]; guess[0] = !guess[0]; } - if (b) - { + if (b) { guess[7] = !guess[7]; guess[2] = !guess[2]; } - if (c) - { + if (c) { guess[8] = !guess[8]; guess[3] = !guess[3]; } - if (d) - { + if (d) { guess[9] = !guess[9]; guess[4] = !guess[4]; } - + // try the guess - if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) - { + if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) { // check if it was valid - if (strcmp(responsestr, ERROR_RESPONSE) != 0) - { + if (strcmp(responsestr, ERROR_RESPONSE) != 0) { // convert response to binarray hextobinarray(e_uid, responsestr); // test if the guess was 'read page 0' command - if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) - { - + if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) { + return true; } - } - else - { + } else { #ifdef RFIDLER_DEBUG UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n"); #endif } - } - else - { - #ifdef RFIDLER_DEBUG + } else { +#ifdef RFIDLER_DEBUG UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); #endif } @@ -262,56 +237,51 @@ bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, u uint8_t e_ext_cmd[40]; uint8_t responsestr[9]; int i; - + // copy encrypted cmd to cipherbits memcpy(cipherbits, e_cmd, 10); - + // copy encrypted uid to cipherbits memcpy(cipherbits + 10, e_uid, 32); - + // copy cmd to plainbits binstringtobinarray(plainbits, READP0CMD); - + // copy uid to plainbits memcpy(plainbits + 10, uid, 32); // xor the plainbits with the cipherbits to get keybits hitag2crack_xor(keybits, plainbits, cipherbits, 42); - + // create extended cmd -> 4 * READP0CMD = 40 bits - for (i=0; i<4; i++) - { + for (i = 0; i < 4; i++) { binstringtobinarray(ext_cmd + (i * 10), READP0CMD); } - + // xor extended cmd with keybits hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40); - + // send extended encrypted cmd - if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40)) - { + if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40)) { // test if it was valid - if (strcmp(responsestr, ERROR_RESPONSE) != 0) - { + if (strcmp(responsestr, ERROR_RESPONSE) != 0) { return true; } - } - else - { + } else { #ifdef RFIDLER_DEBUG UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); #endif } - + return false; - + } // hitag2crack_xor XORs the source with the pad to produce the target. // source, target and pad are binarrays of length len. void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len) { - for (int i=0; i 7)) - { + + if ((pagenum < 0) || (pagenum > 7)) { UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n"); return false; } - + // create cmd binstringtobinarray(cmd, READP0CMD); - if (pagenum & 0x1) - { + if (pagenum & 0x1) { cmd[9] = !cmd[9]; cmd[4] = !cmd[4]; } - if (pagenum & 0x2) - { + if (pagenum & 0x2) { cmd[8] = !cmd[8]; cmd[3] = !cmd[3]; } - if (pagenum & 0x4) - { + if (pagenum & 0x4) { cmd[7] = !cmd[7]; cmd[2] = !cmd[2]; } - + // encrypt command hitag2crack_xor(e_cmd, cmd, keybits, 10); - + // send encrypted command - if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10)) - { + if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10)) { // check if it is valid - if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) - { + if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) { // convert to binarray hextobinarray(e_response, e_responsestr); // decrypt response @@ -370,17 +334,13 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, // convert to hexstring binarraytohex(responsestr, response, 32); return true; - } - else - { + } else { UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n"); } - } - else - { + } else { UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n"); } - + return false; } @@ -397,8 +357,7 @@ bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, i int ret = 0; // get the UID - if(!hitag2_get_uid(uid)) - { + if (!hitag2_get_uid(uid)) { UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n"); return false; } @@ -407,22 +366,19 @@ bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, i CryptoActive = false; // get the UID again - if(!hitag2_get_uid(uid)) - { + if (!hitag2_get_uid(uid)) { UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n"); return false; } - + // send nrar and receive (useless) encrypted page 3 value - if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) - { + if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) { UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n"); return false; } - + // send encrypted command - if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) - { + if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) { #ifdef RFIDLER_DEBUG UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n"); #endif @@ -442,34 +398,29 @@ bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, b int ret = 0; // START_AUTH kills active crypto session - CryptoActive= false; - - if(!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) - { + CryptoActive = false; + + if (!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) { UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n"); return false; } - + // skip 1/2 bit to synchronise manchester HW_Skip_Bits = 1; ret = read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY); // check if response was a valid length (5 sync bits + 32 bits response) - if (ret == 37) - { + if (ret == 37) { // check sync bits - if (memcmp(tmp, Hitag2Sync, 5) != 0) - { + if (memcmp(tmp, Hitag2Sync, 5) != 0) { UserMessage("hitag2crack_tx_rx: no sync\r\n"); return false; } - + // convert response to hexstring binarraytohex(responsestr, tmp + 5, 32); return true; - } - else - { + } else { #ifdef RFIDLER_DEBUG UserMessage("hitag2crack_tx_rx: wrong rx len\r\n"); #endif @@ -485,58 +436,53 @@ bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) { uint32_t initvector; uint8_t *spaceptr; uint8_t *dataptr; - + // extract vals from input dataptr = input; spaceptr = strchr(dataptr, ' '); - if (!spaceptr) - { + if (!spaceptr) { UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n"); return false; } - + *spaceptr = 0x00; - - if (strlen(dataptr) != 12) - { + + if (strlen(dataptr) != 12) { UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n"); return false; } sharedkey = rev64(hexreversetoulonglong(dataptr)); - - dataptr = spaceptr+1; + + dataptr = spaceptr + 1; spaceptr = strchr(dataptr, ' '); - if (!spaceptr) - { + if (!spaceptr) { UserMessage("/r/nno UID\r\n"); return false; } - + *spaceptr = 0x00; - if (strlen(dataptr) != 8) - { + if (strlen(dataptr) != 8) { UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n"); return false; } - + serialnum = rev32(hexreversetoulong(dataptr)); - - dataptr = spaceptr+1; - - if (strlen(dataptr) != 8) - { + + dataptr = spaceptr + 1; + + if (strlen(dataptr) != 8) { UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n"); return false; } - + initvector = rev32(hexreversetoulong(dataptr)); - + // start up crypto engine hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector); - + strcpy(response, "Success\r\n"); - + return true; } @@ -545,21 +491,20 @@ bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) { uint8_t binhex[9]; uint8_t binstr[33]; uint32_t binulong; - - if (strlen(hex) != 8) - { + + if (strlen(hex) != 8) { UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n"); return false; } - + binulong = hextoulong(hex); - + ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32); binarraytobinstring(binstr, bin, 32); binarraytohex(binhex, bin, 32); // UserMessage("ar = %s\r\n", binstr); // UserMessage("arhex = %s\r\n", binhex); - + strcpy(response, binhex); return true; } @@ -570,17 +515,16 @@ bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) { uint8_t binstr[33]; uint32_t binulong; int len; - + len = strlen(e_binstr); - if (len > 32) - { + if (len > 32) { UserMessage("\r\nbinary string must be <= 32 bits\r\n"); return false; } - + binstringtobinarray(e_bin, e_binstr); binulong = binarraytoulong(e_bin, len); - + ulongtobinarray(bin, hitag2_crypt(binulong, len), len); binarraytobinstring(binstr, bin, len); strcpy(response, binstr); @@ -595,7 +539,7 @@ bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) { bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) { return hitag2crack_decrypt_bin(response, e_binstr); } - + // hitag2_keystream uses the first crack algorithm described in the paper, // Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits // of keystream. @@ -618,102 +562,90 @@ bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) { int i; uint8_t *spaceptr = NULL; -/* - keybits = malloc(2080); - if (!keybits) { - UserMessage("cannot malloc keybits\r\n"); - return false; - } -*/ - + /* + keybits = malloc(2080); + if (!keybits) { + UserMessage("cannot malloc keybits\r\n"); + return false; + } + */ + // get uid as hexstring - if(!hitag2_get_uid(uidhex)) - { + if (!hitag2_get_uid(uidhex)) { UserMessage("Cannot get UID\r\n"); return false; } // convert uid hexstring to binarray hextobinarray(uid, uidhex); - + // convert nR and aR hexstrings to binarray spaceptr = strchr(nrarhex, ' '); - if (!spaceptr) - { + if (!spaceptr) { UserMessage("Please supply a valid nR aR pair\r\n"); return false; } *spaceptr = 0x00; - - if (hextobinarray(nrar, nrarhex) != 32) - { + + if (hextobinarray(nrar, nrarhex) != 32) { UserMessage("nR is not 32 bits long\r\n"); return false; } - - if (hextobinarray(nrar + 32, spaceptr + 1) != 32) - { + + if (hextobinarray(nrar + 32, spaceptr + 1) != 32) { UserMessage("aR is not 32 bits long\r\n"); return false; } // find a valid encrypted command - if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) - { + if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) { UserMessage("Cannot find a valid encrypted command\r\n"); return false; } - + // find the 'read page 0' command and recover key stream - if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) - { + if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) { UserMessage("Cannot find encrypted 'read page0' command\r\n"); return false; } - + // using the 40 bits of keystream in keybits, sending commands with ever // increasing lengths to acquire 2048 bits of key stream. kslen = 40; - - while (kslen < 2048) - { + + while (kslen < 2048) { ksoffset = 0; - if (!hitag2crack_send_auth(nrar)) - { + if (!hitag2crack_send_auth(nrar)) { UserMessage("hitag2crack_send_auth failed\r\n"); return false; } // while we have at least 52 bits of keystream, consume it with // extended read page 0 commands. 52 = 10 (min command len) + // 32 (response) + 10 (min command len we'll send) - while ((kslen - ksoffset) >= 52) - { + while ((kslen - ksoffset) >= 52) { // consume the keystream, updating ksoffset as we go - if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar)) - { + if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar)) { UserMessage("hitag2crack_consume_keystream failed\r\n"); return false; } } // send an extended command to retrieve more keystream, updating kslen // as we go - if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) - { + if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) { UserMessage("hitag2crack_extend_keystream failed\r\n"); return false; } UserMessage("Recovered %d bits of keystream\r\n", kslen); } - - for (i=0; i<2048; i+=256) - { + + for (i = 0; i < 2048; i += 256) { binarraytohex(keybitshex, keybits + i, 256); UserMessage("%s\r\n", keybitshex); } response[0] = 0x00; - + return true; } @@ -724,8 +656,7 @@ bool hitag2crack_send_auth(uint8_t *nrar) { uint8_t e_page3str[9]; // get the UID - if(!hitag2_get_uid(uid)) - { + if (!hitag2_get_uid(uid)) { UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n"); return false; } @@ -734,15 +665,13 @@ bool hitag2crack_send_auth(uint8_t *nrar) { CryptoActive = false; // get the UID again - if(!hitag2_get_uid(uid)) - { + if (!hitag2_get_uid(uid)) { UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n"); return false; } - + // send nrar and receive (useless) encrypted page 3 value - if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) - { + if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) { UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n"); return false; } @@ -767,46 +696,41 @@ bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, u // 42 = 32 bit response + 10 bit command reserved for next command. conlen // cannot be longer than 510 bits to fit into the small RWD buffer. conlen = kslen - *ksoffset - 42; - if (conlen < 10) - { + if (conlen < 10) { UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n"); return false; } - + // sanitise conlen - if (conlen > 510) - { + if (conlen > 510) { conlen = 510; } - + // calculate how many repeated commands to send in this extended command. numcmds = conlen / 10; - + // build extended command - for (i=0; i= 44) { - Dbprintf("Challenge success: %02X%02X%02X%02X %02X%02X%02X%02X", - unlocker[u1 - 1][0], unlocker[u1 - 1][1], - unlocker[u1 - 1][2], unlocker[u1 - 1][3], - unlocker[u1 - 1][4], unlocker[u1 - 1][5], - unlocker[u1 - 1][6], unlocker[u1 - 1][7]); + Dbprintf("Challenge success: %02X%02X%02X%02X %02X%02X%02X%02X", + unlocker[u1 - 1][0], unlocker[u1 - 1][1], + unlocker[u1 - 1][2], unlocker[u1 - 1][3], + unlocker[u1 - 1][4], unlocker[u1 - 1][5], + unlocker[u1 - 1][6], unlocker[u1 - 1][7]); STATE = 0; } diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index abfe07f10..23b3a2239 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1817,15 +1817,15 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) { ++check; // test if the field exists -#if defined RDV4 +#if defined RDV4 if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF_RDV40)) { - + analogCnt++; - + analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_RDV40]; - + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; - + if (analogCnt >= 32) { if ((MAX_ADC_HF_VOLTAGE_RDV40 * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) { @@ -1847,13 +1847,13 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) { } #else if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) { - + analogCnt++; - + analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF]; - + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; - + if (analogCnt >= 32) { if ((MAX_ADC_HF_VOLTAGE * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) { From 698ea94bc332f1dd9a62c089d573825b3e69e023 Mon Sep 17 00:00:00 2001 From: Jonathan Farley Date: Tue, 10 Mar 2020 12:40:58 -0400 Subject: [PATCH 095/298] Update Mac-OS-X-Homebrew-Installation-Instructions.md Spelling. --- .../Mac-OS-X-Homebrew-Installation-Instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md index 76f5ee6f3..6ce8b5990 100644 --- a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md @@ -33,7 +33,7 @@ brew upgrade --fetch-HEAD proxmark3 ## Flash the BOOTROM & FULLIMAGE -With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark3 as you plug it into a USB port. You can release the button, two of the four LEDs should stay on. You're un bootloader mode, ready for the next step. In case the two LEDs don't stay on when you're releasing the button, you've an old bootloader, start over and keep the button pressed during the whole flashing procedure. +With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark3 as you plug it into a USB port. You can release the button, two of the four LEDs should stay on. You're in bootloader mode, ready for the next step. In case the two LEDs don't stay on when you're releasing the button, you've an old bootloader, start over and keep the button pressed during the whole flashing procedure. In principle, the helper script `pm3-flash-all` should auto-detect your port, so you can just try: From 9124b3c988bff35806cf0987ea6d12885d7cece2 Mon Sep 17 00:00:00 2001 From: ikarus Date: Tue, 10 Mar 2020 21:37:23 +0100 Subject: [PATCH 096/298] fix: (static)nested time and keys/sec also some wording and consistency --- client/mifare/mifarehost.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 6ab6943cf..b5d1cb267 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -152,7 +152,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { if (*key != UINT64_C(-1)) { break; } else { - PrintAndLogEx(FAILED, "all candidate keys failed. Restarting darkside attack"); + PrintAndLogEx(FAILED, "all key candidates failed. Restarting darkside attack"); free(last_keylist); last_keylist = keylist; first_run = true; @@ -345,7 +345,7 @@ int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultk // copy candidatekeys to test key block memcpy(keyBlock, candidates + i, KEYBLOCK_SIZE); - // check a block of generated candidate keys. + // check a block of generated key candidates. if (mfCheckKeys(blockNo, keyType, true, KEYS_IN_BLOCK, keyBlock, &key64) == PM3_SUCCESS) { *resultkey = key64; found = true; @@ -510,7 +510,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint32_t keycnt = statelists[0].len; if (keycnt == 0) goto out; - PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt); + PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "key candidates", keycnt); memset(resultKey, 0, 6); uint64_t key64 = -1; @@ -544,10 +544,10 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, return -5; } - float bruteforce_per_second = (float)KEYS_IN_BLOCK / (msclock() - start_time) * 1000.0; - - if (i + 1 % 10 == 0) - PrintAndLogEx(INFO, " %6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second); +// if (i + 1 % 10 == 0) { + float bruteforce_per_second = (float)(i + max_keys) / ((msclock() - start_time) / 1000.0); + PrintAndLogEx(INFO, "%6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second); +// } } @@ -644,7 +644,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl uint32_t keycnt = statelists[0].len; if (keycnt == 0) goto out; - PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt); + PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "key candidates", keycnt); memset(resultKey, 0, 6); uint64_t key64 = -1; @@ -689,7 +689,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl num_to_bytes(key64, 6, p_keyblock + j * 6); } - // check a block of generated candidate keys. + // check a block of generated key candidates. if (IfPm3Flash()) { // upload to flash. res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6)); @@ -723,8 +723,8 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl } // if (i%10 == 0) { - float bruteforce_per_second = (float)i + max_keys_chunk / (msclock() - start_time) * 1000.0; - PrintAndLogEx(INFO, "Chunk %6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second); + float bruteforce_per_second = (float)(i + max_keys_chunk) / ((msclock() - start_time) / 1000.0); + PrintAndLogEx(INFO, "%6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second); // } } From fa1103bbc38239bc978c51a56d1fbdb3b5b7a434 Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Wed, 11 Mar 2020 18:23:37 +1100 Subject: [PATCH 097/298] Add Mifare Ultralight bruteforce support to hf_bruteforce lua script --- CHANGELOG.md | 8 ++-- client/luascripts/hf_bruteforce.lua | 68 +++++++++++++++++------------ doc/cheatsheet.md | 10 +++++ 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0391fdf2..085778f36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change `script run hf_bruteforce -s start_id -e end_id -t timeout -x mifare_card_type` - The hf_bruteforce card script now requires Mifare type (mfc or mfu) (@dunderhay) + - Updated `hf_bruteforce.lua` script - added support for brute forcing Mifare Ultralight EV1 cards (@dunderhay) - Added `hf mf personlize` - personalize the UID of a Mifare Classic EV1 card (@pwpiwi) - Change - hint texts added to all lf clone commands (@iceman1001) - Change `lf keri demod` - adjusted the internal id. (@mwalker33) @@ -36,7 +38,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `commands.md` - document with all proxmark client commands. Generated with XX_internal_command_dump_markdown_XX. (@iceman1001) - Change `lf pac clone` - new option `c ` to allow cloning PAC/Stanley tag from card ID (@danshuk) - Change `lf pac read` - decoded PAC/Stanley card ID (@danshuk) - - Change mifare classic keytable output refactored and uses colors (@iceman1001) + - Change mifare classic keytable output refactored and uses colors (@iceman1001) - Fix `hf mf nested` - now writes the correct blockno (@iceman1001) - Change `lf t55xx dump` - now supports saving to JSON (@iceman1001) - Change `hf mf chk | fchk` faster authentication by lower timeout limit. (@pwpiwi) @@ -606,8 +608,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Updated the Reveng 1.31 sourcecode to 1.40 from Reveng project homepage (@iceman1001) - Added possibility to write direct to a Legic Prime Tag (MIM256/1024) without using values from the `BigBuffer` -> `hf legic writeRaw ` (@icsom) - Added possibility to decrease DCF values at address 0x05 & 0x06 on a Legic Prime Tag - DCF-value will be pulled from the BigBuffer (address 0x05 & 0x06) so you have to - load the data into the BigBuffer before with `hf legic load ` & then + DCF-value will be pulled from the BigBuffer (address 0x05 & 0x06) so you have to + load the data into the BigBuffer before with `hf legic load ` & then write the DCF-Values (both at once) with `hf legic write 0x05 0x02` (@icsom) - Added script `legic.lua` for display and edit Data of Legic-Prime Tags (@icsom) - Added the experimental HITAG_S support (@spenneb) diff --git a/client/luascripts/hf_bruteforce.lua b/client/luascripts/hf_bruteforce.lua index a3a6636b8..ff8ba6764 100644 --- a/client/luascripts/hf_bruteforce.lua +++ b/client/luascripts/hf_bruteforce.lua @@ -1,27 +1,34 @@ --- Run me like this: proxmark3 /dev/rfcomm0 -l ./hf_bruteforce.lua +-- Run me like this (connected via USB): ./pm3 -l hf_bruteforce.lua +-- Run me like this (connected via Blueshark addon): ./client/proxmark3 /dev/rfcomm0 -l ./hf_bruteforce.lua local getopt = require('getopt') copyright = '' -author = 'Keld Norman' -version = 'v1.0.0' -desc = [[ - -]] -example = [[ - -- (the above example would bruteforce card number, starting at 1, ending at 10, and waiting 1 second between each card) - - script run hf_bruteforce -s 1 -e 10 -t 1000 -]] +author = 'Daniel Underhay (updated), Keld Norman(original)' +version = 'v2.0.0' usage = [[ -script run hf_bruteforce -s start_id -e end_id -t timeout -d direction +pm3 --> script run hf_bruteforce -s start_id -e end_id -t timeout -x mifare_card_type Arguments: -h this help -s 0-0xFFFFFFFF start id -e 0-0xFFFFFFFF end id - -t 0-99999, pause timeout (ms) between cards (use the word 'pause' to wait for user input) + -t 0-99999, pause timeout (ms) between cards (use the word 'pause' to wait for user input) + -x mfc, mfu mifare type: mfc for Mifare Classic (default) or mfu for Mifare Ultralight EV1 + + +Example: + +pm3 --> script run hf_bruteforce -s 0x11223344 -e 0x11223346 -t 1000 -x mfc + +Bruteforce a 4 byte UID Mifare classic card number, starting at 11223344, ending at 11223346. + + +pm3 --> script run hf_bruteforce -s 0x11223344556677 -e 0x11223344556679 -t 1000 -x mfu + +Bruteforce a 7 byte UID Mifare Ultralight card number, starting at 11223344556677, ending at 11223344556679. + ]] @@ -60,41 +67,49 @@ local function help() print(usage) end --- --- Exit message -local function exitMsg(msg) +--- Print user message +local function msg(msg) print( string.rep('--',20) ) + print('') print(msg) + print('') print( string.rep('--',20) ) - print() end --- -- Start local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() local timeout = 0 local start_id = 0 - local end_id = 0xFFFFFFFF + local end_id = 0xFFFFFFFFFFFFFF + local mftype = 'mfc' - for o, a in getopt.getopt(args, 'e:s:t:h') do + for o, a in getopt.getopt(args, 'e:s:t:x:h') do if o == 's' then start_id = a end if o == 'e' then end_id = a end if o == 't' then timeout = a end + if o == 'x' then mftype = a end if o == 'h' then return print(usage) end end -- template - local command = 'hf 14a sim t 1 u %08X' + local command = '' - print(' Bruteforcing MFC card numbers from 00000000 to FFFFFFFF using delay: '..timeout) - print('') - print( string.rep('--',20) ) + if mftype == 'mfc' then + command = 'hf 14a sim t 1 u %14X' + msg('Bruteforcing Mifare Classic card numbers') + elseif mftype == 'mfu' then + command = 'hf 14a sim t 2 u %14X' + msg('Bruteforcing Mifare Ultralight card numbers') + else + return print(usage) + end + + if command == '' then return print(usage) end for n = start_id, end_id do local c = string.format( command, n ) - print(' Running: "'..c..'"') + print('Running: "'..c..'"') core.console(c) core.console('msleep '..timeout); core.console('hw ping') @@ -102,4 +117,3 @@ local function main(args) end main(args) - diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index b5ccd39b8..a3e0a220c 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -290,6 +290,16 @@ pm3 --> hf mfu eload u hf-mfu-XXXX-dump.eml pm3 --> hf mfu sim t 7 u hf-mfu-XXXX-dump.eml ``` +Bruteforce Mifare Classic card numbers from 11223344 to 11223346 +``` +pm3 --> script run hf_bruteforce -s 0x11223344 -e 0x11223346 -t 1000 -x mfc +``` + +Bruteforce Mifare Ultralight EV1 card numbers from 11223344556677 to 11223344556679 +``` +pm3 --> script run hf_bruteforce -s 0x11223344556677 -e 0x11223344556679 -t 1000 -x mfu +``` + ## Wiegand manipulation ^[Top](#top) From b96585483d3cda770d18c7bad8735ddf5949b2d3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 11 Mar 2020 17:08:03 +0100 Subject: [PATCH 098/298] fix: hf iclass decrypt - making sure we use available bytes even if app limit reports much more data --- client/cmdhficlass.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 4e944c178..f3216e58d 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -785,7 +785,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { return usage_hf_iclass_decrypt(); case 'd': if (param_gethex(Cmd, cmdp + 1, enc_data, 16)) { - PrintAndLogEx(ERR, "data must be 16 HEX symbols"); + PrintAndLogEx(ERR, "Data must be 16 HEX symbols"); errors = true; break; } @@ -794,7 +794,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { break; case 'f': if (param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)) == 0) { - PrintAndLogEx(WARNING, "no filename found after f"); + PrintAndLogEx(WARNING, "No filename found after f"); errors = true; break; } @@ -864,7 +864,14 @@ static int CmdHFiClassDecrypt(const char *Cmd) { BLOCK79ENCRYPTION aa1_encryption = (decrypted[(6 * 8) + 7] & 0x03); - for (uint16_t blocknum = 0; blocknum < applimit; ++blocknum) { + uint32_t limit = MIN(applimit, decryptedlen / 8); + + if (decryptedlen / 8 != applimit) { + PrintAndLogEx(WARNING, "Actual file len " _YELLOW_("%u") "vs HID app-limit len " _YELLOW_("%u"), decryptedlen, applimit * 8); + PrintAndLogEx(INFO, "Setting limit to " _GREEN_("%u"), limit * 8); + } + + for (uint16_t blocknum = 0; blocknum < limit; ++blocknum) { uint8_t idx = blocknum * 8; memcpy(enc_data, decrypted + idx, 8); @@ -885,7 +892,12 @@ static int CmdHFiClassDecrypt(const char *Cmd) { } //Use the first block (CSN) for filename - char *fptr = calloc(42, sizeof(uint8_t)); + char *fptr = calloc(50, sizeof(uint8_t)); + if (!fptr) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); + free(decrypted); + return PM3_EMALLOC; + } strcat(fptr, "hf-iclass-"); FillFileNameByUID(fptr, hdr->csn, "-data-decrypted", sizeof(hdr->csn)); @@ -893,9 +905,9 @@ static int CmdHFiClassDecrypt(const char *Cmd) { saveFileEML(fptr, decrypted, decryptedlen, 8); saveFileJSON(fptr, jsfIclass, decrypted, decryptedlen); + PrintAndLogEx(INFO, "Following output skips CSN / block0"); printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen); - // decode block 6 if (memcmp(decrypted + (8 * 6), empty, 8) != 0) { if (use_sc) { From 5c2d4a0bbd89d764352d6576eb6a72bd5e615fba Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 11 Mar 2020 18:38:07 +0100 Subject: [PATCH 099/298] text --- client/cmdhficlass.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index f3216e58d..e471f3fbe 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -1263,7 +1263,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { if (kbd_enter_pressed()) { PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); DropField(); - return 0; + return PM3_EOPABORTED; } if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) @@ -1355,8 +1355,8 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { // print the dump PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "------+--+-------------------------+"); - PrintAndLogEx(NORMAL, "CSN |00| %s|", sprint_hex(tag_data, 8)); + PrintAndLogEx(INFO, "------+--+-------------------------+"); + PrintAndLogEx(INFO, "CSN |00| %s|", sprint_hex(tag_data, 8)); printIclassDumpContents(tag_data, 1, (gotBytes / 8), gotBytes); if (filename[0] == 0) { From dfd408db8daea19a05cecda7eda236de155411fe Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 11 Mar 2020 21:00:19 +0100 Subject: [PATCH 100/298] cardhelper --- client/cmdhficlass.c | 13 ++++++------- common/cardhelper.c | 17 ++++++++++++++--- common/cardhelper.h | 1 + 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index e471f3fbe..827cbcc38 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -870,19 +870,18 @@ static int CmdHFiClassDecrypt(const char *Cmd) { PrintAndLogEx(WARNING, "Actual file len " _YELLOW_("%u") "vs HID app-limit len " _YELLOW_("%u"), decryptedlen, applimit * 8); PrintAndLogEx(INFO, "Setting limit to " _GREEN_("%u"), limit * 8); } + uint8_t numblocks4userid = GetNumberBlocksForUserId(decrypted + (6 * 8)); for (uint16_t blocknum = 0; blocknum < limit; ++blocknum) { uint8_t idx = blocknum * 8; memcpy(enc_data, decrypted + idx, 8); - // block 7 or higher, and not empty 0xFF - // look inside block 6 to determine if aa1 is encrypted. - if (blocknum > 6 && memcmp(enc_data, empty, 8) != 0) { - - if (aa1_encryption == RFU || aa1_encryption == None) - continue; - + if (aa1_encryption == RFU || aa1_encryption == None) + continue; + + // Decrypted block 7,8,9 if configured. + if (blocknum > 6 && blocknum <= 6 + numblocks4userid && memcmp(enc_data, empty, 8) != 0) { if (use_sc) { Decrypt(enc_data, decrypted + idx); } else { diff --git a/common/cardhelper.c b/common/cardhelper.c index 5cebf4322..df3aff5be 100644 --- a/common/cardhelper.c +++ b/common/cardhelper.c @@ -15,9 +15,10 @@ #include "ui.h" #include "util.h" -#define CARD_INS_DECRYPT 0x01 -#define CARD_INS_ENCRYPT 0x02 -#define CARD_INS_DECODE 0x06 +#define CARD_INS_DECRYPT 0x01 +#define CARD_INS_ENCRYPT 0x02 +#define CARD_INS_DECODE 0x06 +#define CARD_INS_NUMBLOCKS 0x07 static uint8_t cmd[] = {0x96, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // look for CryptoHelper @@ -64,6 +65,7 @@ bool Encrypt(uint8_t *src, uint8_t *dest) { return executeCrypto(CARD_INS_ENCRYPT, src, dest); } +// Call with block6 void DecodeBlock6(uint8_t *src) { int resp_len = 0; uint8_t resp[254] = {0}; @@ -81,3 +83,12 @@ void DecodeBlock6(uint8_t *src) { PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9); } +// Call with block6 +uint8_t GetNumberBlocksForUserId(uint8_t *src) { + int resp_len = 0; + uint8_t resp[254] = {0}; + uint8_t c[] = {0x96, CARD_INS_NUMBLOCKS, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + memcpy(c + 5, src, 8); + ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + return resp[8]; +} \ No newline at end of file diff --git a/common/cardhelper.h b/common/cardhelper.h index 14ae23d1f..fcdd73cfe 100644 --- a/common/cardhelper.h +++ b/common/cardhelper.h @@ -18,4 +18,5 @@ bool IsCryptoHelperPresent(void); bool Encrypt(uint8_t *src, uint8_t *dest); bool Decrypt(uint8_t *src, uint8_t *dest); void DecodeBlock6(uint8_t *src); +uint8_t GetNumberBlocksForUserId(uint8_t *src); #endif From adb6a9abaa1c28f4834879ffe6040bcca3f7ed29 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 12 Mar 2020 12:42:50 +0200 Subject: [PATCH 101/298] disable RDP access --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b2ab84fb4..230bb44bf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,7 +24,7 @@ init: Add-AppveyorMessage -Message "[$env:APPVEYOR_REPO_COMMIT_SHORT]$env:appveyor_repo_name($env:APPVEYOR_REPO_BRANCH)" -Category Information -Details "repository: $env:appveyor_repo_name branch: $env:APPVEYOR_REPO_BRANCH release: $releasename" - iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) + # iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) clone_script: - ps: >- Write-Host "Removing ProxSpace..." -NoNewLine @@ -409,4 +409,4 @@ on_success: on_failure: - ps: Write-Host "Build error." -ForegroundColor Red on_finish: -- ps: $blockRdp = $false; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +- ps: # $blockRdp = $false; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) From 22e2599ce0bd4e2e37b9807084161a7c9f9c52d4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 10:53:25 +0100 Subject: [PATCH 102/298] chg: hf mfu info - colors --- client/cmdhfmfu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 5387cc855..78822ab06 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -527,7 +527,7 @@ static int ul_print_default(uint8_t *data) { uid[5] = data[6]; uid[6] = data[7]; - PrintAndLogEx(NORMAL, " UID : %s ", sprint_hex(uid, 7)); + PrintAndLogEx(NORMAL, " UID : " _YELLOW_("%s"), sprint_hex(uid, 7)); PrintAndLogEx(NORMAL, " UID[0] : %02X, %s", uid[0], getTagInfo(uid[0])); if (uid[0] == 0x05 && ((uid[1] & 0xf0) >> 4) == 2) { // is infineon and 66RxxP uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU @@ -546,17 +546,17 @@ static int ul_print_default(uint8_t *data) { // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 int crc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; if (data[3] == crc0) - PrintAndLogEx(NORMAL, " BCC0 : %02X, Ok", data[3]); + PrintAndLogEx(NORMAL, " BCC0 : %02X ( " _GREEN_("ok") ")", data[3]); else PrintAndLogEx(NORMAL, " BCC0 : %02X, crc should be %02X", data[3], crc0); int crc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6]; if (data[8] == crc1) - PrintAndLogEx(NORMAL, " BCC1 : %02X, Ok", data[8]); + PrintAndLogEx(NORMAL, " BCC1 : %02X ( " _GREEN_("ok") ")", data[8]); else PrintAndLogEx(NORMAL, " BCC1 : %02X, crc should be %02X", data[8], crc1); - PrintAndLogEx(NORMAL, " Internal : %02X, %sdefault", data[9], (data[9] == 0x48) ? "" : "not "); + PrintAndLogEx(NORMAL, " Internal : %02X ( %s)", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default") ); PrintAndLogEx(NORMAL, " Lock : %s - %s", sprint_hex(data + 10, 2), @@ -648,10 +648,10 @@ static int ndef_print_CC(uint8_t *data) { PrintAndLogEx(NORMAL, " Additional feature information"); PrintAndLogEx(NORMAL, " %02X", data[3]); PrintAndLogEx(NORMAL, " 00000000"); - PrintAndLogEx(NORMAL, " xxx - %02X : RFU (%s)", msb3, (msb3 == 0) ? _GREEN_("OK") : _RED_("Fail")); + PrintAndLogEx(NORMAL, " xxx - %02X : RFU ( %s)", msb3, (msb3 == 0) ? _GREEN_("ok") : _RED_("fail")); PrintAndLogEx(NORMAL, " x - %02X : %s special frame", sf, (sf) ? "support" : "don\'t support"); PrintAndLogEx(NORMAL, " x - %02X : %s lock block", lb, (lb) ? "support" : "don\'t support"); - PrintAndLogEx(NORMAL, " xx - %02X : RFU (%s)", mlrule, (mlrule == 0) ? _GREEN_("OK") : _RED_("Fail")); + PrintAndLogEx(NORMAL, " xx - %02X : RFU ( %s)", mlrule, (mlrule == 0) ? _GREEN_("ok") : _RED_("fail")); PrintAndLogEx(NORMAL, " x - %02X : IC %s multiple block reads", mbread, (mbread) ? "support" : "don\'t support"); return PM3_SUCCESS; } @@ -845,7 +845,7 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st if (authlim == 0) PrintAndLogEx(NORMAL, " - Unlimited password attempts"); else - PrintAndLogEx(NORMAL, " - Max number of password attempts is %d", authlim); + PrintAndLogEx(NORMAL, " - Max number of password attempts is " _YELLOW_("%d"), authlim); PrintAndLogEx(NORMAL, " - NFC counter %s", (nfc_cnf_en) ? "enabled" : "disabled"); PrintAndLogEx(NORMAL, " - NFC counter %s", (nfc_cnf_prot_pwd) ? "not protected" : "password protection enabled"); From 14e0b8e2dffa99b3bff97bfe5cae96a765d17867 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 11:40:55 +0100 Subject: [PATCH 103/298] text --- client/cmdhfmfu.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 78822ab06..a13e45d9b 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -62,19 +62,19 @@ static int usage_hf_mfu_info(void) { static int usage_hf_mfu_dump(void) { PrintAndLogEx(NORMAL, "Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); PrintAndLogEx(NORMAL, "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216"); - PrintAndLogEx(NORMAL, "and saves binary dump into the file `filename.bin` or `cardUID.bin`"); + PrintAndLogEx(NORMAL, "and saves binary dump into the file " _YELLOW_("`filename.bin`") " or " _YELLOW_("`cardUID.bin`") ); PrintAndLogEx(NORMAL, "It autodetects card type.\n"); PrintAndLogEx(NORMAL, "Usage: hf mfu dump k l f p q <#pages>"); PrintAndLogEx(NORMAL, " Options :"); PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); - PrintAndLogEx(NORMAL, " f : filename w/o .bin to save the dump as"); - PrintAndLogEx(NORMAL, " p : starting Page number to manually set a page to start the dump at"); + PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w/o .bin") "to save the dump as"); + PrintAndLogEx(NORMAL, " p : starting Page number to manually set a page to start the dump at"); PrintAndLogEx(NORMAL, " q : number of Pages to manually set how many pages to dump"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu dump"); - PrintAndLogEx(NORMAL, " hf mfu dump n myfile"); + PrintAndLogEx(NORMAL, " hf mfu dump f myfile"); PrintAndLogEx(NORMAL, " hf mfu dump k 00112233445566778899AABBCCDDEEFF"); PrintAndLogEx(NORMAL, " hf mfu dump k AABBCCDD\n"); return PM3_SUCCESS; @@ -86,10 +86,10 @@ static int usage_hf_mfu_restore(void) { PrintAndLogEx(NORMAL, " Options :"); PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); - PrintAndLogEx(NORMAL, " s : (optional) enable special write UID -MAGIC TAG ONLY-"); - PrintAndLogEx(NORMAL, " e : (optional) enable special write version/signature -MAGIC NTAG 21* ONLY-"); - PrintAndLogEx(NORMAL, " r : (optional) use the password found in dumpfile to configure tag. requires 'e' parameter to work"); - PrintAndLogEx(NORMAL, " f : filename w/o .bin to restore"); + PrintAndLogEx(NORMAL, " s : (optional) enable special write UID " _BLUE_("-MAGIC TAG ONLY-") ); + PrintAndLogEx(NORMAL, " e : (optional) enable special write version/signature " _BLUE_("-MAGIC NTAG 21* ONLY-") ); + PrintAndLogEx(NORMAL, " r : (optional) use the password found in dumpfile to configure tag. requires " _YELLOW_("'e'") "parameter to work"); + PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w/o .bin") "to restore"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu restore s f myfile"); @@ -129,7 +129,7 @@ static int usage_hf_mfu_wrbl(void) { } static int usage_hf_mfu_eload(void) { - PrintAndLogEx(NORMAL, "It loads emul dump from the file `filename.eml`"); + PrintAndLogEx(NORMAL, "It loads emul dump from the file " _YELLOW_("`filename.eml`") ); PrintAndLogEx(NORMAL, "Hint: See script dumptoemul-mfu.lua to convert the .bin to the eml"); PrintAndLogEx(NORMAL, "Usage: hf mfu eload u [numblocks]"); PrintAndLogEx(NORMAL, " Options:"); From 08f40ef310b0ac1a88815c53d6ebcda19f9881fc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 12:09:11 +0100 Subject: [PATCH 104/298] fix: hf mfu pwdgen - xyz --- common/generator.c | 76 ++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/common/generator.c b/common/generator.c index 6dbac2feb..768917492 100644 --- a/common/generator.c +++ b/common/generator.c @@ -34,42 +34,38 @@ // XYZ 3D printing // Vinglock //------------------------------------ -static void transform_D(uint8_t *ru) { - - const uint32_t c_D[] = { - 0x6D835AFC, 0x7D15CD97, 0x0942B409, 0x32F9C923, 0xA811FB02, 0x64F121E8, - 0xD1CC8B4E, 0xE8873E6F, 0x61399BBB, 0xF1B91926, 0xAC661520, 0xA21A31C9, - 0xD424808D, 0xFE118E07, 0xD18E728D, 0xABAC9E17, 0x18066433, 0x00E18E79, - 0x65A77305, 0x5AE9E297, 0x11FC628C, 0x7BB3431F, 0x942A8308, 0xB2F8FD20, +void transform_D(uint8_t* ru) { + + const uint32_t c_D[] = { + 0x6D835AFC, 0x7D15CD97, 0x0942B409, 0x32F9C923, 0xA811FB02, 0x64F121E8, + 0xD1CC8B4E, 0xE8873E6F, 0x61399BBB, 0xF1B91926, 0xAC661520, 0xA21A31C9, + 0xD424808D, 0xFE118E07, 0xD18E728D, 0xABAC9E17, 0x18066433, 0x00E18E79, + 0x65A77305, 0x5AE9E297, 0x11FC628C, 0x7BB3431F, 0x942A8308, 0xB2F8FD20, 0x5728B869, 0x30726D5A - }; + }; - //Transform - uint8_t i; - uint8_t p = 0; - uint32_t v1 = ((ru[3] << 24) | (ru[2] << 16) | (ru[1] << 8) | ru[0]) + c_D[p++]; - uint32_t v2 = ((ru[7] << 24) | (ru[6] << 16) | (ru[5] << 8) | ru[4]) + c_D[p++]; + //Transform + uint8_t i; + uint8_t p = 0; + uint32_t v1 = ((ru[3] << 24) | (ru[2] << 16) | (ru[1] << 8) | ru[0]) + c_D[p++]; + uint32_t v2 = ((ru[7] << 24) | (ru[6] << 16) | (ru[5] << 8) | ru[4]) + c_D[p++]; + for (i = 0; i < 12; i += 2) + { + uint32_t t1 = PM3_ROTL(v1 ^ v2, v2 & 0x1F) + c_D[p++]; + uint32_t t2 = PM3_ROTL(v2 ^ t1, t1 & 0x1F) + c_D[p++]; + v1 = PM3_ROTL(t1 ^ t2, t2 & 0x1F) + c_D[p++]; + v2 = PM3_ROTL(t2 ^ v1, v1 & 0x1F) + c_D[p++]; + } - for (i = 0; i < 12; i += 2) { - uint32_t xor1 = v1 ^ v2; - uint32_t t1 = ROTL(xor1, v2 & 0x1F) + c_D[p++]; - uint32_t xor2 = v2 ^ t1; - uint32_t t2 = ROTL(xor2, t1 & 0x1F) + c_D[p++]; - uint32_t xor3 = t1 ^ t2; - uint32_t xor4 = t2 ^ v1; - v1 = ROTL(xor3, t2 & 0x1F) + c_D[p++]; - v2 = ROTL(xor4, v1 & 0x1F) + c_D[p++]; - } - - //Re-use ru - ru[0] = v1 & 0xFF; - ru[1] = (v1 >> 8) & 0xFF; - ru[2] = (v1 >> 16) & 0xFF; - ru[3] = (v1 >> 24) & 0xFF; - ru[4] = v2 & 0xFF; - ru[5] = (v2 >> 8) & 0xFF; - ru[6] = (v2 >> 16) & 0xFF; - ru[7] = (v2 >> 24) & 0xFF; + //Re-use ru + ru[0] = v1 & 0xFF; + ru[1] = (v1 >> 8) & 0xFF; + ru[2] = (v1 >> 16) & 0xFF; + ru[3] = (v1 >> 24) & 0xFF; + ru[4] = v2 & 0xFF; + ru[5] = (v2 >> 8) & 0xFF; + ru[6] = (v2 >> 16) & 0xFF; + ru[7] = (v2 >> 24) & 0xFF; } // Transport system (IT) pwd generation algo nickname A. @@ -130,17 +126,23 @@ uint32_t ul_ev1_pwdgenC(uint8_t *uid) { // XYZ 3d printing pwd generation algo nickname D. uint32_t ul_ev1_pwdgenD(uint8_t *uid) { + uint8_t i; - uint8_t r = (uid[1] + uid[3] + uid[5]) & 7; // rotation offset - uint8_t ru[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // rotated UID + // rotation offset + uint8_t r = (uid[1] + uid[3] + uid[5]) & 7; + + // rotated UID + uint8_t ru[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; for (i = 0; i < 7; i++) ru[(i + r) & 7] = uid[i]; transform_D(ru); - // calc key + // offset + r = (ru[0] + ru[2] + ru[4] + ru[6]) & 3; + + // calc key uint32_t pwd = 0; - r = (ru[0] + ru[2] + ru[4] + ru[6]) & 3; // offset for (i = 0; i < 4; i++) pwd = ru[i + r] + (pwd << 8); From 437504eae67c2b37910cc31ffed064c2e3bd9a1b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 12:09:49 +0100 Subject: [PATCH 105/298] fix: hf mfu pwdgen - xyz forgot header --- include/common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/common.h b/include/common.h index 653000409..e7d6bba90 100644 --- a/include/common.h +++ b/include/common.h @@ -64,8 +64,8 @@ extern int DBGLEVEL; # define ROTR(x,n) (((uintmax_t)(x) >> (n)) | ((uintmax_t)(x) << ((sizeof(x) * 8) - (n)))) #endif -#ifndef ROTL -# define ROTL(x,n) (((uintmax_t)(x) << (n)) | ((uintmax_t)(x) >> ((sizeof(x) * 8) - (n)))) +#ifndef PM3_ROTL +# define PM3_ROTL(x,n) (((uintmax_t)(x) << (n)) | ((uintmax_t)(x) >> ((sizeof(x) * 8) - (n)))) #endif // endian change for 64bit From 656f35036d5096e052864693156e99fbc1a5493a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 13:01:23 +0100 Subject: [PATCH 106/298] text --- client/cmdhfmfu.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index a13e45d9b..120db2a9c 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -62,7 +62,7 @@ static int usage_hf_mfu_info(void) { static int usage_hf_mfu_dump(void) { PrintAndLogEx(NORMAL, "Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); PrintAndLogEx(NORMAL, "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216"); - PrintAndLogEx(NORMAL, "and saves binary dump into the file " _YELLOW_("`filename.bin`") " or " _YELLOW_("`cardUID.bin`") ); + PrintAndLogEx(NORMAL, "and saves binary dump into the file " _YELLOW_("`filename.bin`") "or " _YELLOW_("`cardUID.bin`") ); PrintAndLogEx(NORMAL, "It autodetects card type.\n"); PrintAndLogEx(NORMAL, "Usage: hf mfu dump k l f p q <#pages>"); PrintAndLogEx(NORMAL, " Options :"); @@ -82,14 +82,14 @@ static int usage_hf_mfu_dump(void) { static int usage_hf_mfu_restore(void) { PrintAndLogEx(NORMAL, "Restore dumpfile onto card."); - PrintAndLogEx(NORMAL, "Usage: hf mfu restore [h] [l] [s] k n "); + PrintAndLogEx(NORMAL, "Usage: hf mfu restore [h] [l] [s] k n "); PrintAndLogEx(NORMAL, " Options :"); PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); PrintAndLogEx(NORMAL, " s : (optional) enable special write UID " _BLUE_("-MAGIC TAG ONLY-") ); PrintAndLogEx(NORMAL, " e : (optional) enable special write version/signature " _BLUE_("-MAGIC NTAG 21* ONLY-") ); PrintAndLogEx(NORMAL, " r : (optional) use the password found in dumpfile to configure tag. requires " _YELLOW_("'e'") "parameter to work"); - PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w/o .bin") "to restore"); + PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w .bin") "to restore"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu restore s f myfile"); @@ -130,7 +130,7 @@ static int usage_hf_mfu_wrbl(void) { static int usage_hf_mfu_eload(void) { PrintAndLogEx(NORMAL, "It loads emul dump from the file " _YELLOW_("`filename.eml`") ); - PrintAndLogEx(NORMAL, "Hint: See script dumptoemul-mfu.lua to convert the .bin to the eml"); + PrintAndLogEx(NORMAL, "Hint: See " _YELLOW_("`script run dumptoemul-mfu`") "to convert the .bin to the eml"); PrintAndLogEx(NORMAL, "Usage: hf mfu eload u [numblocks]"); PrintAndLogEx(NORMAL, " Options:"); PrintAndLogEx(NORMAL, " h : this help"); @@ -174,6 +174,7 @@ static int usage_hf_mfu_ucauth(void) { } static int usage_hf_mfu_ucsetpwd(void) { + PrintAndLogEx(NORMAL, "Set 3DES password on Mifare Ultralight-C tag."); PrintAndLogEx(NORMAL, "Usage: hf mfu setpwd "); PrintAndLogEx(NORMAL, " [password] - (32 hex symbols)"); PrintAndLogEx(NORMAL, ""); @@ -186,7 +187,8 @@ static int usage_hf_mfu_ucsetpwd(void) { static int usage_hf_mfu_ucsetuid(void) { PrintAndLogEx(NORMAL, "Usage: hf mfu setuid "); PrintAndLogEx(NORMAL, " [uid] - (14 hex symbols)"); - PrintAndLogEx(NORMAL, "\nThis only works for Magic Ultralight tags."); + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, "This only works for " _BLUE_("Magic Ultralight") "tags."); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu setuid 11223344556677"); @@ -223,7 +225,7 @@ static int usage_hf_mfu_pwdgen(void) { } static int usage_hf_mfu_otp_tearoff(void) { - PrintAndLogEx(NORMAL, "Tear-off test against OTP block on MFU tags - More help sooner or later\n"); + PrintAndLogEx(NORMAL, "Tear-off test against OTP block on MFU tags."); PrintAndLogEx(NORMAL, "Usage: hf mfu otptear [h]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); @@ -1276,7 +1278,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password:" _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") "|| Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1286,7 +1288,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password:" _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") "|| Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1296,7 +1298,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { num_to_bytes(ul_ev1_pwdgenC(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password:" _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") "|| Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1316,7 +1318,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { key = default_pwd_pack[i]; len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password:" _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") "|| Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); break; } else { if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; From 6f1ed5a9bf90466534dfa12e8c6702f332bfb979 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 13:51:54 +0100 Subject: [PATCH 107/298] cppchecker shadow var --- tools/hitag2crack/crack2/ht2crack2buildtable.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/hitag2crack/crack2/ht2crack2buildtable.c b/tools/hitag2crack/crack2/ht2crack2buildtable.c index ffabd8f2e..70a6c51ef 100644 --- a/tools/hitag2crack/crack2/ht2crack2buildtable.c +++ b/tools/hitag2crack/crack2/ht2crack2buildtable.c @@ -143,16 +143,16 @@ void writetable(struct table *t1) { // store value in table void store(unsigned char *data) { - unsigned char d1, d2; + unsigned char d_1, d_2; int offset; struct table *t1; // use the first two bytes as an index - d1 = data[0]; - d2 = data[1]; - offset = (d1 * 0x100) + d2; + d_1 = data[0]; + d_2 = data[1]; + offset = (d_1 * 0x100) + d_2; - if (debug) printf("store, d1=%02X, d2=%02X, offset = %d\n", d1, d2, offset); + if (debug) printf("store, d1=%02X, d2=%02X, offset = %d\n", d_1, d_2, offset); // get pointer to table entry t1 = t + offset; From c7d2ccb8bd4177e240d836759b64a2802641847f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 13:52:08 +0100 Subject: [PATCH 108/298] cppchecker function name --- tools/hitag2crack/crack2/hitagcrypto.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/hitag2crack/crack2/hitagcrypto.c b/tools/hitag2crack/crack2/hitagcrypto.c index 5ebfc5ae9..3c4f84bc6 100644 --- a/tools/hitag2crack/crack2/hitagcrypto.c +++ b/tools/hitag2crack/crack2/hitagcrypto.c @@ -228,18 +228,17 @@ static uint32_t hitag2_crypt(uint64_t x); #define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \ ((S >> (C - 3)) & 8) ) - -static uint32_t hitag2_crypt(uint64_t s) { +static uint32_t hitag2_crypt(uint64_t x) { const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 uint32_t bitindex; - bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1; - bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02; - bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04; - bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08; - bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; + bitindex = (ht2_function4a >> pickbits2_2(x, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(x, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4(x, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(x, 27, 30, 32)) & 0x08; + bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(x, 33, 42, 45)) & 0x10; DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); return (ht2_function5c >> bitindex) & 1; From f6e013c7fc5a28166623496c2a179ac57f16b2c4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 13:52:23 +0100 Subject: [PATCH 109/298] cppchecker --- armsrc/hitag2crack.c | 10 +++++----- armsrc/hitag2crack.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/armsrc/hitag2crack.c b/armsrc/hitag2crack.c index 2d0d868b9..d66f740bc 100644 --- a/armsrc/hitag2crack.c +++ b/armsrc/hitag2crack.c @@ -300,7 +300,7 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t response[32]; int i; - if ((pagenum < 0) || (pagenum > 7)) { + if (pagenum > 7) { UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n"); return false; } @@ -351,7 +351,7 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, // cmd is the binarray of the encrypted command to send; // len is the length of the encrypted command. bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len) { - uint8_t tmp[37]; +// uint8_t tmp[37]; uint8_t uid[9]; uint8_t e_page3str[9]; int ret = 0; @@ -551,14 +551,14 @@ bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) { uint8_t uid[32]; uint8_t nrar[64]; uint8_t e_firstcmd[10]; - uint8_t e_page0cmd[10]; +// uint8_t e_page0cmd[10]; // uint8_t keybits[2080]; uint8_t *keybits = DataBuff; uint8_t keybitshex[67]; int kslen; int ksoffset; - uint8_t pagehex[9]; - uint8_t temp[20]; +// uint8_t pagehex[9]; +// uint8_t temp[20]; int i; uint8_t *spaceptr = NULL; diff --git a/armsrc/hitag2crack.h b/armsrc/hitag2crack.h index 75fa54546..af3e41d14 100644 --- a/armsrc/hitag2crack.h +++ b/armsrc/hitag2crack.h @@ -19,9 +19,9 @@ bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, b bool hitag2crack_rng_init(uint8_t *response, uint8_t *input); bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex); -bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *hex); +bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr); bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex); -bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *hex); +bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr); bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex); bool hitag2crack_send_auth(uint8_t *nrar); From 294d2aa96b2c76107875419a1f540287bbc63c9d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 13:52:29 +0100 Subject: [PATCH 110/298] cppchecker --- armsrc/hitag2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 2df49ac3d..7e4c7ca14 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -544,7 +544,7 @@ bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *t // will receive 32-bit configuration page } else if (bSelecting) { // Initiate auth - tx[0] = 0xa0 | key_no >> 4; // WRCPAGE + tx[0] = 0xa0 | (key_no); // WRCPAGE tx[1] = blocknr << 4; crc = hitag_crc(tx, 12); tx[1] |= crc >> 4; From f13149826c22b7917da90e3aa66429d87a0f6203 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 13:52:55 +0100 Subject: [PATCH 111/298] cppchecker format macro --- armsrc/Standalone/lf_icehid.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index d66186c9d..d68f8423d 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -105,7 +105,7 @@ uint32_t IceEM410xdemod() { memset(entry, 0, sizeof(entry)); if (size == 128) { - sprintf((char *)entry, "EM XL TAG ID: %06lx%08lx%08lx - (%05ld_%03ld_%08ld)\n", + sprintf((char *)entry, "EM XL TAG ID: %06"PRIx32"%08"PRIx32"%08"PRIx32" - (%05"PRIu32"_%03"PRIu32"_%08"PRIu32")\n", hi, (uint32_t)(lo >> 32), (uint32_t)lo, @@ -113,7 +113,7 @@ uint32_t IceEM410xdemod() { (uint32_t)((lo >> 16LL) & 0xFF), (uint32_t)(lo & 0xFFFFFF)); } else { - sprintf((char *)entry, "EM TAG ID: %02lx%08lx - (%05ld_%03ld_%08ld)\n", + sprintf((char *)entry, "EM TAG ID: %02"PRIx32"%08"PRIx32" - (%05"PRIu32"_%03"PRIu32"_%08"PRIu32")\n", (uint32_t)(lo >> 32), (uint32_t)lo, (uint32_t)(lo & 0xFFFF), @@ -160,16 +160,16 @@ uint32_t IceAWIDdemod() { uint8_t fac = bytebits_to_byte(dest + 9, 8); uint32_t cardnum = bytebits_to_byte(dest + 17, 16); uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen); - sprintf((char *)entry, "AWID bit len: %d, FC: %d, Card: %ld - Wiegand: %lx, Raw: %08lx%08lx%08lx\n", fmtLen, fac, cardnum, code1, rawHi2, rawHi, rawLo); + sprintf((char *)entry, "AWID bit len: %d, FC: %d, Card: %"PRIu32" - Wiegand: %"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, fac, cardnum, code1, rawHi2, rawHi, rawLo); } else { uint32_t cardnum = bytebits_to_byte(dest + 8 + (fmtLen - 17), 16); if (fmtLen > 32) { uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen - 32); uint32_t code2 = bytebits_to_byte(dest + 8 + (fmtLen - 32), 32); - sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %ld - Wiegand: %lx%08lx, Raw: %08lx%08lx%08lx\n", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); + sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %"PRIu32" - Wiegand: %"PRIx32"%08"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); } else { uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen); - sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %ld - Wiegand: %lx, Raw: %08lx%08lx%08lx\n", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); + sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %"PRIu32" - Wiegand: %"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); } } @@ -209,7 +209,7 @@ uint32_t IceIOdemod() { uint8_t entry[64]; memset(entry, 0, sizeof(entry)); - sprintf((char *)entry, "IO Prox XSF(%02d)%02x:%05d (%08lx%08lx)\n" + sprintf((char *)entry, "IO Prox XSF(%02u)%02x:%05u (%08"PRIx32"%08"PRIx32")\n" , version , facilitycode , number @@ -249,7 +249,7 @@ uint32_t IceHIDDemod() { // go over previously decoded manchester data and decode into usable tag ID if (hi2 != 0) { //extra large HID tags 88/192 bits - sprintf((char *)entry, "HID large: %lx%08lx%08lx (%ld)\n", + sprintf((char *)entry, "HID large: %"PRIx32"%08"PRIx32"%08"PRIx32" (%"PRIu32")\n", hi2, hi, lo, @@ -296,7 +296,7 @@ uint32_t IceHIDDemod() { fac = ((hi & 0xF) << 12) | (lo >> 20); } - sprintf((char *)entry, "HID: %lx%08lx (%ld) Format: %d bit FC: %ld Card: %ld\n", + sprintf((char *)entry, "HID: %"PRIx32"%08"PRIx32" (%"PRIu32") Format: %d bit FC: %"PRIu32" Card: %"PRIu32"\n", hi, lo, (lo >> 1) & 0xFFFF, From f761874347a864421c66db0372e4b7e945f34782 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 14:13:59 +0100 Subject: [PATCH 112/298] cppcheck macro sizeof --- common/generator.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/common/generator.c b/common/generator.c index 768917492..4be63a925 100644 --- a/common/generator.c +++ b/common/generator.c @@ -35,14 +35,14 @@ // Vinglock //------------------------------------ void transform_D(uint8_t* ru) { - - const uint32_t c_D[] = { - 0x6D835AFC, 0x7D15CD97, 0x0942B409, 0x32F9C923, 0xA811FB02, 0x64F121E8, - 0xD1CC8B4E, 0xE8873E6F, 0x61399BBB, 0xF1B91926, 0xAC661520, 0xA21A31C9, - 0xD424808D, 0xFE118E07, 0xD18E728D, 0xABAC9E17, 0x18066433, 0x00E18E79, - 0x65A77305, 0x5AE9E297, 0x11FC628C, 0x7BB3431F, 0x942A8308, 0xB2F8FD20, + + const uint32_t c_D[] = { + 0x6D835AFC, 0x7D15CD97, 0x0942B409, 0x32F9C923, 0xA811FB02, 0x64F121E8, + 0xD1CC8B4E, 0xE8873E6F, 0x61399BBB, 0xF1B91926, 0xAC661520, 0xA21A31C9, + 0xD424808D, 0xFE118E07, 0xD18E728D, 0xABAC9E17, 0x18066433, 0x00E18E79, + 0x65A77305, 0x5AE9E297, 0x11FC628C, 0x7BB3431F, 0x942A8308, 0xB2F8FD20, 0x5728B869, 0x30726D5A - }; + }; //Transform uint8_t i; @@ -51,10 +51,14 @@ void transform_D(uint8_t* ru) { uint32_t v2 = ((ru[7] << 24) | (ru[6] << 16) | (ru[5] << 8) | ru[4]) + c_D[p++]; for (i = 0; i < 12; i += 2) { - uint32_t t1 = PM3_ROTL(v1 ^ v2, v2 & 0x1F) + c_D[p++]; - uint32_t t2 = PM3_ROTL(v2 ^ t1, t1 & 0x1F) + c_D[p++]; - v1 = PM3_ROTL(t1 ^ t2, t2 & 0x1F) + c_D[p++]; - v2 = PM3_ROTL(t2 ^ v1, v1 & 0x1F) + c_D[p++]; + uint32_t tempA = v1 ^ v2; + uint32_t t1 = PM3_ROTL(tempA, v2 & 0x1F) + c_D[p++]; + uint32_t tempB = v2 ^ t1; + uint32_t t2 = PM3_ROTL(tempB, t1 & 0x1F) + c_D[p++]; + tempA = t1 ^ t2; + v1 = PM3_ROTL(tempA, t2 & 0x1F) + c_D[p++]; + tempB = t2 ^ v1; + v2 = PM3_ROTL(tempB, v1 & 0x1F) + c_D[p++]; } //Re-use ru From c3024fe9f256e27b4238a4e016a879db29f6b657 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 14:14:19 +0100 Subject: [PATCH 113/298] cppcheck shadow --- tools/hitag2crack/crack2/ht2crack2buildtable.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/hitag2crack/crack2/ht2crack2buildtable.c b/tools/hitag2crack/crack2/ht2crack2buildtable.c index 70a6c51ef..0aca200ef 100644 --- a/tools/hitag2crack/crack2/ht2crack2buildtable.c +++ b/tools/hitag2crack/crack2/ht2crack2buildtable.c @@ -362,10 +362,10 @@ void makedirs() { } static int datacmp(const void *p1, const void *p2, void *dummy) { - unsigned char *d1 = (unsigned char *)p1; - unsigned char *d2 = (unsigned char *)p2; + unsigned char *d_1 = (unsigned char *)p1; + unsigned char *d_2 = (unsigned char *)p2; - return memcmp(d1, d2, DATASIZE); + return memcmp(d_1, d_2, DATASIZE); } void *sorttable(void *d) { From 53ecdaf78f9fab0654df3b656a9889f296a9607a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 14:14:30 +0100 Subject: [PATCH 114/298] cppcheck func name --- tools/hitag2crack/crack3/hitagcrypto.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/hitag2crack/crack3/hitagcrypto.c b/tools/hitag2crack/crack3/hitagcrypto.c index 23b88228d..21662b43e 100644 --- a/tools/hitag2crack/crack3/hitagcrypto.c +++ b/tools/hitag2crack/crack3/hitagcrypto.c @@ -229,17 +229,17 @@ static uint32_t hitag2_crypt(uint64_t x); ((S >> (C - 3)) & 8) ) -static uint32_t hitag2_crypt(uint64_t s) { +static uint32_t hitag2_crypt(uint64_t x) { const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 uint32_t bitindex; - bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1; - bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02; - bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04; - bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08; - bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; + bitindex = (ht2_function4a >> pickbits2_2(x, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(x, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4(x, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(x, 27, 30, 32)) & 0x08; + bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(x, 33, 42, 45)) & 0x10; DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); return (ht2_function5c >> bitindex) & 1; From 6f20f86c2d7eb2f6900172dac6d678bfbff061b6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 14:22:53 +0100 Subject: [PATCH 115/298] cppchecker - param name --- client/cmdhflto.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index dfbca68c1..c5b73c0c6 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -524,7 +524,7 @@ static int CmdHfLTODump(const char *Cmd) { return PM3_SUCCESS; } -int restoreLTO(uint8_t *dump_data, bool verbose) { +int restoreLTO(uint8_t *dump, bool verbose) { clearCommandBuffer(); lto_switch_on_field(); @@ -545,13 +545,13 @@ int restoreLTO(uint8_t *dump_data, bool verbose) { for (uint8_t blk = 2; blk < 255; blk++) { for (int i = 0; i < 32; i++) { - blkData[i] = dump_data[i + blk * 32]; + blkData[i] = dump[i + blk * 32]; } ret_val = lto_wrbl(blk, blkData, verbose); if (ret_val == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "BLK %03d: " _YELLOW_("write success"), blk); + PrintAndLogEx(SUCCESS, "Block %03d - " _YELLOW_("write success"), blk); } else { lto_switch_off_field(); return ret_val; From e460a4e6ca6fe054ff9a2b58e65ad58679566e68 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 14:23:34 +0100 Subject: [PATCH 116/298] cppchecker - param name --- client/cmdlfindala.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfindala.h b/client/cmdlfindala.h index 1d0762f5f..65ed29e61 100644 --- a/client/cmdlfindala.h +++ b/client/cmdlfindala.h @@ -19,6 +19,6 @@ int detectIndala26(uint8_t *bitStream, size_t *size, uint8_t *invert); int detectIndala64(uint8_t *bitStream, size_t *size, uint8_t *invert); int detectIndala224(uint8_t *bitStream, size_t *size, uint8_t *invert); int demodIndala(void); -int getIndalaBits(uint8_t fc, uint16_t csn, uint8_t *bits); +int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits); #endif From 43e1c5f22deb0b1e1f337fbb81f2f2bf46bc5703 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 14:27:50 +0100 Subject: [PATCH 117/298] cppchecker - shadow --- client/fileutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/fileutils.c b/client/fileutils.c index d9e6e4445..f47e32b73 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -70,7 +70,7 @@ struct wave_info_t { char tag[4]; uint32_t size; } PACKED audio_data; -} PACKED wave_info; +} PACKED; /** * @brief checks if a file exists From bf597dd2d22d678782da0c49e5bfc27dfca188a6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 14:28:02 +0100 Subject: [PATCH 118/298] cppchecker - signed shift --- client/cmdlfkeri.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 3c7863361..c698842a6 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -144,7 +144,7 @@ static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *I *CardID = *CardID | Parity; // Bit 31 was fixed but not in check/parity bits - *CardID |= (1 << 31); + *CardID |= (uint32_t)(1 << 31); PrintAndLogEx(SUCCESS, "Scrambled FC : %d - Card ID : %d to RAW : E0000000%08X",*FC,*ID,*CardID); } From a9aaa3040ec12900b86294b4273645771b1f0a6e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 14:34:18 +0100 Subject: [PATCH 119/298] cppchecker - format print --- tools/hitag2crack/crack3/ht2crack3.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/hitag2crack/crack3/ht2crack3.c b/tools/hitag2crack/crack3/ht2crack3.c index 747f7785c..11cab5ed9 100644 --- a/tools/hitag2crack/crack3/ht2crack3.c +++ b/tools/hitag2crack/crack3/ht2crack3.c @@ -381,14 +381,14 @@ int main(int argc, char *argv[]) { while (getline(&buf, &lenbuf, fp) > 0) { buft1 = strchr(buf, ' '); if (!buft1) { - printf("invalid file input on line %d\n", numnrar + 1); + printf("invalid file input on line %u\n", numnrar + 1); exit(1); } *buft1 = 0x00; buft1++; buft2 = strchr(buft1, '\n'); if (!buft2) { - printf("no CR on line %d\n", numnrar + 1); + printf("no CR on line %u\n", numnrar + 1); exit(1); } *buft2 = 0x00; @@ -406,7 +406,7 @@ int main(int argc, char *argv[]) { fclose(fp); fp = NULL; - printf("Loaded %d NrAr pairs\n", numnrar); + printf("Loaded %u NrAr pairs\n", numnrar); // create table of thread data tdata = (struct threaddata *)malloc(sizeof(struct threaddata) * NUM_THREADS); From 022eacecdce350151345f1e0ca4f031b5b4252d9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 14:37:49 +0100 Subject: [PATCH 120/298] format --- tools/hitag2crack/crack3/ht2crack3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/hitag2crack/crack3/ht2crack3.c b/tools/hitag2crack/crack3/ht2crack3.c index 11cab5ed9..da35bbd14 100644 --- a/tools/hitag2crack/crack3/ht2crack3.c +++ b/tools/hitag2crack/crack3/ht2crack3.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "HardwareProfile.h" #include "rfidler.h" @@ -243,7 +244,7 @@ void *crack(void *d) { // find keys for (klower = data->klowerstart; klower < (data->klowerstart + data->klowerrange); klower++) { - printf("trying klower = 0x%05lx\n", klower); + printf("trying klower = 0x%05"PRIx64"\n", klower); // build table count = 0; for (y = 0; y < 0x40000; y++) { @@ -304,7 +305,7 @@ void *crack(void *d) { if ((found) && (!badguess)) { // brute - printf("possible partial key found: 0x%012lx\n", ((uint64_t)kmiddle << 16) | klower); + printf("possible partial key found: 0x%012"PRIx64"\n", ((uint64_t)kmiddle << 16) | klower); if (testkey(&foundkey, uid, (kmiddle << 16 | klower), TnRaR[0].nR, TnRaR[0].aR) && testkey(&foundkey, uid, (kmiddle << 16 | klower), TnRaR[1].nR, TnRaR[1].aR)) { From 21e6cff4ba96b23076a1a37345b4771c074c4989 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 14:42:04 +0100 Subject: [PATCH 121/298] format printf --- tools/hitag2crack/crack4/ht2crack4.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/hitag2crack/crack4/ht2crack4.c b/tools/hitag2crack/crack4/ht2crack4.c index 44952f4b7..5c2d11c2e 100644 --- a/tools/hitag2crack/crack4/ht2crack4.c +++ b/tools/hitag2crack/crack4/ht2crack4.c @@ -270,14 +270,14 @@ void init_guess_table(char *filename, char *uidstr) { while ((getline(&buf, &lenbuf, fp) > 0) && (num_nRaR < MAX_NONCES)) { buft1 = strchr(buf, ' '); if (!buft1) { - printf("invalid file input on line %d\n", num_nRaR + 1); + printf("invalid file input on line %u\n", num_nRaR + 1); exit(1); } *buft1 = 0x00; buft1++; buft2 = strchr(buft1, '\n'); if (!buft2) { - printf("no CR on line %d\n", num_nRaR + 1); + printf("no CR on line %u\n", num_nRaR + 1); exit(1); } *buft2 = 0x00; @@ -294,7 +294,7 @@ void init_guess_table(char *filename, char *uidstr) { fclose(fp); fp = NULL; - fprintf(stderr, "Loaded %d nRaR pairs\n", num_nRaR); + fprintf(stderr, "Loaded %u nRaR pairs\n", num_nRaR); // set key and copy in enc_nR and ks values // set score to -1.0 to distinguish them from 0 scores @@ -516,7 +516,7 @@ void score_all_traces(unsigned int size) { // start the threads for (i = 0; i < NUM_THREADS; i++) { if (pthread_create(&(threads[i]), NULL, score_some_traces, (void *)(tdata + i))) { - printf("cannot start thread %d\n", i); + printf("cannot start thread %u\n", i); exit(1); } } @@ -524,7 +524,7 @@ void score_all_traces(unsigned int size) { // wait for threads to end for (i = 0; i < NUM_THREADS; i++) { if (pthread_join(threads[i], &status)) { - printf("cannot join thread %d\n", i); + printf("cannot join thread %u\n", i); exit(1); } } @@ -620,13 +620,13 @@ void crack() { uint64_t foundkey; for (i = 16; i <= 48; i++) { - fprintf(stderr, "round %2d, size=%2d\n", i - 16, i); + fprintf(stderr, "round %2u, size=%2u\n", i - 16, i); execute_round(i); // print some metrics revkey = rev64(guesses[0].key); foundkey = ((revkey >> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000); - fprintf(stderr, " guess=%012" PRIx64 ", num_guesses = %d, top score=%1.10f, min score=%1.10f\n", foundkey, num_guesses, guesses[0].score, guesses[num_guesses - 1].score); + fprintf(stderr, " guess=%012" PRIx64 ", num_guesses = %u, top score=%1.10f, min score=%1.10f\n", foundkey, num_guesses, guesses[0].score, guesses[num_guesses - 1].score); } } @@ -745,7 +745,7 @@ void test() { packed = packstate(lfsr); if (hitag2_crypt(lfsr) != f20(packed)) { - printf(" * * * FAIL: %3" PRIu64 ": 0x%012" PRIx64 " = %d, 0x%012" PRIx64 " = 0x%05" PRIx64 "\n", i, lfsr, hitag2_crypt(lfsr), packed, f20(packed)); + printf(" * * * FAIL: %3" PRIu64 ": 0x%012" PRIx64 " = %u, 0x%012" PRIx64 " = 0x%05" PRIx64 "\n", i, lfsr, hitag2_crypt(lfsr), packed, f20(packed)); } } @@ -821,7 +821,7 @@ int main(int argc, char *argv[]) { if ((tot_nRaR > 0) && (tot_nRaR <= num_nRaR)) { num_nRaR = tot_nRaR; } - fprintf(stderr, "Using %d nRaR pairs\n", num_nRaR); + fprintf(stderr, "Using %u nRaR pairs\n", num_nRaR); crack(); From c46119d7553d1366ada9b875a259ff057b53a4a9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 15:03:11 +0100 Subject: [PATCH 122/298] cppchecker - format print --- tools/hitag2crack/crack4/ht2crack4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/hitag2crack/crack4/ht2crack4.c b/tools/hitag2crack/crack4/ht2crack4.c index 5c2d11c2e..54e23d550 100644 --- a/tools/hitag2crack/crack4/ht2crack4.c +++ b/tools/hitag2crack/crack4/ht2crack4.c @@ -575,7 +575,7 @@ void check_supplied_testkey(unsigned int size) { for (i = 0; i < num_guesses; i++) { if (guesses[i].key == partkey) { - fprintf(stderr, " supplied test key score = %1.10f, position = %d\n", guesses[i].score, i); + fprintf(stderr, " supplied test key score = %1.10f, position = %u\n", guesses[i].score, i); return; } } From 2f85bced17dee80fbe0b3cb0e8b481388c570693 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 13 Mar 2020 15:04:07 +0100 Subject: [PATCH 123/298] cppchecker func name --- tools/hitag2crack/crack4/hitagcrypto.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/hitag2crack/crack4/hitagcrypto.c b/tools/hitag2crack/crack4/hitagcrypto.c index 23b88228d..21662b43e 100644 --- a/tools/hitag2crack/crack4/hitagcrypto.c +++ b/tools/hitag2crack/crack4/hitagcrypto.c @@ -229,17 +229,17 @@ static uint32_t hitag2_crypt(uint64_t x); ((S >> (C - 3)) & 8) ) -static uint32_t hitag2_crypt(uint64_t s) { +static uint32_t hitag2_crypt(uint64_t x) { const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 uint32_t bitindex; - bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1; - bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02; - bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04; - bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08; - bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; + bitindex = (ht2_function4a >> pickbits2_2(x, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(x, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4(x, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(x, 27, 30, 32)) & 0x08; + bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(x, 33, 42, 45)) & 0x10; DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); return (ht2_function5c >> bitindex) & 1; From 266f2f0fc89799c7e1d6c5515a690c110562b60e Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sat, 14 Mar 2020 01:09:25 +1100 Subject: [PATCH 124/298] Add colour to `lf hid` commands --- CHANGELOG.md | 1 + client/cmdlfhid.c | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa81e6baa..3f84700e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Add colour to `lf hid` commands in cmdlfhid.c - Change `script run hf_bruteforce -s start_id -e end_id -t timeout -x mifare_card_type` - The hf_bruteforce card script now requires Mifare type (mfc or mfu) (@dunderhay) - Updated `hf_bruteforce.lua` script - added support for brute forcing Mifare Ultralight EV1 cards (@dunderhay) - Added `hf mf personlize` - personalize the UID of a Mifare Classic EV1 card (@pwpiwi) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index eb388faa6..c13882221 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -162,7 +162,7 @@ static int CmdHIDDemod(const char *Cmd) { uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); if (size == 0) { - PrintAndLogEx(DEBUG, "DEBUG: Error - HID not enough samples"); + PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples")); return PM3_ESOFT; } //get binary from fsk wave @@ -171,17 +171,17 @@ static int CmdHIDDemod(const char *Cmd) { if (idx < 0) { if (idx == -1) - PrintAndLogEx(DEBUG, "DEBUG: Error - HID not enough samples"); + PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples")); else if (idx == -2) - PrintAndLogEx(DEBUG, "DEBUG: Error - HID just noise detected"); + PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID just noise detected")); else if (idx == -3) - PrintAndLogEx(DEBUG, "DEBUG: Error - HID problem during FSK demod"); + PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID problem during FSK demod")); else if (idx == -4) - PrintAndLogEx(DEBUG, "DEBUG: Error - HID preamble not found"); + PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID preamble not found")); else if (idx == -5) - PrintAndLogEx(DEBUG, "DEBUG: Error - HID error in Manchester data, size %zu", size); + PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error in Manchester data, size %zu, size")); else - PrintAndLogEx(DEBUG, "DEBUG: Error - HID error demoding fsk %d", idx); + PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error demoding fsk %d, idx")); return PM3_ESOFT; } @@ -190,12 +190,12 @@ static int CmdHIDDemod(const char *Cmd) { setClockGrid(50, waveIdx + (idx * 50)); if (hi2 == 0 && hi == 0 && lo == 0) { - PrintAndLogEx(DEBUG, "DEBUG: Error - HID no values found"); + PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID no values found")); return PM3_ESOFT; } if (hi2 != 0) { //extra large HID tags - PrintAndLogEx(SUCCESS, "HID Prox TAG ID: %x%08x%08x (%u)", hi2, hi, lo, (lo >> 1) & 0xFFFF); + PrintAndLogEx(SUCCESS, "HID Prox TAG ID: " _GREEN_("%x%08x%08x (%u)"), hi2, hi, lo, (lo >> 1) & 0xFFFF); } else { //standard HID tags <38 bits uint8_t fmtLen = 0; uint32_t cc = 0; @@ -241,14 +241,14 @@ static int CmdHIDDemod(const char *Cmd) { fc = ((hi & 0xF) << 12) | (lo >> 20); } if (fmtLen == 32 && (lo & 0x40000000)) { //if 32 bit and Kastle bit set - PrintAndLogEx(SUCCESS, "HID Prox TAG (Kastle format) ID: %x%08x (%u) - Format Len: 32bit - CC: %u - FC: %u - Card: %u", hi, lo, (lo >> 1) & 0xFFFF, cc, fc, cardnum); + PrintAndLogEx(SUCCESS, "HID Prox TAG (Kastle format) ID: " _GREEN_("%x%08x (%u)")"- Format Len: 32bit - CC: %u - FC: %u - Card: %u", hi, lo, (lo >> 1) & 0xFFFF, cc, fc, cardnum); } else { - PrintAndLogEx(SUCCESS, "HID Prox TAG ID: %x%08x (%u) - Format Len: %ubit - OEM: %03u - FC: %u - Card: %u", + PrintAndLogEx(SUCCESS, "HID Prox TAG ID: " _GREEN_("%x%08x (%u)")"- Format Len: %ubit - OEM: %03u - FC: %u - Card: %u", hi, lo, cardnum, fmtLen, oem, fc, cardnum); } } - PrintAndLogEx(DEBUG, "DEBUG: HID idx: %d, Len: %zu, Printing Demod Buffer:", idx, size); + PrintAndLogEx(DEBUG, "DEBUG: HID idx: " _GREEN_("%d, Len: %zu")", Printing Demod Buffer:", idx, size); if (g_debugMode) printDemodBuff(); @@ -288,14 +288,14 @@ static int CmdHIDSim(const char *Cmd) { lo = (lo << 4) | (n & 0xf); } - PrintAndLogEx(INFO, "Simulating HID tag with long ID %x%08x%08x", hi2, hi, lo); + PrintAndLogEx(INFO, "Simulating HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo); payload.longFMT = 1; } else { while (sscanf(&Cmd[i++], "%1x", &n) == 1) { hi = (hi << 4) | (lo >> 28); lo = (lo << 4) | (n & 0xf); } - PrintAndLogEx(SUCCESS, "Simulating HID tag with ID %x%08x", hi, lo); + PrintAndLogEx(SUCCESS, "Simulating HID tag with ID: " _GREEN_("%x%08x"), hi, lo); hi2 = 0; } @@ -331,7 +331,7 @@ static int CmdHIDClone(const char *Cmd) { lo = (lo << 4) | (n & 0xf); } - PrintAndLogEx(INFO, "Preparing to clone HID tag with long ID %x%08x%08x", hi2, hi, lo); + PrintAndLogEx(INFO, "Preparing to clone HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo); longid[0] = 1; } else { @@ -339,7 +339,7 @@ static int CmdHIDClone(const char *Cmd) { hi = (hi << 4) | (lo >> 28); lo = (lo << 4) | (n & 0xf); } - PrintAndLogEx(INFO, "Preparing to clone HID tag with ID %x%08x", hi, lo); + PrintAndLogEx(INFO, "Preparing to clone HID tag with ID: " _GREEN_("%x%08x"), hi, lo); hi2 = 0; } @@ -400,7 +400,7 @@ static int CmdHIDBrute(const char *Cmd) { param_getstr(Cmd, cmdp + 1, format, sizeof(format)); format_idx = HIDFindCardFormat(format); if (format_idx == -1) { - PrintAndLogEx(WARNING, "Unknown format: %s", format); + PrintAndLogEx(WARNING, _YELLOW_("Unknown format: %s"), format); errors = true; } cmdp += 2; @@ -431,7 +431,7 @@ static int CmdHIDBrute(const char *Cmd) { cmdp++; break; default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, _YELLOW_("Unknown parameter '%c'"), param_getchar(Cmd, cmdp)); errors = true; break; } From e041e625c0f596feba915ee730f4edf7a5566e14 Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sat, 14 Mar 2020 01:17:31 +1100 Subject: [PATCH 125/298] Colour fixes --- client/cmdlfhid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index c13882221..80d647437 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -248,7 +248,7 @@ static int CmdHIDDemod(const char *Cmd) { } } - PrintAndLogEx(DEBUG, "DEBUG: HID idx: " _GREEN_("%d, Len: %zu")", Printing Demod Buffer:", idx, size); + PrintAndLogEx(DEBUG, "DEBUG: HID idx: " _GREEN_("%d"), " Len: %zu", Printing Demod Buffer:", idx, size); if (g_debugMode) printDemodBuff(); @@ -400,7 +400,7 @@ static int CmdHIDBrute(const char *Cmd) { param_getstr(Cmd, cmdp + 1, format, sizeof(format)); format_idx = HIDFindCardFormat(format); if (format_idx == -1) { - PrintAndLogEx(WARNING, _YELLOW_("Unknown format: %s"), format); + PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format); errors = true; } cmdp += 2; @@ -431,7 +431,7 @@ static int CmdHIDBrute(const char *Cmd) { cmdp++; break; default: - PrintAndLogEx(WARNING, _YELLOW_("Unknown parameter '%c'"), param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter: " _YELLOW_("%c"), param_getchar(Cmd, cmdp)); errors = true; break; } From 3e8c4b21731fb046f61f611e7ec425759e1c8b3f Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sat, 14 Mar 2020 01:22:22 +1100 Subject: [PATCH 126/298] Typo --- client/cmdlfhid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 80d647437..71517695d 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -431,7 +431,7 @@ static int CmdHIDBrute(const char *Cmd) { cmdp++; break; default: - PrintAndLogEx(WARNING, "Unknown parameter: " _YELLOW_("%c"), param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter: " _YELLOW_("'%c'"), param_getchar(Cmd, cmdp)); errors = true; break; } From 267063a05cf8156d7d564adc0c5fc6d4b7cd5588 Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sat, 14 Mar 2020 01:52:25 +1100 Subject: [PATCH 127/298] Fix compile errors --- client/cmdlfhid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 71517695d..fa3d4878d 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -179,9 +179,9 @@ static int CmdHIDDemod(const char *Cmd) { else if (idx == -4) PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID preamble not found")); else if (idx == -5) - PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error in Manchester data, size %zu, size")); + PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error in Manchester data, size %zu"), size); else - PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error demoding fsk %d, idx")); + PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error demoding fsk %d"), idx); return PM3_ESOFT; } @@ -248,7 +248,7 @@ static int CmdHIDDemod(const char *Cmd) { } } - PrintAndLogEx(DEBUG, "DEBUG: HID idx: " _GREEN_("%d"), " Len: %zu", Printing Demod Buffer:", idx, size); + PrintAndLogEx(DEBUG, "DEBUG: HID idx: %d, Len: %zu, Printing Demod Buffer: ", idx, size); if (g_debugMode) printDemodBuff(); From 875aaee795d1e5ea6566b7b6d5c5ec6df79b5288 Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sat, 14 Mar 2020 01:58:14 +1100 Subject: [PATCH 128/298] Last changes --- client/cmdlfhid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index fa3d4878d..ea76d3fd2 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -243,7 +243,7 @@ static int CmdHIDDemod(const char *Cmd) { if (fmtLen == 32 && (lo & 0x40000000)) { //if 32 bit and Kastle bit set PrintAndLogEx(SUCCESS, "HID Prox TAG (Kastle format) ID: " _GREEN_("%x%08x (%u)")"- Format Len: 32bit - CC: %u - FC: %u - Card: %u", hi, lo, (lo >> 1) & 0xFFFF, cc, fc, cardnum); } else { - PrintAndLogEx(SUCCESS, "HID Prox TAG ID: " _GREEN_("%x%08x (%u)")"- Format Len: %ubit - OEM: %03u - FC: %u - Card: %u", + PrintAndLogEx(SUCCESS, "HID Prox TAG ID: " _GREEN_("%x%08x (%u)")"- Format Len: " _GREEN_("%u bit")"- OEM: %03u - FC: " _GREEN_("%u")"- Card: " _GREEN_("%u"), hi, lo, cardnum, fmtLen, oem, fc, cardnum); } } From 78a2a6891f523cbbc113744407cc81f11dbf68f1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 13 Mar 2020 18:03:48 +0100 Subject: [PATCH 129/298] Add PRIx64 for gcc-arm-none-eabi v8 --- armsrc/util.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/armsrc/util.h b/armsrc/util.h index 9748152ef..052ae266c 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -13,6 +13,11 @@ #include "common.h" +// PRIx64 definition missing with gcc-arm-none-eabi v8? +#ifndef PRIx64 + #define PRIx64 "llx" +#endif + // Basic macros #ifndef SHORT_COIL From aa0c2845cbc39fc18ec9b12056d84e341b980580 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 13 Mar 2020 13:15:06 -0400 Subject: [PATCH 130/298] more temp fix for PRIx32, PRIu32 : lf_icehid , hf_young --- armsrc/util.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/armsrc/util.h b/armsrc/util.h index 052ae266c..4ae95a5d1 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -17,6 +17,12 @@ #ifndef PRIx64 #define PRIx64 "llx" #endif +#ifndef PRIx32 + #define PRIx32 "lx" +#endif +#ifndef PRIu32 + #define PRIu32 "lu" +#endif // Basic macros From 7ad649130a275a7d3c8eccfabe6dbe888b9a82b3 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 13 Mar 2020 18:18:05 +0100 Subject: [PATCH 131/298] fix lf_icehid on gcc v8 --- armsrc/Standalone/lf_icehid.c | 1 + armsrc/util.h | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index d68f8423d..34d4439a0 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -7,6 +7,7 @@ //----------------------------------------------------------------------------- // main code for HID collector aka IceHID by Iceman //----------------------------------------------------------------------------- +#include #include "standalone.h" // standalone definitions #include "proxmark3_arm.h" #include "appmain.h" diff --git a/armsrc/util.h b/armsrc/util.h index 4ae95a5d1..052ae266c 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -17,12 +17,6 @@ #ifndef PRIx64 #define PRIx64 "llx" #endif -#ifndef PRIx32 - #define PRIx32 "lx" -#endif -#ifndef PRIu32 - #define PRIu32 "lu" -#endif // Basic macros From f2a287c6219a810b433c055b7c27d66ac2754913 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 14 Mar 2020 11:04:50 +0100 Subject: [PATCH 132/298] maur keys --- client/dictionaries/mfc_default_keys.dic | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 3001edb61..1e26f948b 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1076,7 +1076,7 @@ f0f0172066b2 f3864fcca693 f3f0172066b2 fc9839273862 - +# # various hotel keys 34D3C568B348 91FF18E63887 @@ -1084,3 +1084,21 @@ fc9839273862 354A787087F1 4a306e62e9b6 B9C874AE63D0 +# +# Data from offical repo +f00dfeedd0d0 +0bb31dc123e5 +7578bf2c66a9 +cd212889c3ed +6936c035ae1b +c6c866aa421e +590bd659cdd2 +aa734d2f40e0 +09800ff94aaf +5a12f83326e7 +c554ef6a6015 +0d8ca561bdf3 +b8937130b6ba +d7744a1a0c44 +82908b57ef4f +fe04ecfe5577 \ No newline at end of file From 132bd6c1f77bd38f5fbc9c2b9cf9ac914a3fc3c3 Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sun, 15 Mar 2020 19:57:47 +1100 Subject: [PATCH 133/298] Add colour to hf 14a and hf mfu commands --- armsrc/lfops.c | 2 +- client/cmdhf14a.c | 39 +++++----- client/cmdhf14b.c | 1 - client/cmdhfmfu.c | 176 ++++++++++++++++++++++++---------------------- client/cmdlfhid.c | 20 +++--- 5 files changed, 124 insertions(+), 114 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index b7b928ff2..84bddc192 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1291,7 +1291,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) cardnum = (lo >> 1) & 0x7FFFF; fac = ((hi & 0xF) << 12) | (lo >> 20); } - Dbprintf("TAG ID: " _YELLOW_("%x%08x (%d)") "- Format Len: " _YELLOW_("%d") "bit - FC: " _YELLOW_("%d") "- Card: "_YELLOW_("%d"), + Dbprintf("TAG ID: " _GREEN_("%x%08x (%d)") "- Format Len: " _GREEN_("%d") "bit - FC: " _GREEN_("%d") "- Card: "_GREEN_("%d"), hi, lo, (lo >> 1) & 0xFFFF, diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index c611caa1f..6d52f25e7 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -189,9 +189,9 @@ static int usage_hf_14a_sim(void) { PrintAndLogEx(NORMAL, " e : (Optional) Fill simulator keys from found keys"); PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344 x"); - PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344"); - PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344556677"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 11223344 x")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 11223344")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 11223344556677")); // PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223445566778899AA\n"); return 0; } @@ -202,7 +202,7 @@ static int usage_hf_14a_sniff(void) { PrintAndLogEx(NORMAL, "c - triggered by first data from card"); PrintAndLogEx(NORMAL, "r - triggered by first 7-bit request from reader (REQ,WUP,...)"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf 14a sniff c r"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sniff c r")); return 0; } static int usage_hf_14a_raw(void) { @@ -261,7 +261,7 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) { return 1; } - PrintAndLogEx(SUCCESS, " UID: %s", sprint_hex(card->uid, card->uidlen)); + PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card->uid, card->uidlen)); PrintAndLogEx(SUCCESS, "ATQA: %02x %02x", card->atqa[1], card->atqa[0]); PrintAndLogEx(SUCCESS, " SAK: %02x [%" PRIu64 "]", card->sak, resp.oldarg[0]); if (card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes @@ -335,17 +335,17 @@ static int CmdHF14AReader(const char *Cmd) { if (select_status == 3) { PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision"); - PrintAndLogEx(SUCCESS, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + PrintAndLogEx(SUCCESS, "ATQA: %02x %02x", card.atqa[1], card.atqa[0]); DropField(); return 1; } - PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(SUCCESS, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLogEx(SUCCESS, " SAK : %02x [%" PRIu64 "]", card.sak, resp.oldarg[0]); + PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]); + PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]); if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes - PrintAndLogEx(SUCCESS, " ATS : %s", sprint_hex(card.ats, card.ats_len)); + PrintAndLogEx(SUCCESS, " ATS: " _GREEN_("%s"), sprint_hex(card.ats, card.ats_len)); } if (!disconnectAfter) { @@ -354,7 +354,7 @@ static int CmdHF14AReader(const char *Cmd) { } if (disconnectAfter) { - if (!silent) PrintAndLogEx(SUCCESS, "field dropped."); + if (!silent) PrintAndLogEx(INFO, "field dropped."); } return 0; @@ -467,7 +467,7 @@ int CmdHF14ASim(const char *Cmd) { break; } if (!errors) { - PrintAndLogEx(SUCCESS, "Emulating ISO/IEC 14443 type A tag with %d byte UID (%s)", uidlen, sprint_hex(uid, uidlen)); + PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")"with " _GREEN_("%d byte UID (%s)"), uidlen, sprint_hex(uid, uidlen)); useUIDfromEML = false; } cmdp += 2; @@ -485,7 +485,7 @@ int CmdHF14ASim(const char *Cmd) { cmdp++; break; default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter " _RED_("'%c'"), param_getchar(Cmd, cmdp)); errors = true; break; } @@ -511,7 +511,7 @@ int CmdHF14ASim(const char *Cmd) { SendCommandNG(CMD_HF_ISO14443A_SIMULATE, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; - PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation"); + PrintAndLogEx(INFO, "Press pm3-button to abort simulation"); bool keypress = kbd_enter_pressed(); while (!keypress) { @@ -1276,14 +1276,14 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (select_status == 3) { PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision"); - PrintAndLogEx(SUCCESS, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + PrintAndLogEx(SUCCESS, "ATQA: %02x %02x", card.atqa[1], card.atqa[0]); DropField(); return select_status; } - PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(SUCCESS, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLogEx(SUCCESS, " SAK : %02x [%" PRIu64 "]", card.sak, resp.oldarg[0]); + PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]); + PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]); bool isMifareClassic = true; switch (card.sak) { @@ -1364,7 +1364,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { // Double & triple sized UID, can be mapped to a manufacturer. if (card.uidlen > 4) { - PrintAndLogEx(SUCCESS, "MANUFACTURER : %s", getTagInfo(card.uid[0])); + PrintAndLogEx(SUCCESS, "MANUFACTURER: " _GREEN_("%s"), getTagInfo(card.uid[0])); } // try to request ATS even if tag claims not to support it @@ -1608,4 +1608,3 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { return select_status; } - diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index c57055e4b..859df4a23 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -1142,4 +1142,3 @@ int readHF14B(bool verbose) { if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); return 0; } - diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 120db2a9c..ccc749708 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -53,9 +53,10 @@ static int usage_hf_mfu_info(void) { PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu info"); - PrintAndLogEx(NORMAL, " hf mfu info k 00112233445566778899AABBCCDDEEFF"); - PrintAndLogEx(NORMAL, " hf mfu info k AABBCCDD"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu info")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu info k 00112233445566778899AABBCCDDEEFF")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu info k AABBCCDD")); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -73,10 +74,11 @@ static int usage_hf_mfu_dump(void) { PrintAndLogEx(NORMAL, " q : number of Pages to manually set how many pages to dump"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu dump"); - PrintAndLogEx(NORMAL, " hf mfu dump f myfile"); - PrintAndLogEx(NORMAL, " hf mfu dump k 00112233445566778899AABBCCDDEEFF"); - PrintAndLogEx(NORMAL, " hf mfu dump k AABBCCDD\n"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu dump")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu dump f myfile")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu dump k 00112233445566778899AABBCCDDEEFF")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu dump k AABBCCDD")); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -92,9 +94,10 @@ static int usage_hf_mfu_restore(void) { PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w .bin") "to restore"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu restore s f myfile"); - PrintAndLogEx(NORMAL, " hf mfu restore k AABBCCDD s f myfile\n"); - PrintAndLogEx(NORMAL, " hf mfu restore k AABBCCDD s e r f myfile\n"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu restore s f myfile")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu restore k AABBCCDD s f myfile")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu restore k AABBCCDD s e r f myfile")); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -107,9 +110,10 @@ static int usage_hf_mfu_rdbl(void) { PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu rdbl b 0"); - PrintAndLogEx(NORMAL, " hf mfu rdbl b 0 k 00112233445566778899AABBCCDDEEFF"); - PrintAndLogEx(NORMAL, " hf mfu rdbl b 0 k AABBCCDD\n"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu rdbl b 0")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu rdbl b 0 k 00112233445566778899AABBCCDDEEFF")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu rdbl b 0 k AABBCCDD")); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -123,8 +127,9 @@ static int usage_hf_mfu_wrbl(void) { PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu wrbl b 0 d 01234567"); - PrintAndLogEx(NORMAL, " hf mfu wrbl b 0 d 01234567 k AABBCCDD\n"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu wrbl b 0 d 01234567")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu wrbl b 0 d 01234567 k AABBCCDD")); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -138,8 +143,10 @@ static int usage_hf_mfu_eload(void) { PrintAndLogEx(NORMAL, " [filename] : without `.eml` (required)"); PrintAndLogEx(NORMAL, " numblocks : number of blocks to load from eml file (optional)"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " sample: hf mfu eload u filename"); - PrintAndLogEx(NORMAL, " hf mfu eload u filename 57"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu eload u filename")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu eload u filename 57")); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -153,8 +160,9 @@ static int usage_hf_mfu_sim(void) { PrintAndLogEx(NORMAL, " u : 4 or 7 byte UID (optional)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu sim t 7"); - PrintAndLogEx(NORMAL, " hf mfu sim t 7 u 1122344556677\n"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu sim t 7")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu sim t 7 u 1122344556677")); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -168,8 +176,9 @@ static int usage_hf_mfu_ucauth(void) { PrintAndLogEx(NORMAL, " 5 : all 0xff key"); PrintAndLogEx(NORMAL, " 6 : 0x00-0xFF key"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu cauth k"); - PrintAndLogEx(NORMAL, " hf mfu cauth k 3"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu cauth k")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu cauth k 3")); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -179,7 +188,7 @@ static int usage_hf_mfu_ucsetpwd(void) { PrintAndLogEx(NORMAL, " [password] - (32 hex symbols)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu setpwd 000102030405060708090a0b0c0d0e0f"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setpwd 000102030405060708090a0b0c0d0e0f")); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -191,7 +200,7 @@ static int usage_hf_mfu_ucsetuid(void) { PrintAndLogEx(NORMAL, "This only works for " _BLUE_("Magic Ultralight") "tags."); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu setuid 11223344556677"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid 11223344556677")); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -203,8 +212,8 @@ static int usage_hf_mfu_gendiverse(void) { PrintAndLogEx(NORMAL, " r : read uid from tag"); PrintAndLogEx(NORMAL, " : 4 byte UID (optional)"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu gen r"); - PrintAndLogEx(NORMAL, " hf mfu gen 11223344"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu gen r")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu gen 11223344")); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -217,9 +226,9 @@ static int usage_hf_mfu_pwdgen(void) { PrintAndLogEx(NORMAL, " r : read uid from tag"); PrintAndLogEx(NORMAL, " : 7 byte UID (optional)"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu pwdgen r"); - PrintAndLogEx(NORMAL, " hf mfu pwdgen 11223344556677"); - PrintAndLogEx(NORMAL, " hf mfu pwdgen t"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu pwdgen r")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu pwdgen 11223344556677")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu pwdgen t")); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -230,7 +239,8 @@ static int usage_hf_mfu_otp_tearoff(void) { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfu otptear"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu otptear")); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -529,43 +539,43 @@ static int ul_print_default(uint8_t *data) { uid[5] = data[6]; uid[6] = data[7]; - PrintAndLogEx(NORMAL, " UID : " _YELLOW_("%s"), sprint_hex(uid, 7)); - PrintAndLogEx(NORMAL, " UID[0] : %02X, %s", uid[0], getTagInfo(uid[0])); + PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, 7)); + PrintAndLogEx(SUCCESS, " UID[0]: %02X, %s", uid[0], getTagInfo(uid[0])); if (uid[0] == 0x05 && ((uid[1] & 0xf0) >> 4) == 2) { // is infineon and 66RxxP uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU switch (chip) { case 0xC2: - PrintAndLogEx(NORMAL, " IC type : SLE 66R04P 770 Bytes"); + PrintAndLogEx(SUCCESS, " IC type: SLE 66R04P 770 Bytes"); break; //77 pages case 0xC4: - PrintAndLogEx(NORMAL, " IC type : SLE 66R16P 2560 Bytes"); + PrintAndLogEx(SUCCESS, " IC type: SLE 66R16P 2560 Bytes"); break; //256 pages case 0xC6: - PrintAndLogEx(NORMAL, " IC type : SLE 66R32P 5120 Bytes"); + PrintAndLogEx(SUCCESS, " IC type: SLE 66R32P 5120 Bytes"); break; //512 pages /2 sectors } } // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 int crc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; if (data[3] == crc0) - PrintAndLogEx(NORMAL, " BCC0 : %02X ( " _GREEN_("ok") ")", data[3]); + PrintAndLogEx(SUCCESS, " BCC0: %02X ( " _GREEN_("ok") ")", data[3]); else - PrintAndLogEx(NORMAL, " BCC0 : %02X, crc should be %02X", data[3], crc0); + PrintAndLogEx(NORMAL, " BCC0: %02X, crc should be %02X", data[3], crc0); int crc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6]; if (data[8] == crc1) - PrintAndLogEx(NORMAL, " BCC1 : %02X ( " _GREEN_("ok") ")", data[8]); + PrintAndLogEx(SUCCESS, " BCC1: %02X ( " _GREEN_("ok") ")", data[8]); else - PrintAndLogEx(NORMAL, " BCC1 : %02X, crc should be %02X", data[8], crc1); + PrintAndLogEx(NORMAL, " BCC1: %02X, crc should be %02X", data[8], crc1); - PrintAndLogEx(NORMAL, " Internal : %02X ( %s)", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default") ); + PrintAndLogEx(SUCCESS, " Internal: %02X ( %s)", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default") ); - PrintAndLogEx(NORMAL, " Lock : %s - %s", + PrintAndLogEx(SUCCESS, " Lock: %s - %s", sprint_hex(data + 10, 2), sprint_bin(data + 10, 2) ); - PrintAndLogEx(NORMAL, "OneTimePad : %s - %s\n", + PrintAndLogEx(SUCCESS, "OneTimePad : %s - %s\n", sprint_hex(data + 12, 4), sprint_bin(data + 12, 4) ); @@ -669,57 +679,57 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) { char *spacer = spc + (10 - spaces); if (tagtype & UL) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "" : ""); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("MIFARE Ultralight (MF0ICU1) %s"), spacer, (tagtype & MAGIC) ? "" : ""); else if (tagtype & UL_C) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "" : ""); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("MIFARE Ultralight C (MF0ULC) %s"), spacer, (tagtype & MAGIC) ? "" : ""); else if (tagtype & UL_NANO_40) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight Nano 40bytes (MF0UNH00)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spacer); else if (tagtype & UL_EV1_48) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spacer); else if (tagtype & UL_EV1_128) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spacer); else if (tagtype & UL_EV1) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 UNKNOWN", spacer); + PrintAndLogEx(NORMAL, "%sTYPE: " _YELLOW_("MIFARE Ultralight EV1 UNKNOWN"), spacer); else if (tagtype & NTAG) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG UNKNOWN", spacer); + PrintAndLogEx(NORMAL, "%sTYPE: " _YELLOW_("NTAG UNKNOWN"), spacer); else if (tagtype & NTAG_203) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 203 144bytes (NT2H0301F0DT)"), spacer); else if (tagtype & NTAG_210) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 210 48bytes (NT2L1011G0DU)"), spacer); else if (tagtype & NTAG_212) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 212 128bytes (NT2L1211G0DU)"), spacer); else if (tagtype & NTAG_213) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 213 144bytes (NT2H1311G0DU)"), spacer); else if (tagtype & NTAG_213_F) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 213F 144bytes (NT2H1311F0DTL)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spacer); else if (tagtype & NTAG_215) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 215 504bytes (NT2H1511G0DU)"), spacer); else if (tagtype & NTAG_216) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 216 888bytes (NT2H1611G0DU)"), spacer); else if (tagtype & NTAG_216_F) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 216F 888bytes (NT2H1611F0DTL)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spacer); else if (tagtype & NTAG_I2C_1K) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I2C 888bytes (NT3H1101FHK)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG I2C 888bytes (NT3H1101FHK)"), spacer); else if (tagtype & NTAG_I2C_2K) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I2C 1904bytes (NT3H1201FHK)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG I2C 1904bytes (NT3H1201FHK)"), spacer); else if (tagtype & NTAG_I2C_1K_PLUS) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I2C plus 888bytes (NT3H2111FHK)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spacer); else if (tagtype & NTAG_I2C_2K_PLUS) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I2C plus 1912bytes (NT3H2211FHK)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spacer); else if (tagtype & MY_D) - PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 (SLE 66RxxS)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("INFINEON my-d\x99 (SLE 66RxxS)"), spacer); else if (tagtype & MY_D_NFC) - PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 NFC (SLE 66RxxP)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spacer); else if (tagtype & MY_D_MOVE) - PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 move (SLE 66R01P)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("INFINEON my-d\x99 move (SLE 66R01P)"), spacer); else if (tagtype & MY_D_MOVE_NFC) - PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 move NFC (SLE 66R01P)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spacer); else if (tagtype & MY_D_MOVE_LEAN) - PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 move lean (SLE 66R01L)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spacer); else if (tagtype & FUDAN_UL) - PrintAndLogEx(NORMAL, "%sTYPE : FUDAN Ultralight Compatible (or other compatible) %s", spacer, (tagtype & MAGIC) ? "" : ""); + PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("FUDAN Ultralight Compatible (or other compatible) %s"), spacer, (tagtype & MAGIC) ? "" : ""); else - PrintAndLogEx(NORMAL, "%sTYPE : Unknown %06x", spacer, tagtype); + PrintAndLogEx(NORMAL, "%sTYPE: " _YELLOW_("Unknown %06x"), spacer, tagtype); return PM3_SUCCESS; } @@ -896,14 +906,14 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig static int ulev1_print_version(uint8_t *data) { PrintAndLogEx(NORMAL, "\n--- Tag Version"); - PrintAndLogEx(NORMAL, " Raw bytes : %s", sprint_hex(data, 8)); - PrintAndLogEx(NORMAL, " Vendor ID : %02X, %s", data[1], getTagInfo(data[1])); - PrintAndLogEx(NORMAL, " Product type : %s", getProductTypeStr(data[2])); - PrintAndLogEx(NORMAL, " Product subtype : %02X, %s", data[3], (data[3] == 1) ? "17 pF" : "50pF"); - PrintAndLogEx(NORMAL, " Major version : %02X", data[4]); - PrintAndLogEx(NORMAL, " Minor version : %02X", data[5]); - PrintAndLogEx(NORMAL, " Size : %s", getUlev1CardSizeStr(data[6])); - PrintAndLogEx(NORMAL, " Protocol type : %02X %s", data[7], (data[7] == 0x3) ? "(ISO14443-3 Compliant)" : ""); + PrintAndLogEx(NORMAL, " Raw bytes: %s", sprint_hex(data, 8)); + PrintAndLogEx(NORMAL, " Vendor ID: %02X, %s", data[1], getTagInfo(data[1])); + PrintAndLogEx(NORMAL, " Product type: %s", getProductTypeStr(data[2])); + PrintAndLogEx(NORMAL, " Product subtype: %02X, %s", data[3], (data[3] == 1) ? "17 pF" : "50pF"); + PrintAndLogEx(NORMAL, " Major version: %02X", data[4]); + PrintAndLogEx(NORMAL, " Minor version: %02X", data[5]); + PrintAndLogEx(NORMAL, " Size: %s", getUlev1CardSizeStr(data[6])); + PrintAndLogEx(NORMAL, " Protocol type: %02X %s", data[7], (data[7] == 0x3) ? "(ISO14443-3 Compliant)" : ""); return PM3_SUCCESS; } @@ -1112,7 +1122,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { cmdp++; break; default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp)); errors = true; break; } @@ -1273,7 +1283,8 @@ static int CmdHF14AMfUInfo(const char *Cmd) { // 1-7 = limit. No automatic tries then. // hasAuthKey, if we was called with key, skip test. if (!authlim && !hasAuthKey) { - PrintAndLogEx(NORMAL, "\n--- Known EV1/NTAG passwords."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _GREEN_("--- Known EV1/NTAG passwords ---")); // test pwd gen A num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); @@ -1324,7 +1335,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; } } - if (len < 1) PrintAndLogEx(WARNING, "password not known"); + if (len < 1) PrintAndLogEx(WARNING, _YELLOW_("password not known")); } } out: @@ -1397,7 +1408,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { cmdp += 2; break; default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp)); errors = true; break; } @@ -1511,7 +1522,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { cmdp++; break; default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp)); errors = true; break; } @@ -1781,7 +1792,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { manualPages = true; break; default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp)); errors = true; break; } @@ -2022,7 +2033,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { read_key = true; break; default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp)); errors = true; break; } @@ -2673,4 +2684,3 @@ int CmdHFMFUltra(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } - diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index ea76d3fd2..b5d449623 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -50,7 +50,7 @@ static int usage_lf_hid_watch(void) { PrintAndLogEx(NORMAL, "Usage: lf hid watch"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hid watch"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf hid watch")); return PM3_SUCCESS; } static int usage_lf_hid_sim(void) { @@ -62,11 +62,11 @@ static int usage_lf_hid_sim(void) { PrintAndLogEx(NORMAL, " h - This help"); PrintAndLogEx(NORMAL, " ID - HID id"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hid sim 2006ec0c86"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf hid sim 2006ec0c86")); return PM3_SUCCESS; } static int usage_lf_hid_clone(void) { - PrintAndLogEx(NORMAL, "Clone HID to T55x7. Tag must be on antenna. "); + PrintAndLogEx(NORMAL, "Clone HID to T55x7. " _BLUE_("Tag must be on antenna!")); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf hid clone [h] [l] ID"); PrintAndLogEx(NORMAL, "Options:"); @@ -74,8 +74,8 @@ static int usage_lf_hid_clone(void) { PrintAndLogEx(NORMAL, " l - 84bit ID"); PrintAndLogEx(NORMAL, " ID - HID id"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hid clone 2006ec0c86"); - PrintAndLogEx(NORMAL, " lf hid clone l 2006ec0c86"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf hid clone 2006ec0c86")); + PrintAndLogEx(NORMAL, _YELLOW_(" lf hid clone l 2006ec0c86")); return PM3_SUCCESS; } static int usage_lf_hid_brute(void) { @@ -97,9 +97,9 @@ static int usage_lf_hid_brute(void) { PrintAndLogEx(NORMAL, " down : direction to decrement card number. (default is both directions)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hid brute w H10301 f 224"); - PrintAndLogEx(NORMAL, " lf hid brute w H10301 f 21 d 2000"); - PrintAndLogEx(NORMAL, " lf hid brute v w H10301 f 21 c 200 d 2000"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute w H10301 f 224")); + PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute w H10301 f 21 d 2000")); + PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute v w H10301 f 21 c 200 d 2000")); return PM3_SUCCESS; } @@ -268,6 +268,8 @@ static int CmdHIDWatch(const char *Cmd) { if (ctmp == 'h') return usage_lf_hid_watch(); clearCommandBuffer(); SendCommandNG(CMD_LF_HID_DEMOD, NULL, 0); + PrintAndLogEx(SUCCESS, "Watching for new HID cards - place tag on antenna"); + PrintAndLogEx(INFO, "Press pm3-button to stop reading new cards"); return PM3_SUCCESS; } @@ -299,7 +301,7 @@ static int CmdHIDSim(const char *Cmd) { hi2 = 0; } - PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation"); + PrintAndLogEx(INFO, "Press pm3-button to abort simulation"); payload.hi2 = hi2; payload.hi = hi; From 367334750c5a442db1ada4655bd33766c57dab0d Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sun, 15 Mar 2020 19:59:16 +1100 Subject: [PATCH 134/298] Add colour lf hid, hf 14a and hf mfu command output --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f84700e6..be95a700d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] - - Add colour to `lf hid` commands in cmdlfhid.c + - Add colour to `hf 14a` and `hf mfu` commands (@dunderhay) + - Add colour to `lf hid` commands (@dunderhay) - Change `script run hf_bruteforce -s start_id -e end_id -t timeout -x mifare_card_type` - The hf_bruteforce card script now requires Mifare type (mfc or mfu) (@dunderhay) - Updated `hf_bruteforce.lua` script - added support for brute forcing Mifare Ultralight EV1 cards (@dunderhay) - Added `hf mf personlize` - personalize the UID of a Mifare Classic EV1 card (@pwpiwi) From 6172eccefd87f6450561df23d0237a8ac90042ee Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 15 Mar 2020 11:03:23 +0100 Subject: [PATCH 135/298] chg: hf 14a info - some hint texts added and static nonce text changed. --- client/cmdhf14a.c | 52 ++++++++++++++++++++++++++++++-------- client/mifare/mifarehost.c | 2 ++ 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 6d52f25e7..389c16fe5 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -230,7 +230,6 @@ static int usage_hf_14a_reader(void) { static int CmdHF14AList(const char *Cmd) { (void)Cmd; // Cmd is not used so far - //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list 14a' instead"); CmdTraceList("14a"); return 0; } @@ -361,7 +360,7 @@ static int CmdHF14AReader(const char *Cmd) { } static int CmdHF14AInfo(const char *Cmd) { - bool verbose = false; + bool verbose = true; bool do_nack_test = false; bool do_aid_search = false; @@ -1281,11 +1280,19 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { return select_status; } + if (verbose) { + PrintAndLogEx(SUCCESS, "-- ISO14443-a Information -----------------------------------"); + PrintAndLogEx(SUCCESS, "-------------------------------------------------------------"); + } PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]); PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]); bool isMifareClassic = true; + bool isMifareDesfire = false; + bool isMifarePlus = false; + bool isMifareUltralight = false; + switch (card.sak) { case 0x00: isMifareClassic = false; @@ -1294,10 +1301,12 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { DropField(); uint32_t tagT = GetHF14AMfU_Type(); - if (tagT != UL_ERROR) + if (tagT != UL_ERROR) { ul_print_type(tagT, 0); - else + isMifareUltralight = true; + } else { PrintAndLogEx(SUCCESS, "TYPE: Possible AZTEK (iso14443a compliant)"); + } // reconnect for further tests clearCommandBuffer(); @@ -1319,6 +1328,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { case 0x04: PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); isMifareClassic = false; + isMifareDesfire = true; break; case 0x08: PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1"); @@ -1331,9 +1341,11 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { break; case 0x10: PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Plus 2k SL2"); + isMifarePlus = true; break; case 0x11: PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Plus 4k SL2"); + isMifarePlus = true; break; case 0x18: PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1"); @@ -1341,10 +1353,13 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { case 0x20: PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); isMifareClassic = false; + isMifareDesfire = true; + isMifarePlus = true; break; case 0x24: PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE DESFire | DESFire EV1"); isMifareClassic = false; + isMifareDesfire = true; break; case 0x28: PrintAndLogEx(SUCCESS, "TYPE : JCOP31 or JCOP41 v2.3.1"); @@ -1461,9 +1476,15 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { switch (card.ats[pos + 2] & 0xf0) { case 0x10: PrintAndLogEx(SUCCESS, " 1x -> MIFARE DESFire"); + isMifareDesfire = true; + isMifareClassic = false; + isMifarePlus = false; break; case 0x20: PrintAndLogEx(SUCCESS, " 2x -> MIFARE Plus"); + isMifarePlus = true; + isMifareDesfire = false; + isMifareClassic = false; break; } switch (card.ats[pos + 2] & 0x0f) { @@ -1590,21 +1611,32 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (isMifareClassic) { int res = detect_classic_prng(); if (res == 1) - PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_("WEAK")); + PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_("weak")); else if (res == 0) - PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_("HARD")); + PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_("hard")); else - PrintAndLogEx(FAILED, "prng detection: " _RED_("Fail")); + PrintAndLogEx(FAILED, "prng detection: " _RED_("fail")); if (do_nack_test) - detect_classic_nackbug(!verbose); + detect_classic_nackbug(false); res = detect_classic_static_nonce(); if (res == 1) - PrintAndLogEx(SUCCESS, "Static nonce detected"); + PrintAndLogEx(SUCCESS, "Static nonce: " _YELLOW_("yes") ); if (res == 2 && verbose) - PrintAndLogEx(SUCCESS, "Static nonce detection failed"); + PrintAndLogEx(SUCCESS, "Static nonce: " _RED_("fail")); } + + if (isMifareUltralight) { + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`hf mfu info`")); + } + if (isMifarePlus) { + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`hf mfp info`")); + } + if (isMifareDesfire) { + PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`hf mfdes info`")); + } + return select_status; } diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index b5d1cb267..e4e1832b5 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -1316,6 +1316,8 @@ int detect_classic_nackbug(bool verbose) { SendCommandNG(CMD_HF_MIFARE_NACK_DETECT, NULL, 0); PacketResponseNG resp; + PrintAndLogEx(INFO, "Checking for NACK bug"); + if (verbose) PrintAndLogEx(SUCCESS, "press pm3-button on the Proxmark3 device to abort both Proxmark3 and client.\n"); From 945e508e234d3772458ea50590af353005236a47 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 15 Mar 2020 11:51:09 +0100 Subject: [PATCH 136/298] new command: hints h - will set hint messages on / off. default mode is OFF. Hint texts makes its easier for beginners but adds text to anyone who knows the pm3 client --- CHANGELOG.md | 1 + client/cmdhf14a.c | 6 +-- client/cmdmain.c | 106 +++++++++++++++++++++++++++++++++++++++++++++- client/proxgui.h | 2 +- client/ui.c | 5 +++ client/ui.h | 2 +- 6 files changed, 116 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be95a700d..0fa346660 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Add 'HINTS' command. Will turn off / on hint messages. Default mode is OFF. (@iceman1001) - Add colour to `hf 14a` and `hf mfu` commands (@dunderhay) - Add colour to `lf hid` commands (@dunderhay) - Change `script run hf_bruteforce -s start_id -e end_id -t timeout -x mifare_card_type` - The hf_bruteforce card script now requires Mifare type (mfc or mfu) (@dunderhay) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 389c16fe5..0355abe85 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1628,13 +1628,13 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } if (isMifareUltralight) { - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`hf mfu info`")); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu info`")); } if (isMifarePlus) { - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`hf mfp info`")); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfp info`")); } if (isMifareDesfire) { - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`hf mfdes info`")); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfdes info`")); } diff --git a/client/cmdmain.c b/client/cmdmain.c index c2364d8f1..d9cbbac74 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -36,9 +36,23 @@ #include "cmdwiegand.h" // wiegand commands #include "ui.h" #include "util_posix.h" +#include "commonutil.h" // ARRAYLEN static int CmdHelp(const char *Cmd); +static int usage_hints(void) { + PrintAndLogEx(NORMAL, "Turn on/off hints"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: hints [h] <0|1>"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " <0|1> off or on"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hints 1"); + return PM3_SUCCESS; +} + static int usage_msleep(void) { PrintAndLogEx(NORMAL, "Sleep for given amount of milliseconds"); PrintAndLogEx(NORMAL, ""); @@ -78,6 +92,70 @@ static void AppendDate(char *s, size_t slen, char *fmt) { strftime(s, slen, fmt, ct); } +static int lf_search_plus(const char *Cmd) { + + sample_config oldconfig; + memset(&oldconfig, 0, sizeof(sample_config)); + + int retval = lf_getconfig(&oldconfig); + + if (retval != PM3_SUCCESS) { + PrintAndLogEx(ERR, "failed to get current device config"); + return retval; + } + + // Divisor : frequency(khz) + // 95 88 47 31 23 + // 125.00 134.83 250.00 375.00 500.00 + + int16_t default_divisor[] = {95, 88, 47, 31, 23}; + + /* + default LF config is set to: + decimation = 1 + bits_per_sample = 8 + averaging = YES + divisor = 95 (125kHz) + trigger_threshold = 0 + samples_to_skip = 0 + verbose = YES + */ + sample_config config = { + .decimation = 1, + .bits_per_sample = 8, + .averaging = 1, + .trigger_threshold = 0, + .samples_to_skip = 0, + .verbose = false + }; + + // Iteration defaults + for (int i = 0; i < ARRAYLEN(default_divisor); ++i) { + + if (kbd_enter_pressed()) { + PrintAndLogEx(INFO, "Keyboard pressed. Done."); + break; + } + // Try to change config! + uint32_t d; + d = config.divisor = default_divisor[i]; + PrintAndLogEx(INFO, "--> trying ( " _GREEN_("%d.%02d kHz")")", 12000 / (d + 1), ((1200000 + (d + 1) / 2) / (d + 1)) - ((12000 / (d + 1)) * 100)); + + retval = lf_config(&config); + if (retval != PM3_SUCCESS) + break; + + // The config for pm3 is changed, we can trying search! + retval = CmdLFfind(Cmd); + if (retval == PM3_SUCCESS) + break; + + } + + lf_config(&oldconfig); + return retval; +} + static int CmdAuto(const char *Cmd) { char ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 'h') return usage_auto(); @@ -90,8 +168,12 @@ static int CmdAuto(const char *Cmd) { if (ret == PM3_SUCCESS) return ret; + ret = lf_search_plus(""); + if (ret == PM3_SUCCESS) + return ret; + PrintAndLogEx(INFO, "Failed both LF / HF SEARCH,"); - PrintAndLogEx(INFO, "Trying 'lf read' and save a trace for you..."); + PrintAndLogEx(INFO, "Trying " _YELLOW_("`lf read`") "and save a trace for you"); CmdPlot(""); lf_read(false, 40000); @@ -109,6 +191,27 @@ int CmdRem(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHints(const char *Cmd) { + uint32_t ms = 0; + char ctmp = tolower(param_getchar(Cmd, 0)); + if (ctmp == 'h') return usage_hints(); + + if (strlen(Cmd) < 1) { + PrintAndLogEx(INFO, "Hints are %s", (g_showhints) ? "ON" : "OFF"); + return PM3_SUCCESS; + } + + if (param_getchar(Cmd, 0) != 0x00) { + ms = param_get32ex(Cmd, 0, 0, 10); + if (ms == 0) + g_showhints = false; + else + g_showhints = true; + } + PrintAndLogEx(INFO, "Hints are %s", (g_showhints) ? "ON" : "OFF"); + return PM3_SUCCESS; +} + static int CmdMsleep(const char *Cmd) { uint32_t ms = 0; char ctmp = tolower(param_getchar(Cmd, 0)); @@ -149,6 +252,7 @@ static command_t CommandTable[] = { {"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"}, {"wiegand", CmdWiegand, AlwaysAvailable, "{ Wiegand format manipulation... }"}, {"", CmdHelp, AlwaysAvailable, ""}, + {"hints", CmdHints, AlwaysAvailable, "Turn hints on / off"}, {"msleep", CmdMsleep, AlwaysAvailable, "Add a pause in milliseconds"}, {"rem", CmdRem, AlwaysAvailable, "Add a text line in log file"}, {"quit", CmdQuit, AlwaysAvailable, ""}, diff --git a/client/proxgui.h b/client/proxgui.h index 8e0868b12..fea28d62b 100644 --- a/client/proxgui.h +++ b/client/proxgui.h @@ -55,7 +55,7 @@ extern size_t DemodBufferLen; extern size_t g_DemodStartIdx; extern bool showDemod; extern uint8_t g_debugMode; - +extern uint8_t g_showhints; #ifndef FILE_PATH_SIZE #define FILE_PATH_SIZE 1000 diff --git a/client/ui.c b/client/ui.c index 215bd66bc..91a2a49e6 100644 --- a/client/ui.c +++ b/client/ui.c @@ -127,6 +127,10 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) { // skip debug messages if client debugging is turned off i.e. 'DATA SETDEBUG 0' if (g_debugMode == 0 && level == DEBUG) return; + + // skip HINT messages if client has hints turned off i.e. 'HINT 0' + if (g_showhints == 0 && level == HINT) + return; char prefix[20] = {0}; char buffer[MAX_PRINT_BUFFER] = {0}; @@ -146,6 +150,7 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) { case DEBUG: strncpy(prefix, _BLUE_("[#]"), sizeof(prefix) - 1); break; + case HINT: case SUCCESS: strncpy(prefix, _GREEN_("[+]"), sizeof(prefix) - 1); break; diff --git a/client/ui.h b/client/ui.h index 7e00ab52b..c67865593 100644 --- a/client/ui.h +++ b/client/ui.h @@ -31,7 +31,7 @@ extern session_arg_t session; #define M_PI 3.14159265358979323846264338327 #endif #define MAX_PRINT_BUFFER 2048 -typedef enum logLevel {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG, INPLACE} logLevel_t; +typedef enum logLevel {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG, INPLACE, HINT} logLevel_t; void ShowGui(void); void HideGraphWindow(void); From 64ee9885d0c13598baf3a401d9f57ceb1c2a1dcc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 15 Mar 2020 11:51:26 +0100 Subject: [PATCH 137/298] nack text --- client/mifare/mifarehost.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index e4e1832b5..9d1293b5b 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -1360,16 +1360,16 @@ int detect_classic_nackbug(bool verbose) { return PM3_SUCCESS; } case 2 : - PrintAndLogEx(SUCCESS, _GREEN_("always leak NACK detected")); + PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("always leak NACK")); return PM3_SUCCESS; case 1 : - PrintAndLogEx(SUCCESS, _GREEN_("NACK bug detected")); + PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("detected")); return PM3_SUCCESS; case 0 : - PrintAndLogEx(SUCCESS, "No NACK bug detected"); + PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("no bug")); return PM3_SUCCESS; default : - PrintAndLogEx(ERR, "errorcode from device [%i]", ok); + PrintAndLogEx(ERR, "errorcode from device " _RED_("[%i]"), ok); return PM3_EUNDEF; } break; From 7d2e65ce91bb240ec7b43e6b11e4953e055e8263 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 15 Mar 2020 11:52:13 +0100 Subject: [PATCH 138/298] forgot a hint part --- client/util.h | 1 + 1 file changed, 1 insertion(+) diff --git a/client/util.h b/client/util.h index fb31e6013..e010175a6 100644 --- a/client/util.h +++ b/client/util.h @@ -23,6 +23,7 @@ uint8_t g_debugMode; uint8_t g_printAndLog; +uint8_t g_showhints; #define PRINTANDLOG_PRINT 1 #define PRINTANDLOG_LOG 2 From 8387bdbdadf09a022612fdd85a4c6aff2806f044 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 15 Mar 2020 13:23:02 +0100 Subject: [PATCH 139/298] change hint loglevel --- client/cmdlf.c | 4 ++-- client/cmdlfpyramid.c | 2 +- client/cmdlfti.c | 2 +- client/cmdlfverichip.c | 2 +- client/cmdlfviking.c | 2 +- client/cmdlfvisa2000.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 29854c6b6..31d10ce49 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -1189,7 +1189,7 @@ static bool CheckChipType(bool getDeviceData) { uint32_t word = 0; if (EM4x05IsBlock0(&word)) { PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("EM4x05/EM4x69")); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x05`") "commands"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05`") "commands"); retval = true; goto out; } @@ -1197,7 +1197,7 @@ static bool CheckChipType(bool getDeviceData) { //check for t55xx chip... if (tryDetectP1(true)) { PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("T55xx")); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf t55xx`") "commands"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf t55xx`") "commands"); retval = true; } diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index 14357201a..91b2fb25e 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -252,7 +252,7 @@ static int CmdPyramidClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf pyramid read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pyramid read`") "to verify"); return res; } diff --git a/client/cmdlfti.c b/client/cmdlfti.c index 8507fa36a..7aa04ca28 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -297,7 +297,7 @@ static int CmdTIWrite(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_LF_TI_WRITE, arg0, arg1, arg2, NULL, 0); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf ti read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf ti read`") "to verify"); return PM3_SUCCESS; } diff --git a/client/cmdlfverichip.c b/client/cmdlfverichip.c index 91b49b8f4..a8cd68195 100644 --- a/client/cmdlfverichip.c +++ b/client/cmdlfverichip.c @@ -123,7 +123,7 @@ static int CmdVerichipClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf verichip read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf verichip read`") "to verify"); return res; } diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 407c28f7e..e30234e5a 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -118,7 +118,7 @@ static int CmdVikingClone(const char *Cmd) { return PM3_ETIMEOUT; } PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf viking read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf viking read`") "to verify"); return resp.status; } diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 1a628e51d..7293b5efc 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -186,7 +186,7 @@ static int CmdVisa2kClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf visa2000 read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf visa2000 read`") "to verify"); return res; } From 3e11d8d522c22ddcd8e8db2d11ba94bf7d032010 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 15 Mar 2020 13:26:15 +0100 Subject: [PATCH 140/298] update hint loglevel --- client/cmdlfawid.c | 2 +- client/cmdlfem4x.c | 6 +++--- client/cmdlffdx.c | 2 +- client/cmdlfgallagher.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 9bcf9e874..468941022 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -424,7 +424,7 @@ static int CmdAWIDClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf awid read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf awid read`") "to verify"); return res; } diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 02a86c2da..e759a4cf3 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -701,7 +701,7 @@ static int CmdEM410xWrite(const char *Cmd) { SendCommandMIX(CMD_LF_EM410X_WRITE, card, (uint32_t)(id >> 32), (uint32_t)id, NULL, 0); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 410x_read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 410x_read`") "to verify"); return PM3_SUCCESS; } @@ -1041,7 +1041,7 @@ static int CmdEM4x50Write(const char *Cmd) { PrintAndLogEx(NORMAL, "no implemented yet"); // // PrintAndLogEx(SUCCESS, "Done"); -// PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x50_read`") "to verify"); +// PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x50_read`") "to verify"); return PM3_SUCCESS; } @@ -1442,7 +1442,7 @@ static int CmdEM4x05Write(const char *Cmd) { PrintAndLogEx(SUCCESS, "Success writing to tag"); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x05_read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05_read`") "to verify"); return status; } static int CmdEM4x05Wipe(const char *Cmd) { diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 11ec2dd64..58f427a3d 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -303,7 +303,7 @@ static int CmdFdxClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf fdx read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf fdx read`") "to verify"); return res; } diff --git a/client/cmdlfgallagher.c b/client/cmdlfgallagher.c index e44682e2b..97a7e0e09 100644 --- a/client/cmdlfgallagher.c +++ b/client/cmdlfgallagher.c @@ -180,7 +180,7 @@ static int CmdGallagherClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf gallagher read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf gallagher read`") "to verify"); return res; } From 3cf06cf478e7860b88bec53408d14f76eef0469a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 15 Mar 2020 13:27:43 +0100 Subject: [PATCH 141/298] update hint loglevel --- client/cmdlfguard.c | 2 +- client/cmdlfhid.c | 2 +- client/cmdlfindala.c | 10 ++++++++-- client/cmdlfio.c | 2 +- client/cmdlfkeri.c | 2 +- client/cmdlfmotorola.c | 2 +- client/cmdlfnedap.c | 2 +- 7 files changed, 14 insertions(+), 8 deletions(-) diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index ba9023c21..a1dbf0587 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -189,7 +189,7 @@ static int CmdGuardClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf gprox read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf gprox read`") "to verify"); return res; } diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index b5d449623..53af57ab7 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -348,7 +348,7 @@ static int CmdHIDClone(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_LF_HID_CLONE, hi2, hi, lo, longid, sizeof(longid)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf hid read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf hid read`") "to verify"); return PM3_SUCCESS; } diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 6da2aa8f2..e5651a3ad 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -246,7 +246,7 @@ static int CmdIndalaDemod(const char *Cmd) { checksum |= DemodBuffer[63] << 0; // b1 PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "Fmt 26 bit FC " _YELLOW_("%u") ", CN " _YELLOW_("%u") ", checksum %1d%1d" + PrintAndLogEx(SUCCESS, "Fmt 26 bit FC " _YELLOW_("%u") ", CN " _YELLOW_("%u") ", checksum " _YELLOW_("%1d%1d") , fc , csn , checksum >> 1 & 0x01 @@ -505,6 +505,7 @@ static int CmdIndalaSim(const char *Cmd) { uint8_t hexuid[100]; int len = 0; param_gethex_ex(Cmd, 0, hexuid, &len); + if (len > 28) return usage_lf_indala_sim(); @@ -670,7 +671,7 @@ static int CmdIndalaClone(const char *Cmd) { print_blocks(blocks, max); int res = clone_t55xx_tag(blocks, max); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf indala read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf indala read`") "to verify"); return res; } @@ -749,6 +750,11 @@ int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits) { bits[62] = 1; bits[63] = 0; } + + // add parity + bits[34] = 1; // p1 64 - 30 = 34 + bits[38] = 1; // p2 68 - 30 = 38 + // 92 = 62 // 93 = 63 diff --git a/client/cmdlfio.c b/client/cmdlfio.c index 994c69a7d..28c653ab4 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -277,7 +277,7 @@ static int CmdIOProxClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf io read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf io read`") "to verify"); return res; } diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index c698842a6..801307fd3 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -282,7 +282,7 @@ static int CmdKeriClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf keri read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf keri read`") "to verify"); return res; } diff --git a/client/cmdlfmotorola.c b/client/cmdlfmotorola.c index c34b48d8e..66427a49a 100644 --- a/client/cmdlfmotorola.c +++ b/client/cmdlfmotorola.c @@ -179,7 +179,7 @@ static int CmdMotorolaClone(const char *Cmd) { print_blocks(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf motorola read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf motorola read`") "to verify"); return res; } diff --git a/client/cmdlfnedap.c b/client/cmdlfnedap.c index a1d23cd91..5ac4e07fa 100644 --- a/client/cmdlfnedap.c +++ b/client/cmdlfnedap.c @@ -476,7 +476,7 @@ static int CmdLFNedapClone(const char *Cmd) { PrintAndLogEx(NORMAL, ""); } PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf nedap read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf nedap read`") "to verify"); return res; } From 3f8157387871fc11378d070673fe54dab0591d77 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 15 Mar 2020 13:28:39 +0100 Subject: [PATCH 142/298] update hint loglevel --- client/cmdlfnexwatch.c | 2 +- client/cmdlfnoralsy.c | 2 +- client/cmdlfpac.c | 2 +- client/cmdlfparadox.c | 2 +- client/cmdlfpcf7931.c | 2 +- client/cmdlfpresco.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index d288eeadc..5e3801118 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -160,7 +160,7 @@ static int CmdNexWatchClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf nexwatch read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf nexwatch read`") "to verify"); return res; } diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index bbb7de0c9..dc8fb4df0 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -171,7 +171,7 @@ static int CmdNoralsyClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf noralsy read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf noralsy read`") "to verify"); return res; } diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index 9ac9aa511..c633ccc1a 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -241,7 +241,7 @@ static int CmdPacClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf pac read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pac read`") "to verify"); return res; } diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index c540290f8..8422f0f6f 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -171,7 +171,7 @@ static int CmdParadoxClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf paradox read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf paradox read`") "to verify"); return res; } diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c index ddcad195d..c37fc9470 100644 --- a/client/cmdlfpcf7931.c +++ b/client/cmdlfpcf7931.c @@ -151,7 +151,7 @@ static int CmdLFPCF7931Write(const char *Cmd) { SendCommandMIX(CMD_LF_PCF7931_WRITE, block, bytepos, data, buf, sizeof(buf)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf pcf7931 read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 read`") "to verify"); return PM3_SUCCESS; } diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index 9f00dbdce..fe4f3dd1c 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -138,7 +138,7 @@ static int CmdPrescoClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf presco read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf presco read`") "to verify"); return res; } From fb3f4ecd361fe09a9b20d976812b8d995ea4d933 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 15 Mar 2020 13:29:00 +0100 Subject: [PATCH 143/298] update hint loglevel --- client/cmdlfsecurakey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c index 0061d56c4..643ab980d 100644 --- a/client/cmdlfsecurakey.c +++ b/client/cmdlfsecurakey.c @@ -170,7 +170,7 @@ static int CmdSecurakeyClone(const char *Cmd) { int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); PrintAndLogEx(SUCCESS, "Done"); - PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf securakey read`") "to verify"); + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf securakey read`") "to verify"); return res; } From 3d2c0bfdefd3cfb711ea662cb26b7748560d4b31 Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sun, 15 Mar 2020 23:32:53 +1100 Subject: [PATCH 144/298] Add colour to hf mfdes command --- client/cmdhf14a.c | 44 ++++++------ client/cmdhfmfdes.c | 164 ++++++++++++++++++++++---------------------- 2 files changed, 103 insertions(+), 105 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 0355abe85..13a5a9213 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1323,55 +1323,55 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } break; case 0x01: - PrintAndLogEx(SUCCESS, "TYPE : NXP TNP3xxx Activision Game Appliance"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP TNP3xxx Activision Game Appliance")); break; case 0x04: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE (various !DESFire !DESFire EV1)")); isMifareClassic = false; isMifareDesfire = true; break; case 0x08: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1")); break; case 0x09: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Mini 0.3k"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Mini 0.3k")); break; case 0x0A: - PrintAndLogEx(SUCCESS, "TYPE : FM11RF005SH (Shanghai Metro)"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("FM11RF005SH (Shanghai Metro)")); break; case 0x10: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Plus 2k SL2"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Plus 2k SL2")); isMifarePlus = true; break; case 0x11: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Plus 4k SL2"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Plus 4k SL2")); isMifarePlus = true; break; case 0x18: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1")); break; case 0x20: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41")); isMifareClassic = false; isMifareDesfire = true; isMifarePlus = true; break; case 0x24: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE DESFire | DESFire EV1"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE DESFire | DESFire EV1")); isMifareClassic = false; - isMifareDesfire = true; + isMifareDesfire = true; break; case 0x28: - PrintAndLogEx(SUCCESS, "TYPE : JCOP31 or JCOP41 v2.3.1"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("JCOP31 or JCOP41 v2.3.1")); break; case 0x38: - PrintAndLogEx(SUCCESS, "TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("Nokia 6212 or 6131 MIFARE CLASSIC 4K")); break; case 0x88: - PrintAndLogEx(SUCCESS, "TYPE : Infineon MIFARE CLASSIC 1K"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("Infineon MIFARE CLASSIC 1K")); break; case 0x98: - PrintAndLogEx(SUCCESS, "TYPE : Gemplus MPCOS"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("Gemplus MPCOS")); break; default: ; @@ -1379,7 +1379,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { // Double & triple sized UID, can be mapped to a manufacturer. if (card.uidlen > 4) { - PrintAndLogEx(SUCCESS, "MANUFACTURER: " _GREEN_("%s"), getTagInfo(card.uid[0])); + PrintAndLogEx(SUCCESS, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card.uid[0])); } // try to request ATS even if tag claims not to support it @@ -1400,7 +1400,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (select_status == 2) { PrintAndLogEx(INFO, "SAK incorrectly claims that card doesn't support RATS"); } - PrintAndLogEx(SUCCESS, " ATS : %s", sprint_hex(card.ats, card.ats_len)); + PrintAndLogEx(SUCCESS, " ATS: %s", sprint_hex(card.ats, card.ats_len)); PrintAndLogEx(SUCCESS, " - TL : length is %d bytes", card.ats[0]); if (card.ats[0] != card.ats_len - 2) { PrintAndLogEx(SUCCESS, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); @@ -1626,17 +1626,17 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (res == 2 && verbose) PrintAndLogEx(SUCCESS, "Static nonce: " _RED_("fail")); } - - if (isMifareUltralight) { + + if (isMifareUltralight) { PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu info`")); } - if (isMifarePlus) { + if (isMifarePlus) { PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfp info`")); } - if (isMifareDesfire) { + if (isMifareDesfire) { PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfdes info`")); } - + return select_status; } diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 9c35a195d..80f9ea250 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -46,34 +46,34 @@ static int CmdHF14ADesInfo(const char *Cmd) { break; case 3: default: - PrintAndLogEx(WARNING, "Command unsuccessful"); + PrintAndLogEx(WARNING, _RED_("Command unsuccessful")); break; } return PM3_ESOFT; } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "-- Desfire Information --------------------------------------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(resp.data.asBytes, 7)); - PrintAndLogEx(NORMAL, " Batch number : %s", sprint_hex(resp.data.asBytes + 28, 5)); - PrintAndLogEx(NORMAL, " Production date : week %02x, 20%02x", resp.data.asBytes[33], resp.data.asBytes[34]); - PrintAndLogEx(NORMAL, " -----------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Hardware Information"); - PrintAndLogEx(NORMAL, " Vendor Id : %s", getTagInfo(resp.data.asBytes[7])); - PrintAndLogEx(NORMAL, " Type : 0x%02X", resp.data.asBytes[8]); - PrintAndLogEx(NORMAL, " Subtype : 0x%02X", resp.data.asBytes[9]); - PrintAndLogEx(NORMAL, " Version : %s", getVersionStr(resp.data.asBytes[10], resp.data.asBytes[11])); - PrintAndLogEx(NORMAL, " Storage size : %s", getCardSizeStr(resp.data.asBytes[12])); - PrintAndLogEx(NORMAL, " Protocol : %s", getProtocolStr(resp.data.asBytes[13])); - PrintAndLogEx(NORMAL, " -----------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Software Information"); - PrintAndLogEx(NORMAL, " Vendor Id : %s", getTagInfo(resp.data.asBytes[14])); - PrintAndLogEx(NORMAL, " Type : 0x%02X", resp.data.asBytes[15]); - PrintAndLogEx(NORMAL, " Subtype : 0x%02X", resp.data.asBytes[16]); - PrintAndLogEx(NORMAL, " Version : %d.%d", resp.data.asBytes[17], resp.data.asBytes[18]); - PrintAndLogEx(NORMAL, " storage size : %s", getCardSizeStr(resp.data.asBytes[19])); - PrintAndLogEx(NORMAL, " Protocol : %s", getProtocolStr(resp.data.asBytes[20])); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "-- Desfire Information --------------------------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " UID : " _GREEN_("%s"), sprint_hex(resp.data.asBytes, 7)); + PrintAndLogEx(SUCCESS, " Batch number : " _GREEN_("%s"), sprint_hex(resp.data.asBytes + 28, 5)); + PrintAndLogEx(SUCCESS, " Production date : week %02x, 20%02x", resp.data.asBytes[33], resp.data.asBytes[34]); + PrintAndLogEx(INFO, " -----------------------------------------------------------"); + PrintAndLogEx(INFO, " Hardware Information"); + PrintAndLogEx(SUCCESS, " Vendor Id : " _YELLOW_("%s"), getTagInfo(resp.data.asBytes[7])); + PrintAndLogEx(SUCCESS, " Type : " _YELLOW_("0x%02X"), resp.data.asBytes[8]); + PrintAndLogEx(SUCCESS, " Subtype : " _YELLOW_("0x%02X"), resp.data.asBytes[9]); + PrintAndLogEx(SUCCESS, " Version : " _YELLOW_("%s"), getVersionStr(resp.data.asBytes[10], resp.data.asBytes[11])); + PrintAndLogEx(SUCCESS, " Storage size : " _YELLOW_("%s"), getCardSizeStr(resp.data.asBytes[12])); + PrintAndLogEx(SUCCESS, " Protocol : " _YELLOW_("%s"), getProtocolStr(resp.data.asBytes[13])); + PrintAndLogEx(INFO, " -----------------------------------------------------------"); + PrintAndLogEx(INFO, " Software Information"); + PrintAndLogEx(SUCCESS, " Vendor Id : " _YELLOW_("%s"), getTagInfo(resp.data.asBytes[14])); + PrintAndLogEx(SUCCESS, " Type : " _YELLOW_("0x%02X"), resp.data.asBytes[15]); + PrintAndLogEx(SUCCESS, " Subtype : " _YELLOW_("0x%02X"), resp.data.asBytes[16]); + PrintAndLogEx(SUCCESS, " Version : " _YELLOW_("%d.%d"), resp.data.asBytes[17], resp.data.asBytes[18]); + PrintAndLogEx(SUCCESS, " storage size : " _YELLOW_("%s"), getCardSizeStr(resp.data.asBytes[19])); + PrintAndLogEx(SUCCESS, " Protocol : " _YELLOW_("%s"), getProtocolStr(resp.data.asBytes[20])); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); // Master Key settings getKeySettings(NULL); @@ -87,8 +87,8 @@ static int CmdHF14ADesInfo(const char *Cmd) { uint8_t tmp[3]; memcpy(tmp, resp.data.asBytes + 3, 3); - PrintAndLogEx(NORMAL, " Available free memory on card : %d bytes", le24toh(tmp)); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " Available free memory on card : " _GREEN_("%d bytes"), le24toh(tmp)); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); /* Card Master key (CMK) 0x00 AID = 00 00 00 (card level) @@ -168,8 +168,8 @@ void getKeySettings(uint8_t *aid) { //memset(messStr, 0x00, 512); if (aid == NULL) { - PrintAndLogEx(NORMAL, " CMK - PICC, Card Master Key settings "); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, " CMK - PICC, Card Master Key settings"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); { uint8_t data[1] = {GET_KEY_SETTINGS}; // 0x45 SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); @@ -177,18 +177,18 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.oldarg[0] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't select master application"); + PrintAndLogEx(WARNING, _RED_(" Can't select master application")); return; } - str = (resp.data.asBytes[3] & (1 << 3)) ? "YES" : "NO"; - PrintAndLogEx(NORMAL, " [0x08] Configuration changeable : %s", str); - str = (resp.data.asBytes[3] & (1 << 2)) ? "NO" : "YES"; - PrintAndLogEx(NORMAL, " [0x04] CMK required for create/delete : %s", str); - str = (resp.data.asBytes[3] & (1 << 1)) ? "NO" : "YES"; - PrintAndLogEx(NORMAL, " [0x02] Directory list access with CMK : %s", str); - str = (resp.data.asBytes[3] & (1 << 0)) ? "YES" : "NO"; - PrintAndLogEx(NORMAL, " [0x01] CMK is changeable : %s", str); + str = (resp.data.asBytes[3] & (1 << 3)) ? _GREEN_("YES") : _RED_("NO"); + PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", str); + str = (resp.data.asBytes[3] & (1 << 2)) ? _RED_("NO") : _GREEN_("YES"); + PrintAndLogEx(SUCCESS, " [0x04] CMK required for create/delete : %s", str); + str = (resp.data.asBytes[3] & (1 << 1)) ? _RED_("NO") : _GREEN_("YES"); + PrintAndLogEx(SUCCESS, " [0x02] Directory list access with CMK : %s", str); + str = (resp.data.asBytes[3] & (1 << 0)) ? _GREEN_("YES") : _RED_("NO"); + PrintAndLogEx(SUCCESS, " [0x01] CMK is changeable : %s", str); { uint8_t data[2] = {GET_KEY_VERSION, 0}; // 0x64 @@ -198,13 +198,13 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { return; } isOK = resp.oldarg[0] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't read key-version"); + PrintAndLogEx(WARNING, _RED_(" Can't read key-version")); return; } - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Max number of keys : %d", resp.data.asBytes[4]); - PrintAndLogEx(NORMAL, " Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); - PrintAndLogEx(NORMAL, " ----------------------------------------------------------"); + PrintAndLogEx(SUCCESS, ""); + PrintAndLogEx(SUCCESS, " Max number of keys : %d", resp.data.asBytes[4]); + PrintAndLogEx(SUCCESS, " Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); + PrintAndLogEx(INFO, " ----------------------------------------------------------"); { uint8_t data[2] = {AUTHENTICATE, 0}; // 0x0A, KEY 0 @@ -213,7 +213,7 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; - PrintAndLogEx(NORMAL, " [0x0A] Authenticate : %s", (isOK == 0xAE) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); { uint8_t data[2] = {AUTHENTICATE_ISO, 0}; // 0x1A, KEY 0 @@ -222,7 +222,7 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; - PrintAndLogEx(NORMAL, " [0x1A] Authenticate ISO : %s", (isOK == 0xAE) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); { uint8_t data[2] = {AUTHENTICATE_AES, 0}; // 0xAA, KEY 0 @@ -231,12 +231,12 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; - PrintAndLogEx(NORMAL, " [0xAA] Authenticate AES : %s", (isOK == 0xAE) ? "NO" : "YES"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " ----------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); } else { - PrintAndLogEx(NORMAL, " AMK - Application Master Key settings"); + PrintAndLogEx(SUCCESS, " AMK - Application Master Key settings"); + PrintAndLogEx(INFO, " ----------------------------------------------------------"); // SELECT AID { @@ -245,12 +245,12 @@ void getKeySettings(uint8_t *aid) { SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | CLEARTRACE, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(WARNING, " Timed-out"); + PrintAndLogEx(WARNING, _RED_(" Timed-out")); return; } isOK = resp.oldarg[0] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't select AID: %s", sprint_hex(aid, 3)); + PrintAndLogEx(WARNING, " Can't select AID: " _RED_("%s"), sprint_hex(aid, 3)); return; } @@ -265,7 +265,7 @@ void getKeySettings(uint8_t *aid) { } isOK = resp.oldarg[0] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't read Application Master key settings"); + PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings")); } else { // Access rights. uint8_t rights = (resp.data.asBytes[3] >> 4 & 0xff); @@ -283,18 +283,18 @@ void getKeySettings(uint8_t *aid) { str = "Authentication with the specified key is necessary to change any key. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed."; break; } - PrintAndLogEx(NORMAL, "Changekey Access rights"); - PrintAndLogEx(NORMAL, "-- %s", str); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Changekey Access rights"); + PrintAndLogEx(SUCCESS, "-- " _GREEN_("%s"), str); + PrintAndLogEx(SUCCESS, ""); // same as CMK str = (resp.data.asBytes[3] & (1 << 3)) ? "YES" : "NO"; - PrintAndLogEx(NORMAL, " 0x08 Configuration changeable : %s", str); + PrintAndLogEx(SUCCESS, " 0x08 Configuration changeable : %s", str); str = (resp.data.asBytes[3] & (1 << 2)) ? "NO" : "YES"; - PrintAndLogEx(NORMAL, " 0x04 AMK required for create/delete : %s", str); + PrintAndLogEx(SUCCESS, " 0x04 AMK required for create/delete : %s", str); str = (resp.data.asBytes[3] & (1 << 1)) ? "NO" : "YES"; - PrintAndLogEx(NORMAL, " 0x02 Directory list access with AMK : %s", str); + PrintAndLogEx(SUCCESS, " 0x02 Directory list access with AMK : %s", str); str = (resp.data.asBytes[3] & (1 << 0)) ? "YES" : "NO"; - PrintAndLogEx(NORMAL, " 0x01 AMK is changeable : %s", str); + PrintAndLogEx(SUCCESS, " 0x01 AMK is changeable : %s", str); } // KEY VERSION - AMK @@ -304,7 +304,7 @@ void getKeySettings(uint8_t *aid) { } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(WARNING, " Timed-out"); + PrintAndLogEx(WARNING, _RED_(" Timed-out")); return; } @@ -316,10 +316,9 @@ void getKeySettings(uint8_t *aid) { //numOfKeys = MAX_NUM_KEYS; } else { numOfKeys = resp.data.asBytes[4]; - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Max number of keys : %d", numOfKeys); - PrintAndLogEx(NORMAL, " Application Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " Max number of keys : %d", numOfKeys); + PrintAndLogEx(SUCCESS, " Application Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); } // LOOP over numOfKeys that we got before. @@ -349,12 +348,12 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { isOK = resp.oldarg[0] & 0xff; if (!isOK) { - PrintAndLogEx(NORMAL, "Command unsuccessful"); + PrintAndLogEx(WARNING, _RED_("Command unsuccessful")); return PM3_ESOFT; } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "-- Desfire Enumerate Applications ---------------------------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, "-- Desfire Enumerate Applications ---------------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); PacketResponseNG respAid; PacketResponseNG respFiles; @@ -363,7 +362,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { int max = resp.oldarg[1] - 3 - 2; for (int i = 3; i <= max; i += 3) { - PrintAndLogEx(NORMAL, " Aid %d : %02X %02X %02X ", num, resp.data.asBytes[i], resp.data.asBytes[i + 1], resp.data.asBytes[i + 2]); + PrintAndLogEx(SUCCESS, " Aid %d : %02X %02X %02X ", num, resp.data.asBytes[i], resp.data.asBytes[i + 1], resp.data.asBytes[i + 2]); num++; aid[0] = resp.data.asBytes[i]; @@ -379,12 +378,12 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { } if (!WaitForResponseTimeout(CMD_ACK, &respAid, 1500)) { - PrintAndLogEx(WARNING, " Timed-out"); + PrintAndLogEx(WARNING, _RED_(" Timed-out")); continue; } isOK = respAid.data.asBytes[2] & 0xff; if (isOK != 0x00) { - PrintAndLogEx(WARNING, " Can't select AID: %s", sprint_hex(resp.data.asBytes + i, 3)); + PrintAndLogEx(WARNING, " Can't select AID: " _RED_("%s"), sprint_hex(resp.data.asBytes + i, 3)); continue; } @@ -395,16 +394,16 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { } if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) { - PrintAndLogEx(WARNING, " Timed-out"); + PrintAndLogEx(WARNING, _RED_(" Timed-out")); continue; } else { isOK = respFiles.data.asBytes[2] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't get file ids "); + PrintAndLogEx(WARNING, _RED_(" Can't get file ids ")); } else { int respfileLen = resp.oldarg[1] - 3 - 2; for (int j = 0; j < respfileLen; ++j) { - PrintAndLogEx(NORMAL, " Fileid %d :", resp.data.asBytes[j + 3]); + PrintAndLogEx(SUCCESS, " Fileid %d :", resp.data.asBytes[j + 3]); } } } @@ -416,21 +415,21 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { } if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) { - PrintAndLogEx(WARNING, " Timed-out"); + PrintAndLogEx(WARNING, _RED_(" Timed-out")); continue; } else { isOK = respFiles.data.asBytes[2] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't get ISO file ids "); + PrintAndLogEx(WARNING, _RED_(" Can't get ISO file ids")); } else { int respfileLen = resp.oldarg[1] - 3 - 2; for (int j = 0; j < respfileLen; ++j) { - PrintAndLogEx(NORMAL, " ISO Fileid %d :", resp.data.asBytes[j + 3]); + PrintAndLogEx(SUCCESS, " ISO Fileid %d :", resp.data.asBytes[j + 3]); } } } } - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; } @@ -457,8 +456,8 @@ static int CmdHF14ADesAuth(const char *Cmd) { PrintAndLogEx(NORMAL, " 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfdes auth 1 1 0 11223344"); - PrintAndLogEx(NORMAL, " hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfdes auth 1 1 0 11223344")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f")); return PM3_SUCCESS; } uint8_t cmdAuthMode = param_get8(Cmd, 0); @@ -531,14 +530,14 @@ static int CmdHF14ADesAuth(const char *Cmd) { if (isOK) { uint8_t *session_key = resp.data.asBytes; - PrintAndLogEx(NORMAL, " Key :%s", sprint_hex(key, keylength)); - PrintAndLogEx(NORMAL, " SESSION :%s", sprint_hex(session_key, keylength)); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " Key : " _GREEN_("%s"), sprint_hex(key, keylength)); + PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(session_key, keylength)); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); //PrintAndLogEx(NORMAL, " Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56"); } else { - PrintAndLogEx(NORMAL, "Client command failed."); + PrintAndLogEx(WARNING, _RED_("Client command failed.")); } - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; } @@ -564,4 +563,3 @@ int CmdHFMFDes(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } - From daba35687143d52ae076318a575c3e4d3ee17fb3 Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sun, 15 Mar 2020 23:32:53 +1100 Subject: [PATCH 145/298] Add colour to hf mfdes command --- CHANGELOG.md | 2 + client/cmdhf14a.c | 44 ++++++------ client/cmdhfmfdes.c | 164 ++++++++++++++++++++++---------------------- 3 files changed, 105 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fa346660..bddf4c141 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Add colour to `hf mfdes` command (@dunderhay) + - Change type colour for `hf 14a` card types (@dunderhay) - Add 'HINTS' command. Will turn off / on hint messages. Default mode is OFF. (@iceman1001) - Add colour to `hf 14a` and `hf mfu` commands (@dunderhay) - Add colour to `lf hid` commands (@dunderhay) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 0355abe85..13a5a9213 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1323,55 +1323,55 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } break; case 0x01: - PrintAndLogEx(SUCCESS, "TYPE : NXP TNP3xxx Activision Game Appliance"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP TNP3xxx Activision Game Appliance")); break; case 0x04: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE (various !DESFire !DESFire EV1)")); isMifareClassic = false; isMifareDesfire = true; break; case 0x08: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1")); break; case 0x09: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Mini 0.3k"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Mini 0.3k")); break; case 0x0A: - PrintAndLogEx(SUCCESS, "TYPE : FM11RF005SH (Shanghai Metro)"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("FM11RF005SH (Shanghai Metro)")); break; case 0x10: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Plus 2k SL2"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Plus 2k SL2")); isMifarePlus = true; break; case 0x11: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Plus 4k SL2"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Plus 4k SL2")); isMifarePlus = true; break; case 0x18: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1")); break; case 0x20: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41")); isMifareClassic = false; isMifareDesfire = true; isMifarePlus = true; break; case 0x24: - PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE DESFire | DESFire EV1"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("NXP MIFARE DESFire | DESFire EV1")); isMifareClassic = false; - isMifareDesfire = true; + isMifareDesfire = true; break; case 0x28: - PrintAndLogEx(SUCCESS, "TYPE : JCOP31 or JCOP41 v2.3.1"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("JCOP31 or JCOP41 v2.3.1")); break; case 0x38: - PrintAndLogEx(SUCCESS, "TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("Nokia 6212 or 6131 MIFARE CLASSIC 4K")); break; case 0x88: - PrintAndLogEx(SUCCESS, "TYPE : Infineon MIFARE CLASSIC 1K"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("Infineon MIFARE CLASSIC 1K")); break; case 0x98: - PrintAndLogEx(SUCCESS, "TYPE : Gemplus MPCOS"); + PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("Gemplus MPCOS")); break; default: ; @@ -1379,7 +1379,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { // Double & triple sized UID, can be mapped to a manufacturer. if (card.uidlen > 4) { - PrintAndLogEx(SUCCESS, "MANUFACTURER: " _GREEN_("%s"), getTagInfo(card.uid[0])); + PrintAndLogEx(SUCCESS, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card.uid[0])); } // try to request ATS even if tag claims not to support it @@ -1400,7 +1400,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (select_status == 2) { PrintAndLogEx(INFO, "SAK incorrectly claims that card doesn't support RATS"); } - PrintAndLogEx(SUCCESS, " ATS : %s", sprint_hex(card.ats, card.ats_len)); + PrintAndLogEx(SUCCESS, " ATS: %s", sprint_hex(card.ats, card.ats_len)); PrintAndLogEx(SUCCESS, " - TL : length is %d bytes", card.ats[0]); if (card.ats[0] != card.ats_len - 2) { PrintAndLogEx(SUCCESS, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); @@ -1626,17 +1626,17 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (res == 2 && verbose) PrintAndLogEx(SUCCESS, "Static nonce: " _RED_("fail")); } - - if (isMifareUltralight) { + + if (isMifareUltralight) { PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu info`")); } - if (isMifarePlus) { + if (isMifarePlus) { PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfp info`")); } - if (isMifareDesfire) { + if (isMifareDesfire) { PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfdes info`")); } - + return select_status; } diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 9c35a195d..80f9ea250 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -46,34 +46,34 @@ static int CmdHF14ADesInfo(const char *Cmd) { break; case 3: default: - PrintAndLogEx(WARNING, "Command unsuccessful"); + PrintAndLogEx(WARNING, _RED_("Command unsuccessful")); break; } return PM3_ESOFT; } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "-- Desfire Information --------------------------------------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(resp.data.asBytes, 7)); - PrintAndLogEx(NORMAL, " Batch number : %s", sprint_hex(resp.data.asBytes + 28, 5)); - PrintAndLogEx(NORMAL, " Production date : week %02x, 20%02x", resp.data.asBytes[33], resp.data.asBytes[34]); - PrintAndLogEx(NORMAL, " -----------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Hardware Information"); - PrintAndLogEx(NORMAL, " Vendor Id : %s", getTagInfo(resp.data.asBytes[7])); - PrintAndLogEx(NORMAL, " Type : 0x%02X", resp.data.asBytes[8]); - PrintAndLogEx(NORMAL, " Subtype : 0x%02X", resp.data.asBytes[9]); - PrintAndLogEx(NORMAL, " Version : %s", getVersionStr(resp.data.asBytes[10], resp.data.asBytes[11])); - PrintAndLogEx(NORMAL, " Storage size : %s", getCardSizeStr(resp.data.asBytes[12])); - PrintAndLogEx(NORMAL, " Protocol : %s", getProtocolStr(resp.data.asBytes[13])); - PrintAndLogEx(NORMAL, " -----------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Software Information"); - PrintAndLogEx(NORMAL, " Vendor Id : %s", getTagInfo(resp.data.asBytes[14])); - PrintAndLogEx(NORMAL, " Type : 0x%02X", resp.data.asBytes[15]); - PrintAndLogEx(NORMAL, " Subtype : 0x%02X", resp.data.asBytes[16]); - PrintAndLogEx(NORMAL, " Version : %d.%d", resp.data.asBytes[17], resp.data.asBytes[18]); - PrintAndLogEx(NORMAL, " storage size : %s", getCardSizeStr(resp.data.asBytes[19])); - PrintAndLogEx(NORMAL, " Protocol : %s", getProtocolStr(resp.data.asBytes[20])); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "-- Desfire Information --------------------------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " UID : " _GREEN_("%s"), sprint_hex(resp.data.asBytes, 7)); + PrintAndLogEx(SUCCESS, " Batch number : " _GREEN_("%s"), sprint_hex(resp.data.asBytes + 28, 5)); + PrintAndLogEx(SUCCESS, " Production date : week %02x, 20%02x", resp.data.asBytes[33], resp.data.asBytes[34]); + PrintAndLogEx(INFO, " -----------------------------------------------------------"); + PrintAndLogEx(INFO, " Hardware Information"); + PrintAndLogEx(SUCCESS, " Vendor Id : " _YELLOW_("%s"), getTagInfo(resp.data.asBytes[7])); + PrintAndLogEx(SUCCESS, " Type : " _YELLOW_("0x%02X"), resp.data.asBytes[8]); + PrintAndLogEx(SUCCESS, " Subtype : " _YELLOW_("0x%02X"), resp.data.asBytes[9]); + PrintAndLogEx(SUCCESS, " Version : " _YELLOW_("%s"), getVersionStr(resp.data.asBytes[10], resp.data.asBytes[11])); + PrintAndLogEx(SUCCESS, " Storage size : " _YELLOW_("%s"), getCardSizeStr(resp.data.asBytes[12])); + PrintAndLogEx(SUCCESS, " Protocol : " _YELLOW_("%s"), getProtocolStr(resp.data.asBytes[13])); + PrintAndLogEx(INFO, " -----------------------------------------------------------"); + PrintAndLogEx(INFO, " Software Information"); + PrintAndLogEx(SUCCESS, " Vendor Id : " _YELLOW_("%s"), getTagInfo(resp.data.asBytes[14])); + PrintAndLogEx(SUCCESS, " Type : " _YELLOW_("0x%02X"), resp.data.asBytes[15]); + PrintAndLogEx(SUCCESS, " Subtype : " _YELLOW_("0x%02X"), resp.data.asBytes[16]); + PrintAndLogEx(SUCCESS, " Version : " _YELLOW_("%d.%d"), resp.data.asBytes[17], resp.data.asBytes[18]); + PrintAndLogEx(SUCCESS, " storage size : " _YELLOW_("%s"), getCardSizeStr(resp.data.asBytes[19])); + PrintAndLogEx(SUCCESS, " Protocol : " _YELLOW_("%s"), getProtocolStr(resp.data.asBytes[20])); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); // Master Key settings getKeySettings(NULL); @@ -87,8 +87,8 @@ static int CmdHF14ADesInfo(const char *Cmd) { uint8_t tmp[3]; memcpy(tmp, resp.data.asBytes + 3, 3); - PrintAndLogEx(NORMAL, " Available free memory on card : %d bytes", le24toh(tmp)); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " Available free memory on card : " _GREEN_("%d bytes"), le24toh(tmp)); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); /* Card Master key (CMK) 0x00 AID = 00 00 00 (card level) @@ -168,8 +168,8 @@ void getKeySettings(uint8_t *aid) { //memset(messStr, 0x00, 512); if (aid == NULL) { - PrintAndLogEx(NORMAL, " CMK - PICC, Card Master Key settings "); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, " CMK - PICC, Card Master Key settings"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); { uint8_t data[1] = {GET_KEY_SETTINGS}; // 0x45 SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); @@ -177,18 +177,18 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.oldarg[0] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't select master application"); + PrintAndLogEx(WARNING, _RED_(" Can't select master application")); return; } - str = (resp.data.asBytes[3] & (1 << 3)) ? "YES" : "NO"; - PrintAndLogEx(NORMAL, " [0x08] Configuration changeable : %s", str); - str = (resp.data.asBytes[3] & (1 << 2)) ? "NO" : "YES"; - PrintAndLogEx(NORMAL, " [0x04] CMK required for create/delete : %s", str); - str = (resp.data.asBytes[3] & (1 << 1)) ? "NO" : "YES"; - PrintAndLogEx(NORMAL, " [0x02] Directory list access with CMK : %s", str); - str = (resp.data.asBytes[3] & (1 << 0)) ? "YES" : "NO"; - PrintAndLogEx(NORMAL, " [0x01] CMK is changeable : %s", str); + str = (resp.data.asBytes[3] & (1 << 3)) ? _GREEN_("YES") : _RED_("NO"); + PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", str); + str = (resp.data.asBytes[3] & (1 << 2)) ? _RED_("NO") : _GREEN_("YES"); + PrintAndLogEx(SUCCESS, " [0x04] CMK required for create/delete : %s", str); + str = (resp.data.asBytes[3] & (1 << 1)) ? _RED_("NO") : _GREEN_("YES"); + PrintAndLogEx(SUCCESS, " [0x02] Directory list access with CMK : %s", str); + str = (resp.data.asBytes[3] & (1 << 0)) ? _GREEN_("YES") : _RED_("NO"); + PrintAndLogEx(SUCCESS, " [0x01] CMK is changeable : %s", str); { uint8_t data[2] = {GET_KEY_VERSION, 0}; // 0x64 @@ -198,13 +198,13 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { return; } isOK = resp.oldarg[0] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't read key-version"); + PrintAndLogEx(WARNING, _RED_(" Can't read key-version")); return; } - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Max number of keys : %d", resp.data.asBytes[4]); - PrintAndLogEx(NORMAL, " Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); - PrintAndLogEx(NORMAL, " ----------------------------------------------------------"); + PrintAndLogEx(SUCCESS, ""); + PrintAndLogEx(SUCCESS, " Max number of keys : %d", resp.data.asBytes[4]); + PrintAndLogEx(SUCCESS, " Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); + PrintAndLogEx(INFO, " ----------------------------------------------------------"); { uint8_t data[2] = {AUTHENTICATE, 0}; // 0x0A, KEY 0 @@ -213,7 +213,7 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; - PrintAndLogEx(NORMAL, " [0x0A] Authenticate : %s", (isOK == 0xAE) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); { uint8_t data[2] = {AUTHENTICATE_ISO, 0}; // 0x1A, KEY 0 @@ -222,7 +222,7 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; - PrintAndLogEx(NORMAL, " [0x1A] Authenticate ISO : %s", (isOK == 0xAE) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); { uint8_t data[2] = {AUTHENTICATE_AES, 0}; // 0xAA, KEY 0 @@ -231,12 +231,12 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; - PrintAndLogEx(NORMAL, " [0xAA] Authenticate AES : %s", (isOK == 0xAE) ? "NO" : "YES"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " ----------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); } else { - PrintAndLogEx(NORMAL, " AMK - Application Master Key settings"); + PrintAndLogEx(SUCCESS, " AMK - Application Master Key settings"); + PrintAndLogEx(INFO, " ----------------------------------------------------------"); // SELECT AID { @@ -245,12 +245,12 @@ void getKeySettings(uint8_t *aid) { SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | CLEARTRACE, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(WARNING, " Timed-out"); + PrintAndLogEx(WARNING, _RED_(" Timed-out")); return; } isOK = resp.oldarg[0] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't select AID: %s", sprint_hex(aid, 3)); + PrintAndLogEx(WARNING, " Can't select AID: " _RED_("%s"), sprint_hex(aid, 3)); return; } @@ -265,7 +265,7 @@ void getKeySettings(uint8_t *aid) { } isOK = resp.oldarg[0] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't read Application Master key settings"); + PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings")); } else { // Access rights. uint8_t rights = (resp.data.asBytes[3] >> 4 & 0xff); @@ -283,18 +283,18 @@ void getKeySettings(uint8_t *aid) { str = "Authentication with the specified key is necessary to change any key. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed."; break; } - PrintAndLogEx(NORMAL, "Changekey Access rights"); - PrintAndLogEx(NORMAL, "-- %s", str); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Changekey Access rights"); + PrintAndLogEx(SUCCESS, "-- " _GREEN_("%s"), str); + PrintAndLogEx(SUCCESS, ""); // same as CMK str = (resp.data.asBytes[3] & (1 << 3)) ? "YES" : "NO"; - PrintAndLogEx(NORMAL, " 0x08 Configuration changeable : %s", str); + PrintAndLogEx(SUCCESS, " 0x08 Configuration changeable : %s", str); str = (resp.data.asBytes[3] & (1 << 2)) ? "NO" : "YES"; - PrintAndLogEx(NORMAL, " 0x04 AMK required for create/delete : %s", str); + PrintAndLogEx(SUCCESS, " 0x04 AMK required for create/delete : %s", str); str = (resp.data.asBytes[3] & (1 << 1)) ? "NO" : "YES"; - PrintAndLogEx(NORMAL, " 0x02 Directory list access with AMK : %s", str); + PrintAndLogEx(SUCCESS, " 0x02 Directory list access with AMK : %s", str); str = (resp.data.asBytes[3] & (1 << 0)) ? "YES" : "NO"; - PrintAndLogEx(NORMAL, " 0x01 AMK is changeable : %s", str); + PrintAndLogEx(SUCCESS, " 0x01 AMK is changeable : %s", str); } // KEY VERSION - AMK @@ -304,7 +304,7 @@ void getKeySettings(uint8_t *aid) { } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(WARNING, " Timed-out"); + PrintAndLogEx(WARNING, _RED_(" Timed-out")); return; } @@ -316,10 +316,9 @@ void getKeySettings(uint8_t *aid) { //numOfKeys = MAX_NUM_KEYS; } else { numOfKeys = resp.data.asBytes[4]; - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Max number of keys : %d", numOfKeys); - PrintAndLogEx(NORMAL, " Application Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " Max number of keys : %d", numOfKeys); + PrintAndLogEx(SUCCESS, " Application Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); } // LOOP over numOfKeys that we got before. @@ -349,12 +348,12 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { isOK = resp.oldarg[0] & 0xff; if (!isOK) { - PrintAndLogEx(NORMAL, "Command unsuccessful"); + PrintAndLogEx(WARNING, _RED_("Command unsuccessful")); return PM3_ESOFT; } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "-- Desfire Enumerate Applications ---------------------------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, "-- Desfire Enumerate Applications ---------------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); PacketResponseNG respAid; PacketResponseNG respFiles; @@ -363,7 +362,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { int max = resp.oldarg[1] - 3 - 2; for (int i = 3; i <= max; i += 3) { - PrintAndLogEx(NORMAL, " Aid %d : %02X %02X %02X ", num, resp.data.asBytes[i], resp.data.asBytes[i + 1], resp.data.asBytes[i + 2]); + PrintAndLogEx(SUCCESS, " Aid %d : %02X %02X %02X ", num, resp.data.asBytes[i], resp.data.asBytes[i + 1], resp.data.asBytes[i + 2]); num++; aid[0] = resp.data.asBytes[i]; @@ -379,12 +378,12 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { } if (!WaitForResponseTimeout(CMD_ACK, &respAid, 1500)) { - PrintAndLogEx(WARNING, " Timed-out"); + PrintAndLogEx(WARNING, _RED_(" Timed-out")); continue; } isOK = respAid.data.asBytes[2] & 0xff; if (isOK != 0x00) { - PrintAndLogEx(WARNING, " Can't select AID: %s", sprint_hex(resp.data.asBytes + i, 3)); + PrintAndLogEx(WARNING, " Can't select AID: " _RED_("%s"), sprint_hex(resp.data.asBytes + i, 3)); continue; } @@ -395,16 +394,16 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { } if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) { - PrintAndLogEx(WARNING, " Timed-out"); + PrintAndLogEx(WARNING, _RED_(" Timed-out")); continue; } else { isOK = respFiles.data.asBytes[2] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't get file ids "); + PrintAndLogEx(WARNING, _RED_(" Can't get file ids ")); } else { int respfileLen = resp.oldarg[1] - 3 - 2; for (int j = 0; j < respfileLen; ++j) { - PrintAndLogEx(NORMAL, " Fileid %d :", resp.data.asBytes[j + 3]); + PrintAndLogEx(SUCCESS, " Fileid %d :", resp.data.asBytes[j + 3]); } } } @@ -416,21 +415,21 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { } if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) { - PrintAndLogEx(WARNING, " Timed-out"); + PrintAndLogEx(WARNING, _RED_(" Timed-out")); continue; } else { isOK = respFiles.data.asBytes[2] & 0xff; if (!isOK) { - PrintAndLogEx(WARNING, " Can't get ISO file ids "); + PrintAndLogEx(WARNING, _RED_(" Can't get ISO file ids")); } else { int respfileLen = resp.oldarg[1] - 3 - 2; for (int j = 0; j < respfileLen; ++j) { - PrintAndLogEx(NORMAL, " ISO Fileid %d :", resp.data.asBytes[j + 3]); + PrintAndLogEx(SUCCESS, " ISO Fileid %d :", resp.data.asBytes[j + 3]); } } } } - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; } @@ -457,8 +456,8 @@ static int CmdHF14ADesAuth(const char *Cmd) { PrintAndLogEx(NORMAL, " 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mfdes auth 1 1 0 11223344"); - PrintAndLogEx(NORMAL, " hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfdes auth 1 1 0 11223344")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f")); return PM3_SUCCESS; } uint8_t cmdAuthMode = param_get8(Cmd, 0); @@ -531,14 +530,14 @@ static int CmdHF14ADesAuth(const char *Cmd) { if (isOK) { uint8_t *session_key = resp.data.asBytes; - PrintAndLogEx(NORMAL, " Key :%s", sprint_hex(key, keylength)); - PrintAndLogEx(NORMAL, " SESSION :%s", sprint_hex(session_key, keylength)); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " Key : " _GREEN_("%s"), sprint_hex(key, keylength)); + PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(session_key, keylength)); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); //PrintAndLogEx(NORMAL, " Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56"); } else { - PrintAndLogEx(NORMAL, "Client command failed."); + PrintAndLogEx(WARNING, _RED_("Client command failed.")); } - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; } @@ -564,4 +563,3 @@ int CmdHFMFDes(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } - From e5b38c46c60dd199f1b923f5f835358bbad1597d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 15 Mar 2020 13:48:50 +0100 Subject: [PATCH 146/298] chg: hints - allow ON/OFF --- client/cmdmain.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/client/cmdmain.c b/client/cmdmain.c index d9cbbac74..57cd4d10a 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -194,20 +194,31 @@ int CmdRem(const char *Cmd) { static int CmdHints(const char *Cmd) { uint32_t ms = 0; char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hints(); + if (ctmp == 'h') return usage_hints(); if (strlen(Cmd) < 1) { PrintAndLogEx(INFO, "Hints are %s", (g_showhints) ? "ON" : "OFF"); return PM3_SUCCESS; } - if (param_getchar(Cmd, 0) != 0x00) { - ms = param_get32ex(Cmd, 0, 0, 10); - if (ms == 0) + if (strlen(Cmd) > 1){ + str_lower((char *)Cmd); + if (str_startswith(Cmd, "of")) { g_showhints = false; - else - g_showhints = true; + } else { + g_showhints = true; + } + } else { + if (param_getchar(Cmd, 0) != 0x00) { + ms = param_get32ex(Cmd, 0, 0, 10); + if (ms == 0) { + g_showhints = false; + } else { + g_showhints = true; + } + } } + PrintAndLogEx(INFO, "Hints are %s", (g_showhints) ? "ON" : "OFF"); return PM3_SUCCESS; } From eb99a09d474be9b4047b283d55e103c9776fa12b Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Sun, 15 Mar 2020 23:52:05 +1100 Subject: [PATCH 147/298] Change mf card type colour from green to yellow --- CHANGELOG.md | 2 +- client/cmdhfmfu.c | 46 +++++++++++++++++++++++----------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bddf4c141..f6d2e03c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] - - Add colour to `hf mfdes` command (@dunderhay) - Change type colour for `hf 14a` card types (@dunderhay) + - Add colour to `hf mfdes` command (@dunderhay) - Add 'HINTS' command. Will turn off / on hint messages. Default mode is OFF. (@iceman1001) - Add colour to `hf 14a` and `hf mfu` commands (@dunderhay) - Add colour to `lf hid` commands (@dunderhay) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index ccc749708..5c70f37cd 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -679,55 +679,55 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) { char *spacer = spc + (10 - spaces); if (tagtype & UL) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("MIFARE Ultralight (MF0ICU1) %s"), spacer, (tagtype & MAGIC) ? "" : ""); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1) %s"), spacer, (tagtype & MAGIC) ? "" : ""); else if (tagtype & UL_C) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("MIFARE Ultralight C (MF0ULC) %s"), spacer, (tagtype & MAGIC) ? "" : ""); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC) %s"), spacer, (tagtype & MAGIC) ? "" : ""); else if (tagtype & UL_NANO_40) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spacer); else if (tagtype & UL_EV1_48) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spacer); else if (tagtype & UL_EV1_128) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spacer); else if (tagtype & UL_EV1) PrintAndLogEx(NORMAL, "%sTYPE: " _YELLOW_("MIFARE Ultralight EV1 UNKNOWN"), spacer); else if (tagtype & NTAG) PrintAndLogEx(NORMAL, "%sTYPE: " _YELLOW_("NTAG UNKNOWN"), spacer); else if (tagtype & NTAG_203) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 203 144bytes (NT2H0301F0DT)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG 203 144bytes (NT2H0301F0DT)"), spacer); else if (tagtype & NTAG_210) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 210 48bytes (NT2L1011G0DU)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG 210 48bytes (NT2L1011G0DU)"), spacer); else if (tagtype & NTAG_212) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 212 128bytes (NT2L1211G0DU)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG 212 128bytes (NT2L1211G0DU)"), spacer); else if (tagtype & NTAG_213) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 213 144bytes (NT2H1311G0DU)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG 213 144bytes (NT2H1311G0DU)"), spacer); else if (tagtype & NTAG_213_F) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spacer); else if (tagtype & NTAG_215) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 215 504bytes (NT2H1511G0DU)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG 215 504bytes (NT2H1511G0DU)"), spacer); else if (tagtype & NTAG_216) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 216 888bytes (NT2H1611G0DU)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG 216 888bytes (NT2H1611G0DU)"), spacer); else if (tagtype & NTAG_216_F) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spacer); else if (tagtype & NTAG_I2C_1K) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG I2C 888bytes (NT3H1101FHK)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG I2C 888bytes (NT3H1101FHK)"), spacer); else if (tagtype & NTAG_I2C_2K) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG I2C 1904bytes (NT3H1201FHK)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG I2C 1904bytes (NT3H1201FHK)"), spacer); else if (tagtype & NTAG_I2C_1K_PLUS) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spacer); else if (tagtype & NTAG_I2C_2K_PLUS) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spacer); else if (tagtype & MY_D) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("INFINEON my-d\x99 (SLE 66RxxS)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("INFINEON my-d\x99 (SLE 66RxxS)"), spacer); else if (tagtype & MY_D_NFC) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spacer); else if (tagtype & MY_D_MOVE) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("INFINEON my-d\x99 move (SLE 66R01P)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("INFINEON my-d\x99 move (SLE 66R01P)"), spacer); else if (tagtype & MY_D_MOVE_NFC) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spacer); else if (tagtype & MY_D_MOVE_LEAN) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spacer); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spacer); else if (tagtype & FUDAN_UL) - PrintAndLogEx(SUCCESS, "%sTYPE: " _GREEN_("FUDAN Ultralight Compatible (or other compatible) %s"), spacer, (tagtype & MAGIC) ? "" : ""); + PrintAndLogEx(SUCCESS, "%sTYPE: " _YELLOW_("FUDAN Ultralight Compatible (or other compatible) %s"), spacer, (tagtype & MAGIC) ? "" : ""); else PrintAndLogEx(NORMAL, "%sTYPE: " _YELLOW_("Unknown %06x"), spacer, tagtype); return PM3_SUCCESS; From 4a8a0eca981c30bc5137e7d7b1e1179becba82b3 Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Mon, 16 Mar 2020 00:02:18 +1100 Subject: [PATCH 148/298] Additional colour changes --- CHANGELOG.md | 1 + client/cmdhfmfdes.c | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6d2e03c2..1066a1f92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Additional colour changes as recommended by @iceman (@dunderhay) - Change type colour for `hf 14a` card types (@dunderhay) - Add colour to `hf mfdes` command (@dunderhay) - Add 'HINTS' command. Will turn off / on hint messages. Default mode is OFF. (@iceman1001) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 80f9ea250..698af4a2d 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -181,13 +181,13 @@ void getKeySettings(uint8_t *aid) { return; } - str = (resp.data.asBytes[3] & (1 << 3)) ? _GREEN_("YES") : _RED_("NO"); + str = (resp.data.asBytes[3] & (1 << 3)) ? _GREEN_("YES") : "NO"; PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", str); - str = (resp.data.asBytes[3] & (1 << 2)) ? _RED_("NO") : _GREEN_("YES"); + str = (resp.data.asBytes[3] & (1 << 2)) ? "NO" : _GREEN_("YES"); PrintAndLogEx(SUCCESS, " [0x04] CMK required for create/delete : %s", str); - str = (resp.data.asBytes[3] & (1 << 1)) ? _RED_("NO") : _GREEN_("YES"); + str = (resp.data.asBytes[3] & (1 << 1)) ? "NO" : _GREEN_("YES"); PrintAndLogEx(SUCCESS, " [0x02] Directory list access with CMK : %s", str); - str = (resp.data.asBytes[3] & (1 << 0)) ? _GREEN_("YES") : _RED_("NO"); + str = (resp.data.asBytes[3] & (1 << 0)) ? _GREEN_("YES") : "NO"; PrintAndLogEx(SUCCESS, " [0x01] CMK is changeable : %s", str); { @@ -202,8 +202,8 @@ void getKeySettings(uint8_t *aid) { return; } PrintAndLogEx(SUCCESS, ""); - PrintAndLogEx(SUCCESS, " Max number of keys : %d", resp.data.asBytes[4]); - PrintAndLogEx(SUCCESS, " Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); + PrintAndLogEx(SUCCESS, " Max number of keys : " _YELLOW_("%d"), resp.data.asBytes[4]); + PrintAndLogEx(SUCCESS, " Master key Version : " _YELLOW_("%d (0x%02x)"), resp.data.asBytes[3], resp.data.asBytes[3]); PrintAndLogEx(INFO, " ----------------------------------------------------------"); { From 5e3c070ab9c950b12528ff7a168a71a61b44cb2a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 15 Mar 2020 22:41:05 +0100 Subject: [PATCH 149/298] emojis support --- client/cmdhf.c | 4 +- client/cmdlf.c | 4 +- client/emojis.h | 1862 +++++++++++++++++++++++++++++++++ client/emojis_alt.h | 15 + client/emojis_scrap_github.py | 35 + client/proxmark3.c | 7 +- client/ui.c | 159 ++- client/ui.h | 6 +- 8 files changed, 2070 insertions(+), 22 deletions(-) create mode 100644 client/emojis.h create mode 100644 client/emojis_alt.h create mode 100755 client/emojis_scrap_github.py diff --git a/client/cmdhf.c b/client/cmdhf.c index 35b50b852..418cc8b90 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -178,7 +178,7 @@ int CmdHFTune(const char *Cmd) { if (cmdp == 'h') return usage_hf_tune(); int iter = param_get32ex(Cmd, 0, 0, 10); - PrintAndLogEx(SUCCESS, "Measuring HF antenna, click " _GREEN_("pm3 button") "or press " _GREEN_("Enter") "to exit"); + PrintAndLogEx(INFO, "Measuring HF antenna, click " _GREEN_("pm3 button") "or press " _GREEN_("Enter") "to exit"); PacketResponseNG resp; clearCommandBuffer(); @@ -218,7 +218,7 @@ int CmdHFTune(const char *Cmd) { return PM3_ETIMEOUT; } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "Done."); + PrintAndLogEx(INFO, "Done."); return PM3_SUCCESS; } diff --git a/client/cmdlf.c b/client/cmdlf.c index 29854c6b6..d61aff0ca 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -253,7 +253,7 @@ static int CmdLFTune(const char *Cmd) { //Validations if (errors) return usage_lf_tune(); - PrintAndLogEx(SUCCESS, "Measuring LF antenna at " _YELLOW_("%.2f") "kHz, click " _GREEN_("pm3 button") "or press " _GREEN_("Enter") "to exit", LF_DIV2FREQ(divisor)); + PrintAndLogEx(INFO, "Measuring LF antenna at " _YELLOW_("%.2f") "kHz, click " _GREEN_("pm3 button") "or press " _GREEN_("Enter") "to exit", LF_DIV2FREQ(divisor)); uint8_t params[] = {1, 0}; params[1] = divisor; @@ -295,7 +295,7 @@ static int CmdLFTune(const char *Cmd) { return PM3_ETIMEOUT; } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "Done."); + PrintAndLogEx(INFO, "Done."); return PM3_SUCCESS; } diff --git a/client/emojis.h b/client/emojis.h new file mode 100644 index 000000000..b7ef0e92a --- /dev/null +++ b/client/emojis.h @@ -0,0 +1,1862 @@ +#ifndef EMOJIS_H__ +#define EMOJIS_H__ + +typedef struct emoji_s { + const char *alias; + const char *emoji; +} emoji_t; +// emoji_t array are expected to be NULL terminated + +static emoji_t EmojiTable[] = { + {":grinning:", "😀"}, + {":smiley:", "😃"}, + {":smile:", "😄"}, + {":grin:", "😁"}, + {":laughing:", "😆"}, + {":satisfied:", "😆"}, + {":sweat_smile:", "😅"}, + {":rofl:", "🤣"}, + {":joy:", "😂"}, + {":slightly_smiling_face:", "🙂"}, + {":upside_down_face:", "🙃"}, + {":wink:", "😉"}, + {":blush:", "😊"}, + {":innocent:", "😇"}, + {":smiling_face_with_three_hearts:", "🥰"}, + {":heart_eyes:", "😍"}, + {":star_struck:", "🤩"}, + {":kissing_heart:", "😘"}, + {":kissing:", "😗"}, + {":relaxed:", "☺️"}, + {":kissing_closed_eyes:", "😚"}, + {":kissing_smiling_eyes:", "😙"}, + {":smiling_face_with_tear:", "🥲"}, + {":yum:", "😋"}, + {":stuck_out_tongue:", "😛"}, + {":stuck_out_tongue_winking_eye:", "😜"}, + {":zany_face:", "🤪"}, + {":stuck_out_tongue_closed_eyes:", "😝"}, + {":money_mouth_face:", "🤑"}, + {":hugs:", "🤗"}, + {":hand_over_mouth:", "🤭"}, + {":shushing_face:", "🤫"}, + {":thinking:", "🤔"}, + {":zipper_mouth_face:", "🤐"}, + {":raised_eyebrow:", "🤨"}, + {":neutral_face:", "😐"}, + {":expressionless:", "😑"}, + {":no_mouth:", "😶"}, + {":smirk:", "😏"}, + {":unamused:", "😒"}, + {":roll_eyes:", "🙄"}, + {":grimacing:", "😬"}, + {":lying_face:", "🤥"}, + {":relieved:", "😌"}, + {":pensive:", "😔"}, + {":sleepy:", "😪"}, + {":drooling_face:", "🤤"}, + {":sleeping:", "😴"}, + {":mask:", "😷"}, + {":face_with_thermometer:", "🤒"}, + {":face_with_head_bandage:", "🤕"}, + {":nauseated_face:", "🤢"}, + {":vomiting_face:", "🤮"}, + {":sneezing_face:", "🤧"}, + {":hot_face:", "🥵"}, + {":cold_face:", "🥶"}, + {":woozy_face:", "🥴"}, + {":dizzy_face:", "😵"}, + {":exploding_head:", "🤯"}, + {":cowboy_hat_face:", "🤠"}, + {":partying_face:", "🥳"}, + {":disguised_face:", "🥸"}, + {":sunglasses:", "😎"}, + {":nerd_face:", "🤓"}, + {":monocle_face:", "🧐"}, + {":confused:", "😕"}, + {":worried:", "😟"}, + {":slightly_frowning_face:", "🙁"}, + {":frowning_face:", "☹️"}, + {":open_mouth:", "😮"}, + {":hushed:", "😯"}, + {":astonished:", "😲"}, + {":flushed:", "😳"}, + {":pleading_face:", "🥺"}, + {":frowning:", "😦"}, + {":anguished:", "😧"}, + {":fearful:", "😨"}, + {":cold_sweat:", "😰"}, + {":disappointed_relieved:", "😥"}, + {":cry:", "😢"}, + {":sob:", "😭"}, + {":scream:", "😱"}, + {":confounded:", "😖"}, + {":persevere:", "😣"}, + {":disappointed:", "😞"}, + {":sweat:", "😓"}, + {":weary:", "😩"}, + {":tired_face:", "😫"}, + {":yawning_face:", "🥱"}, + {":triumph:", "😤"}, + {":rage:", "😡"}, + {":pout:", "😡"}, + {":angry:", "😠"}, + {":cursing_face:", "🤬"}, + {":smiling_imp:", "😈"}, + {":imp:", "👿"}, + {":skull:", "💀"}, + {":skull_and_crossbones:", "☠️"}, + {":hankey:", "💩"}, + {":poop:", "💩"}, + {":shit:", "💩"}, + {":clown_face:", "🤡"}, + {":japanese_ogre:", "👹"}, + {":japanese_goblin:", "👺"}, + {":ghost:", "👻"}, + {":alien:", "👽"}, + {":space_invader:", "👾"}, + {":robot:", "🤖"}, + {":smiley_cat:", "😺"}, + {":smile_cat:", "😸"}, + {":joy_cat:", "😹"}, + {":heart_eyes_cat:", "😻"}, + {":smirk_cat:", "😼"}, + {":kissing_cat:", "😽"}, + {":scream_cat:", "🙀"}, + {":crying_cat_face:", "😿"}, + {":pouting_cat:", "😾"}, + {":see_no_evil:", "🙈"}, + {":hear_no_evil:", "🙉"}, + {":speak_no_evil:", "🙊"}, + {":kiss:", "💋"}, + {":love_letter:", "💌"}, + {":cupid:", "💘"}, + {":gift_heart:", "💝"}, + {":sparkling_heart:", "💖"}, + {":heartpulse:", "💗"}, + {":heartbeat:", "💓"}, + {":revolving_hearts:", "💞"}, + {":two_hearts:", "💕"}, + {":heart_decoration:", "💟"}, + {":heavy_heart_exclamation:", "❣️"}, + {":broken_heart:", "💔"}, + {":heart:", "❤️"}, + {":orange_heart:", "🧡"}, + {":yellow_heart:", "💛"}, + {":green_heart:", "💚"}, + {":blue_heart:", "💙"}, + {":purple_heart:", "💜"}, + {":brown_heart:", "🤎"}, + {":black_heart:", "🖤"}, + {":white_heart:", "🤍"}, + {":100:", "💯"}, + {":anger:", "💢"}, + {":boom:", "💥"}, + {":collision:", "💥"}, + {":dizzy:", "💫"}, + {":sweat_drops:", "💦"}, + {":dash:", "💨"}, + {":hole:", "🕳️"}, + {":bomb:", "💣"}, + {":speech_balloon:", "💬"}, + {":eye_speech_bubble:", "👁️‍🗨️"}, + {":left_speech_bubble:", "🗨️"}, + {":right_anger_bubble:", "🗯️"}, + {":thought_balloon:", "💭"}, + {":zzz:", "💤"}, + {":wave:", "👋"}, + {":raised_back_of_hand:", "🤚"}, + {":raised_hand_with_fingers_splayed:", "🖐️"}, + {":hand:", "✋"}, + {":raised_hand:", "✋"}, + {":vulcan_salute:", "🖖"}, + {":ok_hand:", "👌"}, + {":pinched_fingers:", "🤌"}, + {":pinching_hand:", "🤏"}, + {":v:", "✌️"}, + {":crossed_fingers:", "🤞"}, + {":love_you_gesture:", "🤟"}, + {":metal:", "🤘"}, + {":call_me_hand:", "🤙"}, + {":point_left:", "👈"}, + {":point_right:", "👉"}, + {":point_up_2:", "👆"}, + {":middle_finger:", "🖕"}, + {":fu:", "🖕"}, + {":point_down:", "👇"}, + {":point_up:", "☝️"}, + {":+1:", "👍"}, + {":thumbsup:", "👍"}, + {":-1:", "👎"}, + {":thumbsdown:", "👎"}, + {":fist_raised:", "✊"}, + {":fist:", "✊"}, + {":fist_oncoming:", "👊"}, + {":facepunch:", "👊"}, + {":punch:", "👊"}, + {":fist_left:", "🤛"}, + {":fist_right:", "🤜"}, + {":clap:", "👏"}, + {":raised_hands:", "🙌"}, + {":open_hands:", "👐"}, + {":palms_up_together:", "🤲"}, + {":handshake:", "🤝"}, + {":pray:", "🙏"}, + {":writing_hand:", "✍️"}, + {":nail_care:", "💅"}, + {":selfie:", "🤳"}, + {":muscle:", "💪"}, + {":mechanical_arm:", "🦾"}, + {":mechanical_leg:", "🦿"}, + {":leg:", "🦵"}, + {":foot:", "🦶"}, + {":ear:", "👂"}, + {":ear_with_hearing_aid:", "🦻"}, + {":nose:", "👃"}, + {":brain:", "🧠"}, + {":anatomical_heart:", "🫀"}, + {":lungs:", "🫁"}, + {":tooth:", "🦷"}, + {":bone:", "🦴"}, + {":eyes:", "👀"}, + {":eye:", "👁️"}, + {":tongue:", "👅"}, + {":lips:", "👄"}, + {":baby:", "👶"}, + {":child:", "🧒"}, + {":boy:", "👦"}, + {":girl:", "👧"}, + {":adult:", "🧑"}, + {":blond_haired_person:", "👱"}, + {":man:", "👨"}, + {":bearded_person:", "🧔"}, + {":red_haired_man:", "👨‍🦰"}, + {":curly_haired_man:", "👨‍🦱"}, + {":white_haired_man:", "👨‍🦳"}, + {":bald_man:", "👨‍🦲"}, + {":woman:", "👩"}, + {":red_haired_woman:", "👩‍🦰"}, + {":person_red_hair:", "🧑‍🦰"}, + {":curly_haired_woman:", "👩‍🦱"}, + {":person_curly_hair:", "🧑‍🦱"}, + {":white_haired_woman:", "👩‍🦳"}, + {":person_white_hair:", "🧑‍🦳"}, + {":bald_woman:", "👩‍🦲"}, + {":person_bald:", "🧑‍🦲"}, + {":blond_haired_woman:", "👱‍♀️"}, + {":blonde_woman:", "👱‍♀️"}, + {":blond_haired_man:", "👱‍♂️"}, + {":older_adult:", "🧓"}, + {":older_man:", "👴"}, + {":older_woman:", "👵"}, + {":frowning_person:", "🙍"}, + {":frowning_man:", "🙍‍♂️"}, + {":frowning_woman:", "🙍‍♀️"}, + {":pouting_face:", "🙎"}, + {":pouting_man:", "🙎‍♂️"}, + {":pouting_woman:", "🙎‍♀️"}, + {":no_good:", "🙅"}, + {":no_good_man:", "🙅‍♂️"}, + {":ng_man:", "🙅‍♂️"}, + {":no_good_woman:", "🙅‍♀️"}, + {":ng_woman:", "🙅‍♀️"}, + {":ok_person:", "🙆"}, + {":ok_man:", "🙆‍♂️"}, + {":ok_woman:", "🙆‍♀️"}, + {":tipping_hand_person:", "💁"}, + {":information_desk_person:", "💁"}, + {":tipping_hand_man:", "💁‍♂️"}, + {":sassy_man:", "💁‍♂️"}, + {":tipping_hand_woman:", "💁‍♀️"}, + {":sassy_woman:", "💁‍♀️"}, + {":raising_hand:", "🙋"}, + {":raising_hand_man:", "🙋‍♂️"}, + {":raising_hand_woman:", "🙋‍♀️"}, + {":deaf_person:", "🧏"}, + {":deaf_man:", "🧏‍♂️"}, + {":deaf_woman:", "🧏‍♀️"}, + {":bow:", "🙇"}, + {":bowing_man:", "🙇‍♂️"}, + {":bowing_woman:", "🙇‍♀️"}, + {":facepalm:", "🤦"}, + {":man_facepalming:", "🤦‍♂️"}, + {":woman_facepalming:", "🤦‍♀️"}, + {":shrug:", "🤷"}, + {":man_shrugging:", "🤷‍♂️"}, + {":woman_shrugging:", "🤷‍♀️"}, + {":health_worker:", "🧑‍⚕️"}, + {":man_health_worker:", "👨‍⚕️"}, + {":woman_health_worker:", "👩‍⚕️"}, + {":student:", "🧑‍🎓"}, + {":man_student:", "👨‍🎓"}, + {":woman_student:", "👩‍🎓"}, + {":teacher:", "🧑‍🏫"}, + {":man_teacher:", "👨‍🏫"}, + {":woman_teacher:", "👩‍🏫"}, + {":judge:", "🧑‍⚖️"}, + {":man_judge:", "👨‍⚖️"}, + {":woman_judge:", "👩‍⚖️"}, + {":farmer:", "🧑‍🌾"}, + {":man_farmer:", "👨‍🌾"}, + {":woman_farmer:", "👩‍🌾"}, + {":cook:", "🧑‍🍳"}, + {":man_cook:", "👨‍🍳"}, + {":woman_cook:", "👩‍🍳"}, + {":mechanic:", "🧑‍🔧"}, + {":man_mechanic:", "👨‍🔧"}, + {":woman_mechanic:", "👩‍🔧"}, + {":factory_worker:", "🧑‍🏭"}, + {":man_factory_worker:", "👨‍🏭"}, + {":woman_factory_worker:", "👩‍🏭"}, + {":office_worker:", "🧑‍💼"}, + {":man_office_worker:", "👨‍💼"}, + {":woman_office_worker:", "👩‍💼"}, + {":scientist:", "🧑‍🔬"}, + {":man_scientist:", "👨‍🔬"}, + {":woman_scientist:", "👩‍🔬"}, + {":technologist:", "🧑‍💻"}, + {":man_technologist:", "👨‍💻"}, + {":woman_technologist:", "👩‍💻"}, + {":singer:", "🧑‍🎤"}, + {":man_singer:", "👨‍🎤"}, + {":woman_singer:", "👩‍🎤"}, + {":artist:", "🧑‍🎨"}, + {":man_artist:", "👨‍🎨"}, + {":woman_artist:", "👩‍🎨"}, + {":pilot:", "🧑‍✈️"}, + {":man_pilot:", "👨‍✈️"}, + {":woman_pilot:", "👩‍✈️"}, + {":astronaut:", "🧑‍🚀"}, + {":man_astronaut:", "👨‍🚀"}, + {":woman_astronaut:", "👩‍🚀"}, + {":firefighter:", "🧑‍🚒"}, + {":man_firefighter:", "👨‍🚒"}, + {":woman_firefighter:", "👩‍🚒"}, + {":police_officer:", "👮"}, + {":cop:", "👮"}, + {":policeman:", "👮‍♂️"}, + {":policewoman:", "👮‍♀️"}, + {":detective:", "🕵️"}, + {":male_detective:", "🕵️‍♂️"}, + {":female_detective:", "🕵️‍♀️"}, + {":guard:", "💂"}, + {":guardsman:", "💂‍♂️"}, + {":guardswoman:", "💂‍♀️"}, + {":ninja:", "🥷"}, + {":construction_worker:", "👷"}, + {":construction_worker_man:", "👷‍♂️"}, + {":construction_worker_woman:", "👷‍♀️"}, + {":prince:", "🤴"}, + {":princess:", "👸"}, + {":person_with_turban:", "👳"}, + {":man_with_turban:", "👳‍♂️"}, + {":woman_with_turban:", "👳‍♀️"}, + {":man_with_gua_pi_mao:", "👲"}, + {":woman_with_headscarf:", "🧕"}, + {":person_in_tuxedo:", "🤵"}, + {":man_in_tuxedo:", "🤵‍♂️"}, + {":woman_in_tuxedo:", "🤵‍♀️"}, + {":person_with_veil:", "👰"}, + {":man_with_veil:", "👰‍♂️"}, + {":woman_with_veil:", "👰‍♀️"}, + {":bride_with_veil:", "👰‍♀️"}, + {":pregnant_woman:", "🤰"}, + {":breast_feeding:", "🤱"}, + {":woman_feeding_baby:", "👩‍🍼"}, + {":man_feeding_baby:", "👨‍🍼"}, + {":person_feeding_baby:", "🧑‍🍼"}, + {":angel:", "👼"}, + {":santa:", "🎅"}, + {":mrs_claus:", "🤶"}, + {":mx_claus:", "🧑‍🎄"}, + {":superhero:", "🦸"}, + {":superhero_man:", "🦸‍♂️"}, + {":superhero_woman:", "🦸‍♀️"}, + {":supervillain:", "🦹"}, + {":supervillain_man:", "🦹‍♂️"}, + {":supervillain_woman:", "🦹‍♀️"}, + {":mage:", "🧙"}, + {":mage_man:", "🧙‍♂️"}, + {":mage_woman:", "🧙‍♀️"}, + {":fairy:", "🧚"}, + {":fairy_man:", "🧚‍♂️"}, + {":fairy_woman:", "🧚‍♀️"}, + {":vampire:", "🧛"}, + {":vampire_man:", "🧛‍♂️"}, + {":vampire_woman:", "🧛‍♀️"}, + {":merperson:", "🧜"}, + {":merman:", "🧜‍♂️"}, + {":mermaid:", "🧜‍♀️"}, + {":elf:", "🧝"}, + {":elf_man:", "🧝‍♂️"}, + {":elf_woman:", "🧝‍♀️"}, + {":genie:", "🧞"}, + {":genie_man:", "🧞‍♂️"}, + {":genie_woman:", "🧞‍♀️"}, + {":zombie:", "🧟"}, + {":zombie_man:", "🧟‍♂️"}, + {":zombie_woman:", "🧟‍♀️"}, + {":massage:", "💆"}, + {":massage_man:", "💆‍♂️"}, + {":massage_woman:", "💆‍♀️"}, + {":haircut:", "💇"}, + {":haircut_man:", "💇‍♂️"}, + {":haircut_woman:", "💇‍♀️"}, + {":walking:", "🚶"}, + {":walking_man:", "🚶‍♂️"}, + {":walking_woman:", "🚶‍♀️"}, + {":standing_person:", "🧍"}, + {":standing_man:", "🧍‍♂️"}, + {":standing_woman:", "🧍‍♀️"}, + {":kneeling_person:", "🧎"}, + {":kneeling_man:", "🧎‍♂️"}, + {":kneeling_woman:", "🧎‍♀️"}, + {":person_with_probing_cane:", "🧑‍🦯"}, + {":man_with_probing_cane:", "👨‍🦯"}, + {":woman_with_probing_cane:", "👩‍🦯"}, + {":person_in_motorized_wheelchair:", "🧑‍🦼"}, + {":man_in_motorized_wheelchair:", "👨‍🦼"}, + {":woman_in_motorized_wheelchair:", "👩‍🦼"}, + {":person_in_manual_wheelchair:", "🧑‍🦽"}, + {":man_in_manual_wheelchair:", "👨‍🦽"}, + {":woman_in_manual_wheelchair:", "👩‍🦽"}, + {":runner:", "🏃"}, + {":running:", "🏃"}, + {":running_man:", "🏃‍♂️"}, + {":running_woman:", "🏃‍♀️"}, + {":woman_dancing:", "💃"}, + {":dancer:", "💃"}, + {":man_dancing:", "🕺"}, + {":business_suit_levitating:", "🕴️"}, + {":dancers:", "👯"}, + {":dancing_men:", "👯‍♂️"}, + {":dancing_women:", "👯‍♀️"}, + {":sauna_person:", "🧖"}, + {":sauna_man:", "🧖‍♂️"}, + {":sauna_woman:", "🧖‍♀️"}, + {":climbing:", "🧗"}, + {":climbing_man:", "🧗‍♂️"}, + {":climbing_woman:", "🧗‍♀️"}, + {":person_fencing:", "🤺"}, + {":horse_racing:", "🏇"}, + {":skier:", "⛷️"}, + {":snowboarder:", "🏂"}, + {":golfing:", "🏌️"}, + {":golfing_man:", "🏌️‍♂️"}, + {":golfing_woman:", "🏌️‍♀️"}, + {":surfer:", "🏄"}, + {":surfing_man:", "🏄‍♂️"}, + {":surfing_woman:", "🏄‍♀️"}, + {":rowboat:", "🚣"}, + {":rowing_man:", "🚣‍♂️"}, + {":rowing_woman:", "🚣‍♀️"}, + {":swimmer:", "🏊"}, + {":swimming_man:", "🏊‍♂️"}, + {":swimming_woman:", "🏊‍♀️"}, + {":bouncing_ball_person:", "⛹️"}, + {":bouncing_ball_man:", "⛹️‍♂️"}, + {":basketball_man:", "⛹️‍♂️"}, + {":bouncing_ball_woman:", "⛹️‍♀️"}, + {":basketball_woman:", "⛹️‍♀️"}, + {":weight_lifting:", "🏋️"}, + {":weight_lifting_man:", "🏋️‍♂️"}, + {":weight_lifting_woman:", "🏋️‍♀️"}, + {":bicyclist:", "🚴"}, + {":biking_man:", "🚴‍♂️"}, + {":biking_woman:", "🚴‍♀️"}, + {":mountain_bicyclist:", "🚵"}, + {":mountain_biking_man:", "🚵‍♂️"}, + {":mountain_biking_woman:", "🚵‍♀️"}, + {":cartwheeling:", "🤸"}, + {":man_cartwheeling:", "🤸‍♂️"}, + {":woman_cartwheeling:", "🤸‍♀️"}, + {":wrestling:", "🤼"}, + {":men_wrestling:", "🤼‍♂️"}, + {":women_wrestling:", "🤼‍♀️"}, + {":water_polo:", "🤽"}, + {":man_playing_water_polo:", "🤽‍♂️"}, + {":woman_playing_water_polo:", "🤽‍♀️"}, + {":handball_person:", "🤾"}, + {":man_playing_handball:", "🤾‍♂️"}, + {":woman_playing_handball:", "🤾‍♀️"}, + {":juggling_person:", "🤹"}, + {":man_juggling:", "🤹‍♂️"}, + {":woman_juggling:", "🤹‍♀️"}, + {":lotus_position:", "🧘"}, + {":lotus_position_man:", "🧘‍♂️"}, + {":lotus_position_woman:", "🧘‍♀️"}, + {":bath:", "🛀"}, + {":sleeping_bed:", "🛌"}, + {":people_holding_hands:", "🧑‍🤝‍🧑"}, + {":two_women_holding_hands:", "👭"}, + {":couple:", "👫"}, + {":two_men_holding_hands:", "👬"}, + {":couplekiss:", "💏"}, + {":couplekiss_man_woman:", "👩‍❤️‍💋‍👨"}, + {":couplekiss_man_man:", "👨‍❤️‍💋‍👨"}, + {":couplekiss_woman_woman:", "👩‍❤️‍💋‍👩"}, + {":couple_with_heart:", "💑"}, + {":couple_with_heart_woman_man:", "👩‍❤️‍👨"}, + {":couple_with_heart_man_man:", "👨‍❤️‍👨"}, + {":couple_with_heart_woman_woman:", "👩‍❤️‍👩"}, + {":family:", "👪"}, + {":family_man_woman_boy:", "👨‍👩‍👦"}, + {":family_man_woman_girl:", "👨‍👩‍👧"}, + {":family_man_woman_girl_boy:", "👨‍👩‍👧‍👦"}, + {":family_man_woman_boy_boy:", "👨‍👩‍👦‍👦"}, + {":family_man_woman_girl_girl:", "👨‍👩‍👧‍👧"}, + {":family_man_man_boy:", "👨‍👨‍👦"}, + {":family_man_man_girl:", "👨‍👨‍👧"}, + {":family_man_man_girl_boy:", "👨‍👨‍👧‍👦"}, + {":family_man_man_boy_boy:", "👨‍👨‍👦‍👦"}, + {":family_man_man_girl_girl:", "👨‍👨‍👧‍👧"}, + {":family_woman_woman_boy:", "👩‍👩‍👦"}, + {":family_woman_woman_girl:", "👩‍👩‍👧"}, + {":family_woman_woman_girl_boy:", "👩‍👩‍👧‍👦"}, + {":family_woman_woman_boy_boy:", "👩‍👩‍👦‍👦"}, + {":family_woman_woman_girl_girl:", "👩‍👩‍👧‍👧"}, + {":family_man_boy:", "👨‍👦"}, + {":family_man_boy_boy:", "👨‍👦‍👦"}, + {":family_man_girl:", "👨‍👧"}, + {":family_man_girl_boy:", "👨‍👧‍👦"}, + {":family_man_girl_girl:", "👨‍👧‍👧"}, + {":family_woman_boy:", "👩‍👦"}, + {":family_woman_boy_boy:", "👩‍👦‍👦"}, + {":family_woman_girl:", "👩‍👧"}, + {":family_woman_girl_boy:", "👩‍👧‍👦"}, + {":family_woman_girl_girl:", "👩‍👧‍👧"}, + {":speaking_head:", "🗣️"}, + {":bust_in_silhouette:", "👤"}, + {":busts_in_silhouette:", "👥"}, + {":people_hugging:", "🫂"}, + {":footprints:", "👣"}, + {":monkey_face:", "🐵"}, + {":monkey:", "🐒"}, + {":gorilla:", "🦍"}, + {":orangutan:", "🦧"}, + {":dog:", "🐶"}, + {":dog2:", "🐕"}, + {":guide_dog:", "🦮"}, + {":service_dog:", "🐕‍🦺"}, + {":poodle:", "🐩"}, + {":wolf:", "🐺"}, + {":fox_face:", "🦊"}, + {":raccoon:", "🦝"}, + {":cat:", "🐱"}, + {":cat2:", "🐈"}, + {":black_cat:", "🐈‍⬛"}, + {":lion:", "🦁"}, + {":tiger:", "🐯"}, + {":tiger2:", "🐅"}, + {":leopard:", "🐆"}, + {":horse:", "🐴"}, + {":racehorse:", "🐎"}, + {":unicorn:", "🦄"}, + {":zebra:", "🦓"}, + {":deer:", "🦌"}, + {":bison:", "🦬"}, + {":cow:", "🐮"}, + {":ox:", "🐂"}, + {":water_buffalo:", "🐃"}, + {":cow2:", "🐄"}, + {":pig:", "🐷"}, + {":pig2:", "🐖"}, + {":boar:", "🐗"}, + {":pig_nose:", "🐽"}, + {":ram:", "🐏"}, + {":sheep:", "🐑"}, + {":goat:", "🐐"}, + {":dromedary_camel:", "🐪"}, + {":camel:", "🐫"}, + {":llama:", "🦙"}, + {":giraffe:", "🦒"}, + {":elephant:", "🐘"}, + {":mammoth:", "🦣"}, + {":rhinoceros:", "🦏"}, + {":hippopotamus:", "🦛"}, + {":mouse:", "🐭"}, + {":mouse2:", "🐁"}, + {":rat:", "🐀"}, + {":hamster:", "🐹"}, + {":rabbit:", "🐰"}, + {":rabbit2:", "🐇"}, + {":chipmunk:", "🐿️"}, + {":beaver:", "🦫"}, + {":hedgehog:", "🦔"}, + {":bat:", "🦇"}, + {":bear:", "🐻"}, + {":polar_bear:", "🐻‍❄️"}, + {":koala:", "🐨"}, + {":panda_face:", "🐼"}, + {":sloth:", "🦥"}, + {":otter:", "🦦"}, + {":skunk:", "🦨"}, + {":kangaroo:", "🦘"}, + {":badger:", "🦡"}, + {":feet:", "🐾"}, + {":paw_prints:", "🐾"}, + {":turkey:", "🦃"}, + {":chicken:", "🐔"}, + {":rooster:", "🐓"}, + {":hatching_chick:", "🐣"}, + {":baby_chick:", "🐤"}, + {":hatched_chick:", "🐥"}, + {":bird:", "🐦"}, + {":penguin:", "🐧"}, + {":dove:", "🕊️"}, + {":eagle:", "🦅"}, + {":duck:", "🦆"}, + {":swan:", "🦢"}, + {":owl:", "🦉"}, + {":dodo:", "🦤"}, + {":feather:", "🪶"}, + {":flamingo:", "🦩"}, + {":peacock:", "🦚"}, + {":parrot:", "🦜"}, + {":frog:", "🐸"}, + {":crocodile:", "🐊"}, + {":turtle:", "🐢"}, + {":lizard:", "🦎"}, + {":snake:", "🐍"}, + {":dragon_face:", "🐲"}, + {":dragon:", "🐉"}, + {":sauropod:", "🦕"}, + {":t-rex:", "🦖"}, + {":whale:", "🐳"}, + {":whale2:", "🐋"}, + {":dolphin:", "🐬"}, + {":flipper:", "🐬"}, + {":seal:", "🦭"}, + {":fish:", "🐟"}, + {":tropical_fish:", "🐠"}, + {":blowfish:", "🐡"}, + {":shark:", "🦈"}, + {":octopus:", "🐙"}, + {":shell:", "🐚"}, + {":snail:", "🐌"}, + {":butterfly:", "🦋"}, + {":bug:", "🐛"}, + {":ant:", "🐜"}, + {":bee:", "🐝"}, + {":honeybee:", "🐝"}, + {":beetle:", "🪲"}, + {":lady_beetle:", "🐞"}, + {":cricket:", "🦗"}, + {":cockroach:", "🪳"}, + {":spider:", "🕷️"}, + {":spider_web:", "🕸️"}, + {":scorpion:", "🦂"}, + {":mosquito:", "🦟"}, + {":fly:", "🪰"}, + {":worm:", "🪱"}, + {":microbe:", "🦠"}, + {":bouquet:", "💐"}, + {":cherry_blossom:", "🌸"}, + {":white_flower:", "💮"}, + {":rosette:", "🏵️"}, + {":rose:", "🌹"}, + {":wilted_flower:", "🥀"}, + {":hibiscus:", "🌺"}, + {":sunflower:", "🌻"}, + {":blossom:", "🌼"}, + {":tulip:", "🌷"}, + {":seedling:", "🌱"}, + {":potted_plant:", "🪴"}, + {":evergreen_tree:", "🌲"}, + {":deciduous_tree:", "🌳"}, + {":palm_tree:", "🌴"}, + {":cactus:", "🌵"}, + {":ear_of_rice:", "🌾"}, + {":herb:", "🌿"}, + {":shamrock:", "☘️"}, + {":four_leaf_clover:", "🍀"}, + {":maple_leaf:", "🍁"}, + {":fallen_leaf:", "🍂"}, + {":leaves:", "🍃"}, + {":grapes:", "🍇"}, + {":melon:", "🍈"}, + {":watermelon:", "🍉"}, + {":tangerine:", "🍊"}, + {":orange:", "🍊"}, + {":mandarin:", "🍊"}, + {":lemon:", "🍋"}, + {":banana:", "🍌"}, + {":pineapple:", "🍍"}, + {":mango:", "🥭"}, + {":apple:", "🍎"}, + {":green_apple:", "🍏"}, + {":pear:", "🍐"}, + {":peach:", "🍑"}, + {":cherries:", "🍒"}, + {":strawberry:", "🍓"}, + {":blueberries:", "🫐"}, + {":kiwi_fruit:", "🥝"}, + {":tomato:", "🍅"}, + {":olive:", "🫒"}, + {":coconut:", "🥥"}, + {":avocado:", "🥑"}, + {":eggplant:", "🍆"}, + {":potato:", "🥔"}, + {":carrot:", "🥕"}, + {":corn:", "🌽"}, + {":hot_pepper:", "🌶️"}, + {":bell_pepper:", "🫑"}, + {":cucumber:", "🥒"}, + {":leafy_green:", "🥬"}, + {":broccoli:", "🥦"}, + {":garlic:", "🧄"}, + {":onion:", "🧅"}, + {":mushroom:", "🍄"}, + {":peanuts:", "🥜"}, + {":chestnut:", "🌰"}, + {":bread:", "🍞"}, + {":croissant:", "🥐"}, + {":baguette_bread:", "🥖"}, + {":flatbread:", "🫓"}, + {":pretzel:", "🥨"}, + {":bagel:", "🥯"}, + {":pancakes:", "🥞"}, + {":waffle:", "🧇"}, + {":cheese:", "🧀"}, + {":meat_on_bone:", "🍖"}, + {":poultry_leg:", "🍗"}, + {":cut_of_meat:", "🥩"}, + {":bacon:", "🥓"}, + {":hamburger:", "🍔"}, + {":fries:", "🍟"}, + {":pizza:", "🍕"}, + {":hotdog:", "🌭"}, + {":sandwich:", "🥪"}, + {":taco:", "🌮"}, + {":burrito:", "🌯"}, + {":tamale:", "🫔"}, + {":stuffed_flatbread:", "🥙"}, + {":falafel:", "🧆"}, + {":egg:", "🥚"}, + {":fried_egg:", "🍳"}, + {":shallow_pan_of_food:", "🥘"}, + {":stew:", "🍲"}, + {":fondue:", "🫕"}, + {":bowl_with_spoon:", "🥣"}, + {":green_salad:", "🥗"}, + {":popcorn:", "🍿"}, + {":butter:", "🧈"}, + {":salt:", "🧂"}, + {":canned_food:", "🥫"}, + {":bento:", "🍱"}, + {":rice_cracker:", "🍘"}, + {":rice_ball:", "🍙"}, + {":rice:", "🍚"}, + {":curry:", "🍛"}, + {":ramen:", "🍜"}, + {":spaghetti:", "🍝"}, + {":sweet_potato:", "🍠"}, + {":oden:", "🍢"}, + {":sushi:", "🍣"}, + {":fried_shrimp:", "🍤"}, + {":fish_cake:", "🍥"}, + {":moon_cake:", "🥮"}, + {":dango:", "🍡"}, + {":dumpling:", "🥟"}, + {":fortune_cookie:", "🥠"}, + {":takeout_box:", "🥡"}, + {":crab:", "🦀"}, + {":lobster:", "🦞"}, + {":shrimp:", "🦐"}, + {":squid:", "🦑"}, + {":oyster:", "🦪"}, + {":icecream:", "🍦"}, + {":shaved_ice:", "🍧"}, + {":ice_cream:", "🍨"}, + {":doughnut:", "🍩"}, + {":cookie:", "🍪"}, + {":birthday:", "🎂"}, + {":cake:", "🍰"}, + {":cupcake:", "🧁"}, + {":pie:", "🥧"}, + {":chocolate_bar:", "🍫"}, + {":candy:", "🍬"}, + {":lollipop:", "🍭"}, + {":custard:", "🍮"}, + {":honey_pot:", "🍯"}, + {":baby_bottle:", "🍼"}, + {":milk_glass:", "🥛"}, + {":coffee:", "☕"}, + {":teapot:", "🫖"}, + {":tea:", "🍵"}, + {":sake:", "🍶"}, + {":champagne:", "🍾"}, + {":wine_glass:", "🍷"}, + {":cocktail:", "🍸"}, + {":tropical_drink:", "🍹"}, + {":beer:", "🍺"}, + {":beers:", "🍻"}, + {":clinking_glasses:", "🥂"}, + {":tumbler_glass:", "🥃"}, + {":cup_with_straw:", "🥤"}, + {":bubble_tea:", "🧋"}, + {":beverage_box:", "🧃"}, + {":mate:", "🧉"}, + {":ice_cube:", "🧊"}, + {":chopsticks:", "🥢"}, + {":plate_with_cutlery:", "🍽️"}, + {":fork_and_knife:", "🍴"}, + {":spoon:", "🥄"}, + {":hocho:", "🔪"}, + {":knife:", "🔪"}, + {":amphora:", "🏺"}, + {":earth_africa:", "🌍"}, + {":earth_americas:", "🌎"}, + {":earth_asia:", "🌏"}, + {":globe_with_meridians:", "🌐"}, + {":world_map:", "🗺️"}, + {":japan:", "🗾"}, + {":compass:", "🧭"}, + {":mountain_snow:", "🏔️"}, + {":mountain:", "⛰️"}, + {":volcano:", "🌋"}, + {":mount_fuji:", "🗻"}, + {":camping:", "🏕️"}, + {":beach_umbrella:", "🏖️"}, + {":desert:", "🏜️"}, + {":desert_island:", "🏝️"}, + {":national_park:", "🏞️"}, + {":stadium:", "🏟️"}, + {":classical_building:", "🏛️"}, + {":building_construction:", "🏗️"}, + {":bricks:", "🧱"}, + {":rock:", "🪨"}, + {":wood:", "🪵"}, + {":hut:", "🛖"}, + {":houses:", "🏘️"}, + {":derelict_house:", "🏚️"}, + {":house:", "🏠"}, + {":house_with_garden:", "🏡"}, + {":office:", "🏢"}, + {":post_office:", "🏣"}, + {":european_post_office:", "🏤"}, + {":hospital:", "🏥"}, + {":bank:", "🏦"}, + {":hotel:", "🏨"}, + {":love_hotel:", "🏩"}, + {":convenience_store:", "🏪"}, + {":school:", "🏫"}, + {":department_store:", "🏬"}, + {":factory:", "🏭"}, + {":japanese_castle:", "🏯"}, + {":european_castle:", "🏰"}, + {":wedding:", "💒"}, + {":tokyo_tower:", "🗼"}, + {":statue_of_liberty:", "🗽"}, + {":church:", "⛪"}, + {":mosque:", "🕌"}, + {":hindu_temple:", "🛕"}, + {":synagogue:", "🕍"}, + {":shinto_shrine:", "⛩️"}, + {":kaaba:", "🕋"}, + {":fountain:", "⛲"}, + {":tent:", "⛺"}, + {":foggy:", "🌁"}, + {":night_with_stars:", "🌃"}, + {":cityscape:", "🏙️"}, + {":sunrise_over_mountains:", "🌄"}, + {":sunrise:", "🌅"}, + {":city_sunset:", "🌆"}, + {":city_sunrise:", "🌇"}, + {":bridge_at_night:", "🌉"}, + {":hotsprings:", "♨️"}, + {":carousel_horse:", "🎠"}, + {":ferris_wheel:", "🎡"}, + {":roller_coaster:", "🎢"}, + {":barber:", "💈"}, + {":circus_tent:", "🎪"}, + {":steam_locomotive:", "🚂"}, + {":railway_car:", "🚃"}, + {":bullettrain_side:", "🚄"}, + {":bullettrain_front:", "🚅"}, + {":train2:", "🚆"}, + {":metro:", "🚇"}, + {":light_rail:", "🚈"}, + {":station:", "🚉"}, + {":tram:", "🚊"}, + {":monorail:", "🚝"}, + {":mountain_railway:", "🚞"}, + {":train:", "🚋"}, + {":bus:", "🚌"}, + {":oncoming_bus:", "🚍"}, + {":trolleybus:", "🚎"}, + {":minibus:", "🚐"}, + {":ambulance:", "🚑"}, + {":fire_engine:", "🚒"}, + {":police_car:", "🚓"}, + {":oncoming_police_car:", "🚔"}, + {":taxi:", "🚕"}, + {":oncoming_taxi:", "🚖"}, + {":car:", "🚗"}, + {":red_car:", "🚗"}, + {":oncoming_automobile:", "🚘"}, + {":blue_car:", "🚙"}, + {":pickup_truck:", "🛻"}, + {":truck:", "🚚"}, + {":articulated_lorry:", "🚛"}, + {":tractor:", "🚜"}, + {":racing_car:", "🏎️"}, + {":motorcycle:", "🏍️"}, + {":motor_scooter:", "🛵"}, + {":manual_wheelchair:", "🦽"}, + {":motorized_wheelchair:", "🦼"}, + {":auto_rickshaw:", "🛺"}, + {":bike:", "🚲"}, + {":kick_scooter:", "🛴"}, + {":skateboard:", "🛹"}, + {":roller_skate:", "🛼"}, + {":busstop:", "🚏"}, + {":motorway:", "🛣️"}, + {":railway_track:", "🛤️"}, + {":oil_drum:", "🛢️"}, + {":fuelpump:", "⛽"}, + {":rotating_light:", "🚨"}, + {":traffic_light:", "🚥"}, + {":vertical_traffic_light:", "🚦"}, + {":stop_sign:", "🛑"}, + {":construction:", "🚧"}, + {":anchor:", "⚓"}, + {":boat:", "⛵"}, + {":sailboat:", "⛵"}, + {":canoe:", "🛶"}, + {":speedboat:", "🚤"}, + {":passenger_ship:", "🛳️"}, + {":ferry:", "⛴️"}, + {":motor_boat:", "🛥️"}, + {":ship:", "🚢"}, + {":airplane:", "✈️"}, + {":small_airplane:", "🛩️"}, + {":flight_departure:", "🛫"}, + {":flight_arrival:", "🛬"}, + {":parachute:", "🪂"}, + {":seat:", "💺"}, + {":helicopter:", "🚁"}, + {":suspension_railway:", "🚟"}, + {":mountain_cableway:", "🚠"}, + {":aerial_tramway:", "🚡"}, + {":artificial_satellite:", "🛰️"}, + {":rocket:", "🚀"}, + {":flying_saucer:", "🛸"}, + {":bellhop_bell:", "🛎️"}, + {":luggage:", "🧳"}, + {":hourglass:", "⌛"}, + {":hourglass_flowing_sand:", "⏳"}, + {":watch:", "⌚"}, + {":alarm_clock:", "⏰"}, + {":stopwatch:", "⏱️"}, + {":timer_clock:", "⏲️"}, + {":mantelpiece_clock:", "🕰️"}, + {":clock12:", "🕛"}, + {":clock1230:", "🕧"}, + {":clock1:", "🕐"}, + {":clock130:", "🕜"}, + {":clock2:", "🕑"}, + {":clock230:", "🕝"}, + {":clock3:", "🕒"}, + {":clock330:", "🕞"}, + {":clock4:", "🕓"}, + {":clock430:", "🕟"}, + {":clock5:", "🕔"}, + {":clock530:", "🕠"}, + {":clock6:", "🕕"}, + {":clock630:", "🕡"}, + {":clock7:", "🕖"}, + {":clock730:", "🕢"}, + {":clock8:", "🕗"}, + {":clock830:", "🕣"}, + {":clock9:", "🕘"}, + {":clock930:", "🕤"}, + {":clock10:", "🕙"}, + {":clock1030:", "🕥"}, + {":clock11:", "🕚"}, + {":clock1130:", "🕦"}, + {":new_moon:", "🌑"}, + {":waxing_crescent_moon:", "🌒"}, + {":first_quarter_moon:", "🌓"}, + {":moon:", "🌔"}, + {":waxing_gibbous_moon:", "🌔"}, + {":full_moon:", "🌕"}, + {":waning_gibbous_moon:", "🌖"}, + {":last_quarter_moon:", "🌗"}, + {":waning_crescent_moon:", "🌘"}, + {":crescent_moon:", "🌙"}, + {":new_moon_with_face:", "🌚"}, + {":first_quarter_moon_with_face:", "🌛"}, + {":last_quarter_moon_with_face:", "🌜"}, + {":thermometer:", "🌡️"}, + {":sunny:", "☀️"}, + {":full_moon_with_face:", "🌝"}, + {":sun_with_face:", "🌞"}, + {":ringed_planet:", "🪐"}, + {":star:", "⭐"}, + {":star2:", "🌟"}, + {":stars:", "🌠"}, + {":milky_way:", "🌌"}, + {":cloud:", "☁️"}, + {":partly_sunny:", "⛅"}, + {":cloud_with_lightning_and_rain:", "⛈️"}, + {":sun_behind_small_cloud:", "🌤️"}, + {":sun_behind_large_cloud:", "🌥️"}, + {":sun_behind_rain_cloud:", "🌦️"}, + {":cloud_with_rain:", "🌧️"}, + {":cloud_with_snow:", "🌨️"}, + {":cloud_with_lightning:", "🌩️"}, + {":tornado:", "🌪️"}, + {":fog:", "🌫️"}, + {":wind_face:", "🌬️"}, + {":cyclone:", "🌀"}, + {":rainbow:", "🌈"}, + {":closed_umbrella:", "🌂"}, + {":open_umbrella:", "☂️"}, + {":umbrella:", "☔"}, + {":parasol_on_ground:", "⛱️"}, + {":zap:", "⚡"}, + {":snowflake:", "❄️"}, + {":snowman_with_snow:", "☃️"}, + {":snowman:", "⛄"}, + {":comet:", "☄️"}, + {":fire:", "🔥"}, + {":droplet:", "💧"}, + {":ocean:", "🌊"}, + {":jack_o_lantern:", "🎃"}, + {":christmas_tree:", "🎄"}, + {":fireworks:", "🎆"}, + {":sparkler:", "🎇"}, + {":firecracker:", "🧨"}, + {":sparkles:", "✨"}, + {":balloon:", "🎈"}, + {":tada:", "🎉"}, + {":confetti_ball:", "🎊"}, + {":tanabata_tree:", "🎋"}, + {":bamboo:", "🎍"}, + {":dolls:", "🎎"}, + {":flags:", "🎏"}, + {":wind_chime:", "🎐"}, + {":rice_scene:", "🎑"}, + {":red_envelope:", "🧧"}, + {":ribbon:", "🎀"}, + {":gift:", "🎁"}, + {":reminder_ribbon:", "🎗️"}, + {":tickets:", "🎟️"}, + {":ticket:", "🎫"}, + {":medal_military:", "🎖️"}, + {":trophy:", "🏆"}, + {":medal_sports:", "🏅"}, + {":1st_place_medal:", "🥇"}, + {":2nd_place_medal:", "🥈"}, + {":3rd_place_medal:", "🥉"}, + {":soccer:", "⚽"}, + {":baseball:", "⚾"}, + {":softball:", "🥎"}, + {":basketball:", "🏀"}, + {":volleyball:", "🏐"}, + {":football:", "🏈"}, + {":rugby_football:", "🏉"}, + {":tennis:", "🎾"}, + {":flying_disc:", "🥏"}, + {":bowling:", "🎳"}, + {":cricket_game:", "🏏"}, + {":field_hockey:", "🏑"}, + {":ice_hockey:", "🏒"}, + {":lacrosse:", "🥍"}, + {":ping_pong:", "🏓"}, + {":badminton:", "🏸"}, + {":boxing_glove:", "🥊"}, + {":martial_arts_uniform:", "🥋"}, + {":goal_net:", "🥅"}, + {":golf:", "⛳"}, + {":ice_skate:", "⛸️"}, + {":fishing_pole_and_fish:", "🎣"}, + {":diving_mask:", "🤿"}, + {":running_shirt_with_sash:", "🎽"}, + {":ski:", "🎿"}, + {":sled:", "🛷"}, + {":curling_stone:", "🥌"}, + {":dart:", "🎯"}, + {":yo_yo:", "🪀"}, + {":kite:", "🪁"}, + {":8ball:", "🎱"}, + {":crystal_ball:", "🔮"}, + {":magic_wand:", "🪄"}, + {":nazar_amulet:", "🧿"}, + {":video_game:", "🎮"}, + {":joystick:", "🕹️"}, + {":slot_machine:", "🎰"}, + {":game_die:", "🎲"}, + {":jigsaw:", "🧩"}, + {":teddy_bear:", "🧸"}, + {":pi_ata:", "🪅"}, + {":nesting_dolls:", "🪆"}, + {":spades:", "♠️"}, + {":hearts:", "♥️"}, + {":diamonds:", "♦️"}, + {":clubs:", "♣️"}, + {":chess_pawn:", "♟️"}, + {":black_joker:", "🃏"}, + {":mahjong:", "🀄"}, + {":flower_playing_cards:", "🎴"}, + {":performing_arts:", "🎭"}, + {":framed_picture:", "🖼️"}, + {":art:", "🎨"}, + {":thread:", "🧵"}, + {":sewing_needle:", "🪡"}, + {":yarn:", "🧶"}, + {":knot:", "🪢"}, + {":eyeglasses:", "👓"}, + {":dark_sunglasses:", "🕶️"}, + {":goggles:", "🥽"}, + {":lab_coat:", "🥼"}, + {":safety_vest:", "🦺"}, + {":necktie:", "👔"}, + {":shirt:", "👕"}, + {":tshirt:", "👕"}, + {":jeans:", "👖"}, + {":scarf:", "🧣"}, + {":gloves:", "🧤"}, + {":coat:", "🧥"}, + {":socks:", "🧦"}, + {":dress:", "👗"}, + {":kimono:", "👘"}, + {":sari:", "🥻"}, + {":one_piece_swimsuit:", "🩱"}, + {":swim_brief:", "🩲"}, + {":shorts:", "🩳"}, + {":bikini:", "👙"}, + {":womans_clothes:", "👚"}, + {":purse:", "👛"}, + {":handbag:", "👜"}, + {":pouch:", "👝"}, + {":shopping:", "🛍️"}, + {":school_satchel:", "🎒"}, + {":thong_sandal:", "🩴"}, + {":mans_shoe:", "👞"}, + {":shoe:", "👞"}, + {":athletic_shoe:", "👟"}, + {":hiking_boot:", "🥾"}, + {":flat_shoe:", "🥿"}, + {":high_heel:", "👠"}, + {":sandal:", "👡"}, + {":ballet_shoes:", "🩰"}, + {":boot:", "👢"}, + {":crown:", "👑"}, + {":womans_hat:", "👒"}, + {":tophat:", "🎩"}, + {":mortar_board:", "🎓"}, + {":billed_cap:", "🧢"}, + {":military_helmet:", "🪖"}, + {":rescue_worker_helmet:", "⛑️"}, + {":prayer_beads:", "📿"}, + {":lipstick:", "💄"}, + {":ring:", "💍"}, + {":gem:", "💎"}, + {":mute:", "🔇"}, + {":speaker:", "🔈"}, + {":sound:", "🔉"}, + {":loud_sound:", "🔊"}, + {":loudspeaker:", "📢"}, + {":mega:", "📣"}, + {":postal_horn:", "📯"}, + {":bell:", "🔔"}, + {":no_bell:", "🔕"}, + {":musical_score:", "🎼"}, + {":musical_note:", "🎵"}, + {":notes:", "🎶"}, + {":studio_microphone:", "🎙️"}, + {":level_slider:", "🎚️"}, + {":control_knobs:", "🎛️"}, + {":microphone:", "🎤"}, + {":headphones:", "🎧"}, + {":radio:", "📻"}, + {":saxophone:", "🎷"}, + {":accordion:", "🪗"}, + {":guitar:", "🎸"}, + {":musical_keyboard:", "🎹"}, + {":trumpet:", "🎺"}, + {":violin:", "🎻"}, + {":banjo:", "🪕"}, + {":drum:", "🥁"}, + {":long_drum:", "🪘"}, + {":iphone:", "📱"}, + {":calling:", "📲"}, + {":phone:", "☎️"}, + {":telephone:", "☎️"}, + {":telephone_receiver:", "📞"}, + {":pager:", "📟"}, + {":fax:", "📠"}, + {":battery:", "🔋"}, + {":electric_plug:", "🔌"}, + {":computer:", "💻"}, + {":desktop_computer:", "🖥️"}, + {":printer:", "🖨️"}, + {":keyboard:", "⌨️"}, + {":computer_mouse:", "🖱️"}, + {":trackball:", "🖲️"}, + {":minidisc:", "💽"}, + {":floppy_disk:", "💾"}, + {":cd:", "💿"}, + {":dvd:", "📀"}, + {":abacus:", "🧮"}, + {":movie_camera:", "🎥"}, + {":film_strip:", "🎞️"}, + {":film_projector:", "📽️"}, + {":clapper:", "🎬"}, + {":tv:", "📺"}, + {":camera:", "📷"}, + {":camera_flash:", "📸"}, + {":video_camera:", "📹"}, + {":vhs:", "📼"}, + {":mag:", "🔍"}, + {":mag_right:", "🔎"}, + {":candle:", "🕯️"}, + {":bulb:", "💡"}, + {":flashlight:", "🔦"}, + {":izakaya_lantern:", "🏮"}, + {":lantern:", "🏮"}, + {":diya_lamp:", "🪔"}, + {":notebook_with_decorative_cover:", "📔"}, + {":closed_book:", "📕"}, + {":book:", "📖"}, + {":open_book:", "📖"}, + {":green_book:", "📗"}, + {":blue_book:", "📘"}, + {":orange_book:", "📙"}, + {":books:", "📚"}, + {":notebook:", "📓"}, + {":ledger:", "📒"}, + {":page_with_curl:", "📃"}, + {":scroll:", "📜"}, + {":page_facing_up:", "📄"}, + {":newspaper:", "📰"}, + {":newspaper_roll:", "🗞️"}, + {":bookmark_tabs:", "📑"}, + {":bookmark:", "🔖"}, + {":label:", "🏷️"}, + {":moneybag:", "💰"}, + {":coin:", "🪙"}, + {":yen:", "💴"}, + {":dollar:", "💵"}, + {":euro:", "💶"}, + {":pound:", "💷"}, + {":money_with_wings:", "💸"}, + {":credit_card:", "💳"}, + {":receipt:", "🧾"}, + {":chart:", "💹"}, + {":email:", "✉️"}, + {":envelope:", "✉️"}, + {":e-mail:", "📧"}, + {":incoming_envelope:", "📨"}, + {":envelope_with_arrow:", "📩"}, + {":outbox_tray:", "📤"}, + {":inbox_tray:", "📥"}, + {":package:", "📦"}, + {":mailbox:", "📫"}, + {":mailbox_closed:", "📪"}, + {":mailbox_with_mail:", "📬"}, + {":mailbox_with_no_mail:", "📭"}, + {":postbox:", "📮"}, + {":ballot_box:", "🗳️"}, + {":pencil2:", "✏️"}, + {":black_nib:", "✒️"}, + {":fountain_pen:", "🖋️"}, + {":pen:", "🖊️"}, + {":paintbrush:", "🖌️"}, + {":crayon:", "🖍️"}, + {":memo:", "📝"}, + {":pencil:", "📝"}, + {":briefcase:", "💼"}, + {":file_folder:", "📁"}, + {":open_file_folder:", "📂"}, + {":card_index_dividers:", "🗂️"}, + {":date:", "📅"}, + {":calendar:", "📆"}, + {":spiral_notepad:", "🗒️"}, + {":spiral_calendar:", "🗓️"}, + {":card_index:", "📇"}, + {":chart_with_upwards_trend:", "📈"}, + {":chart_with_downwards_trend:", "📉"}, + {":bar_chart:", "📊"}, + {":clipboard:", "📋"}, + {":pushpin:", "📌"}, + {":round_pushpin:", "📍"}, + {":paperclip:", "📎"}, + {":paperclips:", "🖇️"}, + {":straight_ruler:", "📏"}, + {":triangular_ruler:", "📐"}, + {":scissors:", "✂️"}, + {":card_file_box:", "🗃️"}, + {":file_cabinet:", "🗄️"}, + {":wastebasket:", "🗑️"}, + {":lock:", "🔒"}, + {":unlock:", "🔓"}, + {":lock_with_ink_pen:", "🔏"}, + {":closed_lock_with_key:", "🔐"}, + {":key:", "🔑"}, + {":old_key:", "🗝️"}, + {":hammer:", "🔨"}, + {":axe:", "🪓"}, + {":pick:", "⛏️"}, + {":hammer_and_pick:", "⚒️"}, + {":hammer_and_wrench:", "🛠️"}, + {":dagger:", "🗡️"}, + {":crossed_swords:", "⚔️"}, + {":gun:", "🔫"}, + {":boomerang:", "🪃"}, + {":bow_and_arrow:", "🏹"}, + {":shield:", "🛡️"}, + {":carpentry_saw:", "🪚"}, + {":wrench:", "🔧"}, + {":screwdriver:", "🪛"}, + {":nut_and_bolt:", "🔩"}, + {":gear:", "⚙️"}, + {":clamp:", "🗜️"}, + {":balance_scale:", "⚖️"}, + {":probing_cane:", "🦯"}, + {":link:", "🔗"}, + {":chains:", "⛓️"}, + {":hook:", "🪝"}, + {":toolbox:", "🧰"}, + {":magnet:", "🧲"}, + {":ladder:", "🪜"}, + {":alembic:", "⚗️"}, + {":test_tube:", "🧪"}, + {":petri_dish:", "🧫"}, + {":dna:", "🧬"}, + {":microscope:", "🔬"}, + {":telescope:", "🔭"}, + {":satellite:", "📡"}, + {":syringe:", "💉"}, + {":drop_of_blood:", "🩸"}, + {":pill:", "💊"}, + {":adhesive_bandage:", "🩹"}, + {":stethoscope:", "🩺"}, + {":door:", "🚪"}, + {":elevator:", "🛗"}, + {":mirror:", "🪞"}, + {":window:", "🪟"}, + {":bed:", "🛏️"}, + {":couch_and_lamp:", "🛋️"}, + {":chair:", "🪑"}, + {":toilet:", "🚽"}, + {":plunger:", "🪠"}, + {":shower:", "🚿"}, + {":bathtub:", "🛁"}, + {":mouse_trap:", "🪤"}, + {":razor:", "🪒"}, + {":lotion_bottle:", "🧴"}, + {":safety_pin:", "🧷"}, + {":broom:", "🧹"}, + {":basket:", "🧺"}, + {":roll_of_paper:", "🧻"}, + {":bucket:", "🪣"}, + {":soap:", "🧼"}, + {":toothbrush:", "🪥"}, + {":sponge:", "🧽"}, + {":fire_extinguisher:", "🧯"}, + {":shopping_cart:", "🛒"}, + {":smoking:", "🚬"}, + {":coffin:", "⚰️"}, + {":headstone:", "🪦"}, + {":funeral_urn:", "⚱️"}, + {":moyai:", "🗿"}, + {":placard:", "🪧"}, + {":atm:", "🏧"}, + {":put_litter_in_its_place:", "🚮"}, + {":potable_water:", "🚰"}, + {":wheelchair:", "♿"}, + {":mens:", "🚹"}, + {":womens:", "🚺"}, + {":restroom:", "🚻"}, + {":baby_symbol:", "🚼"}, + {":wc:", "🚾"}, + {":passport_control:", "🛂"}, + {":customs:", "🛃"}, + {":baggage_claim:", "🛄"}, + {":left_luggage:", "🛅"}, + {":warning:", "⚠️"}, + {":children_crossing:", "🚸"}, + {":no_entry:", "⛔"}, + {":no_entry_sign:", "🚫"}, + {":no_bicycles:", "🚳"}, + {":no_smoking:", "🚭"}, + {":do_not_litter:", "🚯"}, + {":non-potable_water:", "🚱"}, + {":no_pedestrians:", "🚷"}, + {":no_mobile_phones:", "📵"}, + {":underage:", "🔞"}, + {":radioactive:", "☢️"}, + {":biohazard:", "☣️"}, + {":arrow_up:", "⬆️"}, + {":arrow_upper_right:", "↗️"}, + {":arrow_right:", "➡️"}, + {":arrow_lower_right:", "↘️"}, + {":arrow_down:", "⬇️"}, + {":arrow_lower_left:", "↙️"}, + {":arrow_left:", "⬅️"}, + {":arrow_upper_left:", "↖️"}, + {":arrow_up_down:", "↕️"}, + {":left_right_arrow:", "↔️"}, + {":leftwards_arrow_with_hook:", "↩️"}, + {":arrow_right_hook:", "↪️"}, + {":arrow_heading_up:", "⤴️"}, + {":arrow_heading_down:", "⤵️"}, + {":arrows_clockwise:", "🔃"}, + {":arrows_counterclockwise:", "🔄"}, + {":back:", "🔙"}, + {":end:", "🔚"}, + {":on:", "🔛"}, + {":soon:", "🔜"}, + {":top:", "🔝"}, + {":place_of_worship:", "🛐"}, + {":atom_symbol:", "⚛️"}, + {":om:", "🕉️"}, + {":star_of_david:", "✡️"}, + {":wheel_of_dharma:", "☸️"}, + {":yin_yang:", "☯️"}, + {":latin_cross:", "✝️"}, + {":orthodox_cross:", "☦️"}, + {":star_and_crescent:", "☪️"}, + {":peace_symbol:", "☮️"}, + {":menorah:", "🕎"}, + {":six_pointed_star:", "🔯"}, + {":aries:", "♈"}, + {":taurus:", "♉"}, + {":gemini:", "♊"}, + {":cancer:", "♋"}, + {":leo:", "♌"}, + {":virgo:", "♍"}, + {":libra:", "♎"}, + {":scorpius:", "♏"}, + {":sagittarius:", "♐"}, + {":capricorn:", "♑"}, + {":aquarius:", "♒"}, + {":pisces:", "♓"}, + {":ophiuchus:", "⛎"}, + {":twisted_rightwards_arrows:", "🔀"}, + {":repeat:", "🔁"}, + {":repeat_one:", "🔂"}, + {":arrow_forward:", "▶️"}, + {":fast_forward:", "⏩"}, + {":next_track_button:", "⏭️"}, + {":play_or_pause_button:", "⏯️"}, + {":arrow_backward:", "◀️"}, + {":rewind:", "⏪"}, + {":previous_track_button:", "⏮️"}, + {":arrow_up_small:", "🔼"}, + {":arrow_double_up:", "⏫"}, + {":arrow_down_small:", "🔽"}, + {":arrow_double_down:", "⏬"}, + {":pause_button:", "⏸️"}, + {":stop_button:", "⏹️"}, + {":record_button:", "⏺️"}, + {":eject_button:", "⏏️"}, + {":cinema:", "🎦"}, + {":low_brightness:", "🔅"}, + {":high_brightness:", "🔆"}, + {":signal_strength:", "📶"}, + {":vibration_mode:", "📳"}, + {":mobile_phone_off:", "📴"}, + {":female_sign:", "♀️"}, + {":male_sign:", "♂️"}, + {":transgender_symbol:", "⚧️"}, + {":heavy_multiplication_x:", "✖️"}, + {":heavy_plus_sign:", "➕"}, + {":heavy_minus_sign:", "➖"}, + {":heavy_division_sign:", "➗"}, + {":infinity:", "♾️"}, + {":bangbang:", "‼️"}, + {":interrobang:", "⁉️"}, + {":question:", "❓"}, + {":grey_question:", "❔"}, + {":grey_exclamation:", "❕"}, + {":exclamation:", "❗"}, + {":heavy_exclamation_mark:", "❗"}, + {":wavy_dash:", "〰️"}, + {":currency_exchange:", "💱"}, + {":heavy_dollar_sign:", "💲"}, + {":medical_symbol:", "⚕️"}, + {":recycle:", "♻️"}, + {":fleur_de_lis:", "⚜️"}, + {":trident:", "🔱"}, + {":name_badge:", "📛"}, + {":beginner:", "🔰"}, + {":o:", "⭕"}, + {":white_check_mark:", "✅"}, + {":ballot_box_with_check:", "☑️"}, + {":heavy_check_mark:", "✔️"}, + {":x:", "❌"}, + {":negative_squared_cross_mark:", "❎"}, + {":curly_loop:", "➰"}, + {":loop:", "➿"}, + {":part_alternation_mark:", "〽️"}, + {":eight_spoked_asterisk:", "✳️"}, + {":eight_pointed_black_star:", "✴️"}, + {":sparkle:", "❇️"}, + {":copyright:", "©️"}, + {":registered:", "®️"}, + {":tm:", "™️"}, + {":hash:", "#️⃣"}, + {":asterisk:", "*️⃣"}, + {":zero:", "0️⃣"}, + {":one:", "1️⃣"}, + {":two:", "2️⃣"}, + {":three:", "3️⃣"}, + {":four:", "4️⃣"}, + {":five:", "5️⃣"}, + {":six:", "6️⃣"}, + {":seven:", "7️⃣"}, + {":eight:", "8️⃣"}, + {":nine:", "9️⃣"}, + {":keycap_ten:", "🔟"}, + {":capital_abcd:", "🔠"}, + {":abcd:", "🔡"}, + {":1234:", "🔢"}, + {":symbols:", "🔣"}, + {":abc:", "🔤"}, + {":a:", "🅰️"}, + {":ab:", "🆎"}, + {":b:", "🅱️"}, + {":cl:", "🆑"}, + {":cool:", "🆒"}, + {":free:", "🆓"}, + {":information_source:", "ℹ️"}, + {":id:", "🆔"}, + {":m:", "Ⓜ️"}, + {":new:", "🆕"}, + {":ng:", "🆖"}, + {":o2:", "🅾️"}, + {":ok:", "🆗"}, + {":parking:", "🅿️"}, + {":sos:", "🆘"}, + {":up:", "🆙"}, + {":vs:", "🆚"}, + {":koko:", "🈁"}, + {":sa:", "🈂️"}, + {":u6708:", "🈷️"}, + {":u6709:", "🈶"}, + {":u6307:", "🈯"}, + {":ideograph_advantage:", "🉐"}, + {":u5272:", "🈹"}, + {":u7121:", "🈚"}, + {":u7981:", "🈲"}, + {":accept:", "🉑"}, + {":u7533:", "🈸"}, + {":u5408:", "🈴"}, + {":u7a7a:", "🈳"}, + {":congratulations:", "㊗️"}, + {":secret:", "㊙️"}, + {":u55b6:", "🈺"}, + {":u6e80:", "🈵"}, + {":red_circle:", "🔴"}, + {":orange_circle:", "🟠"}, + {":yellow_circle:", "🟡"}, + {":green_circle:", "🟢"}, + {":large_blue_circle:", "🔵"}, + {":purple_circle:", "🟣"}, + {":brown_circle:", "🟤"}, + {":black_circle:", "⚫"}, + {":white_circle:", "⚪"}, + {":red_square:", "🟥"}, + {":orange_square:", "🟧"}, + {":yellow_square:", "🟨"}, + {":green_square:", "🟩"}, + {":blue_square:", "🟦"}, + {":purple_square:", "🟪"}, + {":brown_square:", "🟫"}, + {":black_large_square:", "⬛"}, + {":white_large_square:", "⬜"}, + {":black_medium_square:", "◼️"}, + {":white_medium_square:", "◻️"}, + {":black_medium_small_square:", "◾"}, + {":white_medium_small_square:", "◽"}, + {":black_small_square:", "▪️"}, + {":white_small_square:", "▫️"}, + {":large_orange_diamond:", "🔶"}, + {":large_blue_diamond:", "🔷"}, + {":small_orange_diamond:", "🔸"}, + {":small_blue_diamond:", "🔹"}, + {":small_red_triangle:", "🔺"}, + {":small_red_triangle_down:", "🔻"}, + {":diamond_shape_with_a_dot_inside:", "💠"}, + {":radio_button:", "🔘"}, + {":white_square_button:", "🔳"}, + {":black_square_button:", "🔲"}, + {":checkered_flag:", "🏁"}, + {":triangular_flag_on_post:", "🚩"}, + {":crossed_flags:", "🎌"}, + {":black_flag:", "🏴"}, + {":white_flag:", "🏳️"}, + {":rainbow_flag:", "🏳️‍🌈"}, + {":transgender_flag:", "🏳️‍⚧️"}, + {":pirate_flag:", "🏴‍☠️"}, + {":ascension_island:", "🇦🇨"}, + {":andorra:", "🇦🇩"}, + {":united_arab_emirates:", "🇦🇪"}, + {":afghanistan:", "🇦🇫"}, + {":antigua_barbuda:", "🇦🇬"}, + {":anguilla:", "🇦🇮"}, + {":albania:", "🇦🇱"}, + {":armenia:", "🇦🇲"}, + {":angola:", "🇦🇴"}, + {":antarctica:", "🇦🇶"}, + {":argentina:", "🇦🇷"}, + {":american_samoa:", "🇦🇸"}, + {":austria:", "🇦🇹"}, + {":australia:", "🇦🇺"}, + {":aruba:", "🇦🇼"}, + {":aland_islands:", "🇦🇽"}, + {":azerbaijan:", "🇦🇿"}, + {":bosnia_herzegovina:", "🇧🇦"}, + {":barbados:", "🇧🇧"}, + {":bangladesh:", "🇧🇩"}, + {":belgium:", "🇧🇪"}, + {":burkina_faso:", "🇧🇫"}, + {":bulgaria:", "🇧🇬"}, + {":bahrain:", "🇧🇭"}, + {":burundi:", "🇧🇮"}, + {":benin:", "🇧🇯"}, + {":st_barthelemy:", "🇧🇱"}, + {":bermuda:", "🇧🇲"}, + {":brunei:", "🇧🇳"}, + {":bolivia:", "🇧🇴"}, + {":caribbean_netherlands:", "🇧🇶"}, + {":brazil:", "🇧🇷"}, + {":bahamas:", "🇧🇸"}, + {":bhutan:", "🇧🇹"}, + {":bouvet_island:", "🇧🇻"}, + {":botswana:", "🇧🇼"}, + {":belarus:", "🇧🇾"}, + {":belize:", "🇧🇿"}, + {":canada:", "🇨🇦"}, + {":cocos_islands:", "🇨🇨"}, + {":congo_kinshasa:", "🇨🇩"}, + {":central_african_republic:", "🇨🇫"}, + {":congo_brazzaville:", "🇨🇬"}, + {":switzerland:", "🇨🇭"}, + {":cote_divoire:", "🇨🇮"}, + {":cook_islands:", "🇨🇰"}, + {":chile:", "🇨🇱"}, + {":cameroon:", "🇨🇲"}, + {":cn:", "🇨🇳"}, + {":colombia:", "🇨🇴"}, + {":clipperton_island:", "🇨🇵"}, + {":costa_rica:", "🇨🇷"}, + {":cuba:", "🇨🇺"}, + {":cape_verde:", "🇨🇻"}, + {":curacao:", "🇨🇼"}, + {":christmas_island:", "🇨🇽"}, + {":cyprus:", "🇨🇾"}, + {":czech_republic:", "🇨🇿"}, + {":de:", "🇩🇪"}, + {":diego_garcia:", "🇩🇬"}, + {":djibouti:", "🇩🇯"}, + {":denmark:", "🇩🇰"}, + {":dominica:", "🇩🇲"}, + {":dominican_republic:", "🇩🇴"}, + {":algeria:", "🇩🇿"}, + {":ceuta_melilla:", "🇪🇦"}, + {":ecuador:", "🇪🇨"}, + {":estonia:", "🇪🇪"}, + {":egypt:", "🇪🇬"}, + {":western_sahara:", "🇪🇭"}, + {":eritrea:", "🇪🇷"}, + {":es:", "🇪🇸"}, + {":ethiopia:", "🇪🇹"}, + {":eu:", "🇪🇺"}, + {":european_union:", "🇪🇺"}, + {":finland:", "🇫🇮"}, + {":fiji:", "🇫🇯"}, + {":falkland_islands:", "🇫🇰"}, + {":micronesia:", "🇫🇲"}, + {":faroe_islands:", "🇫🇴"}, + {":fr:", "🇫🇷"}, + {":gabon:", "🇬🇦"}, + {":gb:", "🇬🇧"}, + {":uk:", "🇬🇧"}, + {":grenada:", "🇬🇩"}, + {":georgia:", "🇬🇪"}, + {":french_guiana:", "🇬🇫"}, + {":guernsey:", "🇬🇬"}, + {":ghana:", "🇬🇭"}, + {":gibraltar:", "🇬🇮"}, + {":greenland:", "🇬🇱"}, + {":gambia:", "🇬🇲"}, + {":guinea:", "🇬🇳"}, + {":guadeloupe:", "🇬🇵"}, + {":equatorial_guinea:", "🇬🇶"}, + {":greece:", "🇬🇷"}, + {":south_georgia_south_sandwich_islands:", "🇬🇸"}, + {":guatemala:", "🇬🇹"}, + {":guam:", "🇬🇺"}, + {":guinea_bissau:", "🇬🇼"}, + {":guyana:", "🇬🇾"}, + {":hong_kong:", "🇭🇰"}, + {":heard_mcdonald_islands:", "🇭🇲"}, + {":honduras:", "🇭🇳"}, + {":croatia:", "🇭🇷"}, + {":haiti:", "🇭🇹"}, + {":hungary:", "🇭🇺"}, + {":canary_islands:", "🇮🇨"}, + {":indonesia:", "🇮🇩"}, + {":ireland:", "🇮🇪"}, + {":israel:", "🇮🇱"}, + {":isle_of_man:", "🇮🇲"}, + {":india:", "🇮🇳"}, + {":british_indian_ocean_territory:", "🇮🇴"}, + {":iraq:", "🇮🇶"}, + {":iran:", "🇮🇷"}, + {":iceland:", "🇮🇸"}, + {":it:", "🇮🇹"}, + {":jersey:", "🇯🇪"}, + {":jamaica:", "🇯🇲"}, + {":jordan:", "🇯🇴"}, + {":jp:", "🇯🇵"}, + {":kenya:", "🇰🇪"}, + {":kyrgyzstan:", "🇰🇬"}, + {":cambodia:", "🇰🇭"}, + {":kiribati:", "🇰🇮"}, + {":comoros:", "🇰🇲"}, + {":st_kitts_nevis:", "🇰🇳"}, + {":north_korea:", "🇰🇵"}, + {":kr:", "🇰🇷"}, + {":kuwait:", "🇰🇼"}, + {":cayman_islands:", "🇰🇾"}, + {":kazakhstan:", "🇰🇿"}, + {":laos:", "🇱🇦"}, + {":lebanon:", "🇱🇧"}, + {":st_lucia:", "🇱🇨"}, + {":liechtenstein:", "🇱🇮"}, + {":sri_lanka:", "🇱🇰"}, + {":liberia:", "🇱🇷"}, + {":lesotho:", "🇱🇸"}, + {":lithuania:", "🇱🇹"}, + {":luxembourg:", "🇱🇺"}, + {":latvia:", "🇱🇻"}, + {":libya:", "🇱🇾"}, + {":morocco:", "🇲🇦"}, + {":monaco:", "🇲🇨"}, + {":moldova:", "🇲🇩"}, + {":montenegro:", "🇲🇪"}, + {":st_martin:", "🇲🇫"}, + {":madagascar:", "🇲🇬"}, + {":marshall_islands:", "🇲🇭"}, + {":macedonia:", "🇲🇰"}, + {":mali:", "🇲🇱"}, + {":myanmar:", "🇲🇲"}, + {":mongolia:", "🇲🇳"}, + {":macau:", "🇲🇴"}, + {":northern_mariana_islands:", "🇲🇵"}, + {":martinique:", "🇲🇶"}, + {":mauritania:", "🇲🇷"}, + {":montserrat:", "🇲🇸"}, + {":malta:", "🇲🇹"}, + {":mauritius:", "🇲🇺"}, + {":maldives:", "🇲🇻"}, + {":malawi:", "🇲🇼"}, + {":mexico:", "🇲🇽"}, + {":malaysia:", "🇲🇾"}, + {":mozambique:", "🇲🇿"}, + {":namibia:", "🇳🇦"}, + {":new_caledonia:", "🇳🇨"}, + {":niger:", "🇳🇪"}, + {":norfolk_island:", "🇳🇫"}, + {":nigeria:", "🇳🇬"}, + {":nicaragua:", "🇳🇮"}, + {":netherlands:", "🇳🇱"}, + {":norway:", "🇳🇴"}, + {":nepal:", "🇳🇵"}, + {":nauru:", "🇳🇷"}, + {":niue:", "🇳🇺"}, + {":new_zealand:", "🇳🇿"}, + {":oman:", "🇴🇲"}, + {":panama:", "🇵🇦"}, + {":peru:", "🇵🇪"}, + {":french_polynesia:", "🇵🇫"}, + {":papua_new_guinea:", "🇵🇬"}, + {":philippines:", "🇵🇭"}, + {":pakistan:", "🇵🇰"}, + {":poland:", "🇵🇱"}, + {":st_pierre_miquelon:", "🇵🇲"}, + {":pitcairn_islands:", "🇵🇳"}, + {":puerto_rico:", "🇵🇷"}, + {":palestinian_territories:", "🇵🇸"}, + {":portugal:", "🇵🇹"}, + {":palau:", "🇵🇼"}, + {":paraguay:", "🇵🇾"}, + {":qatar:", "🇶🇦"}, + {":reunion:", "🇷🇪"}, + {":romania:", "🇷🇴"}, + {":serbia:", "🇷🇸"}, + {":ru:", "🇷🇺"}, + {":rwanda:", "🇷🇼"}, + {":saudi_arabia:", "🇸🇦"}, + {":solomon_islands:", "🇸🇧"}, + {":seychelles:", "🇸🇨"}, + {":sudan:", "🇸🇩"}, + {":sweden:", "🇸🇪"}, + {":singapore:", "🇸🇬"}, + {":st_helena:", "🇸🇭"}, + {":slovenia:", "🇸🇮"}, + {":svalbard_jan_mayen:", "🇸🇯"}, + {":slovakia:", "🇸🇰"}, + {":sierra_leone:", "🇸🇱"}, + {":san_marino:", "🇸🇲"}, + {":senegal:", "🇸🇳"}, + {":somalia:", "🇸🇴"}, + {":suriname:", "🇸🇷"}, + {":south_sudan:", "🇸🇸"}, + {":sao_tome_principe:", "🇸🇹"}, + {":el_salvador:", "🇸🇻"}, + {":sint_maarten:", "🇸🇽"}, + {":syria:", "🇸🇾"}, + {":swaziland:", "🇸🇿"}, + {":tristan_da_cunha:", "🇹🇦"}, + {":turks_caicos_islands:", "🇹🇨"}, + {":chad:", "🇹🇩"}, + {":french_southern_territories:", "🇹🇫"}, + {":togo:", "🇹🇬"}, + {":thailand:", "🇹🇭"}, + {":tajikistan:", "🇹🇯"}, + {":tokelau:", "🇹🇰"}, + {":timor_leste:", "🇹🇱"}, + {":turkmenistan:", "🇹🇲"}, + {":tunisia:", "🇹🇳"}, + {":tonga:", "🇹🇴"}, + {":tr:", "🇹🇷"}, + {":trinidad_tobago:", "🇹🇹"}, + {":tuvalu:", "🇹🇻"}, + {":taiwan:", "🇹🇼"}, + {":tanzania:", "🇹🇿"}, + {":ukraine:", "🇺🇦"}, + {":uganda:", "🇺🇬"}, + {":us_outlying_islands:", "🇺🇲"}, + {":united_nations:", "🇺🇳"}, + {":us:", "🇺🇸"}, + {":uruguay:", "🇺🇾"}, + {":uzbekistan:", "🇺🇿"}, + {":vatican_city:", "🇻🇦"}, + {":st_vincent_grenadines:", "🇻🇨"}, + {":venezuela:", "🇻🇪"}, + {":british_virgin_islands:", "🇻🇬"}, + {":us_virgin_islands:", "🇻🇮"}, + {":vietnam:", "🇻🇳"}, + {":vanuatu:", "🇻🇺"}, + {":wallis_futuna:", "🇼🇫"}, + {":samoa:", "🇼🇸"}, + {":kosovo:", "🇽🇰"}, + {":yemen:", "🇾🇪"}, + {":mayotte:", "🇾🇹"}, + {":south_africa:", "🇿🇦"}, + {":zambia:", "🇿🇲"}, + {":zimbabwe:", "🇿🇼"}, + {":england:", "🏴󠁧󠁢󠁥󠁮󠁧󠁿"}, + {":scotland:", "🏴󠁧󠁢󠁳󠁣󠁴󠁿"}, + {":wales:", "🏴󠁧󠁢󠁷󠁬󠁳󠁿"}, + {NULL, NULL} +}; + +#endif diff --git a/client/emojis_alt.h b/client/emojis_alt.h new file mode 100644 index 000000000..9d11f73b9 --- /dev/null +++ b/client/emojis_alt.h @@ -0,0 +1,15 @@ +#ifndef EMOJIS_ALT_H__ +#define EMOJIS_ALT_H__ + +typedef struct emoji_alt_s { + const char *alias; + const char *alttext; +} emoji_alt_t; +// emoji_alt_t array are expected to be NULL terminated + +static emoji_alt_t EmojiAltTable[] = { + {":wink:", ";)"}, + {NULL, NULL} +}; + +#endif diff --git a/client/emojis_scrap_github.py b/client/emojis_scrap_github.py new file mode 100755 index 000000000..777bf8aa5 --- /dev/null +++ b/client/emojis_scrap_github.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +# Mostly derived from https://github.com/mrowa44/emojify Copyright (c) 2015 Justyna Rachowicz + +from urllib.request import urlopen +import json + + +EMOJI_JSON_URL = 'https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json' + +def print_emoji(emoji_json): + for alias in emoji_json['aliases']: + print(' {{":{0}:", "{1}"}},'.format(alias, emoji_json['emoji'])) + +print( +"""#ifndef EMOJIS_H__ +#define EMOJIS_H__ + +typedef struct emoji_s { + const char *alias; + const char *emoji; +} emoji_t; +// emoji_t array are expected to be NULL terminated + +static emoji_t EmojiTable[] = {""") +with urlopen(EMOJI_JSON_URL) as conn: + emojis_json = json.loads(conn.read().decode('utf-8')) + for emoji_json in emojis_json: + print_emoji(emoji_json) + +print( +""" {NULL, NULL} +}; + +#endif""") diff --git a/client/proxmark3.c b/client/proxmark3.c index 522d982c7..c21852852 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -36,7 +36,7 @@ static void showBanner(void) { PrintAndLogEx(NORMAL, " " _BLUE_("██████╗ ███╗ ███╗ ████╗ ")); PrintAndLogEx(NORMAL, " " _BLUE_("██╔══██╗████╗ ████║ ══█║")); PrintAndLogEx(NORMAL, " " _BLUE_("██████╔╝██╔████╔██║ ████╔╝")); - PrintAndLogEx(NORMAL, " " _BLUE_("██╔═══╝ ██║╚██╔╝██║ ══█║") " iceman@icesql.net"); + PrintAndLogEx(NORMAL, " " _BLUE_("██╔═══╝ ██║╚██╔╝██║ ══█║") " :snowflake: iceman@icesql.net"); PrintAndLogEx(NORMAL, " " _BLUE_("██║ ██║ ╚═╝ ██║ ████╔╝") " https://github.com/rfidresearchgroup/proxmark3/"); PrintAndLogEx(NORMAL, " " _BLUE_("╚═╝ ╚═╝ ╚═╝ ╚═══╝ ") "pre-release v4.0"); #else @@ -756,6 +756,7 @@ int main(int argc, char *argv[]) { } session.supports_colors = DetectWindowsAnsiSupport(); + session.emoji_mode = ALTTEXT; session.stdinOnTTY = isatty(STDIN_FILENO); session.stdoutOnTTY = isatty(STDOUT_FILENO); @@ -766,8 +767,10 @@ int main(int argc, char *argv[]) { // For info, grep --color=auto is doing sth like this, plus test getenv("TERM") != "dumb": // struct stat tmp_stat; // if ((fstat (STDOUT_FILENO, &tmp_stat) == 0) && (S_ISCHR (tmp_stat.st_mode)) && isatty(STDIN_FILENO)) - if (session.stdinOnTTY && session.stdoutOnTTY) + if (session.stdinOnTTY && session.stdoutOnTTY) { session.supports_colors = true; + session.emoji_mode = EMOJI; + } #endif // Let's take a baudrate ok for real UART, USB-CDC & BT don't use that info anyway if (speed == 0) diff --git a/client/ui.c b/client/ui.c index 91a2a49e6..1c04def6c 100644 --- a/client/ui.c +++ b/client/ui.c @@ -31,6 +31,8 @@ # include // _mkdir #endif #include +#include "emojis.h" +#include "emojis_alt.h" session_arg_t session; double CursorScaleFactor = 1; @@ -132,39 +134,66 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) { if (g_showhints == 0 && level == HINT) return; - char prefix[20] = {0}; + char prefix[40] = {0}; char buffer[MAX_PRINT_BUFFER] = {0}; - char buffer2[MAX_PRINT_BUFFER + 20] = {0}; + char buffer2[MAX_PRINT_BUFFER + sizeof(prefix)] = {0}; char *token = NULL; char *tmp_ptr = NULL; FILE *stream = stdout; const char *spinner[] = {_YELLOW_("[\\]"), _YELLOW_("[|]"), _YELLOW_("[/]"), _YELLOW_("[-]")}; + const char *spinner_emoji[] = {" :clock1: ", " :clock2: ", " :clock3: ", " :clock4: ", " :clock5: ", " :clock6: ", + " :clock7: ", " :clock8: ", " :clock9: ", " :clock10: ", " :clock11: ", " :clock12: "}; switch (level) { case ERR: - strncpy(prefix, _RED_("[!!]"), sizeof(prefix) - 1); + if (session.emoji_mode == EMOJI) + strncpy(prefix, " :rotating_light: ", sizeof(prefix) - 1); + else + strncpy(prefix, _RED_("[!!]"), sizeof(prefix) - 1); stream = stderr; break; case FAILED: - strncpy(prefix, _RED_("[-]"), sizeof(prefix) - 1); + if (session.emoji_mode == EMOJI) + strncpy(prefix, " :no_entry: ", sizeof(prefix) - 1); + else + strncpy(prefix, _RED_("[-]"), sizeof(prefix) - 1); break; case DEBUG: - strncpy(prefix, _BLUE_("[#]"), sizeof(prefix) - 1); + if (session.emoji_mode == EMOJI) + strncpy(prefix, " :speech_balloon: ", sizeof(prefix) - 1); + else + strncpy(prefix, _BLUE_("[#]"), sizeof(prefix) - 1); break; case HINT: case SUCCESS: - strncpy(prefix, _GREEN_("[+]"), sizeof(prefix) - 1); + if (session.emoji_mode == EMOJI) + strncpy(prefix, " :star: ", sizeof(prefix) - 1); + else + strncpy(prefix, _GREEN_("[+]"), sizeof(prefix) - 1); break; case WARNING: - strncpy(prefix, _CYAN_("[!]"), sizeof(prefix) - 1); + if (session.emoji_mode == EMOJI) + strncpy(prefix, " :warning: ", sizeof(prefix) - 1); + else + strncpy(prefix, _CYAN_("[!]"), sizeof(prefix) - 1); break; case INFO: - strncpy(prefix, _YELLOW_("[=]"), sizeof(prefix) - 1); + if (session.emoji_mode == EMOJI) + strncpy(prefix, " :information_source: ", sizeof(prefix) - 1); + else + strncpy(prefix, _YELLOW_("[=]"), sizeof(prefix) - 1); break; case INPLACE: - strncpy(prefix, spinner[PrintAndLogEx_spinidx], sizeof(prefix) - 1); - PrintAndLogEx_spinidx++; - if (PrintAndLogEx_spinidx == ARRAYLEN(spinner)) - PrintAndLogEx_spinidx = 0; + if (session.emoji_mode == EMOJI) { + strncpy(prefix, spinner_emoji[PrintAndLogEx_spinidx], sizeof(prefix) - 1); + PrintAndLogEx_spinidx++; + if (PrintAndLogEx_spinidx >= ARRAYLEN(spinner_emoji)) + PrintAndLogEx_spinidx = 0; + } else { + strncpy(prefix, spinner[PrintAndLogEx_spinidx], sizeof(prefix) - 1); + PrintAndLogEx_spinidx++; + if (PrintAndLogEx_spinidx >= ARRAYLEN(spinner)) + PrintAndLogEx_spinidx = 0; + } break; case NORMAL: // no prefixes for normal @@ -207,9 +236,11 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) { } else { snprintf(buffer2, sizeof(buffer2), "%s%s", prefix, buffer); if (level == INPLACE) { - char buffer3[MAX_PRINT_BUFFER + 20] = {0}; + char buffer3[sizeof(buffer2)] = {0}; + char buffer4[sizeof(buffer2)] = {0}; memcpy_filter_ansi(buffer3, buffer2, sizeof(buffer2), !session.supports_colors); - fprintf(stream, "\r%s", buffer3); + memcpy_filter_emoji(buffer4, buffer3, sizeof(buffer3), session.emoji_mode); + fprintf(stream, "\r%s", buffer4); fflush(stream); } else { fPrintAndLog(stream, "%s", buffer2); @@ -225,6 +256,7 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { static int logging = 1; char buffer[MAX_PRINT_BUFFER] = {0}; char buffer2[MAX_PRINT_BUFFER] = {0}; + char buffer3[MAX_PRINT_BUFFER] = {0}; // lock this section to avoid interlacing prints from different threads pthread_mutex_lock(&print_lock); @@ -281,7 +313,8 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { bool filter_ansi = !session.supports_colors; memcpy_filter_ansi(buffer2, buffer, sizeof(buffer), filter_ansi); if (g_printAndLog & PRINTANDLOG_PRINT) { - fprintf(stream, "%s", buffer2); + memcpy_filter_emoji(buffer3, buffer2, sizeof(buffer2), session.emoji_mode); + fprintf(stream, "%s", buffer3); fprintf(stream, " "); // cleaning prompt fprintf(stream, "\n"); } @@ -356,6 +389,102 @@ void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter) { } } +static bool emojify_token(const char *token, uint8_t token_length, const char **emojified_token, uint8_t *emojified_token_length, emojiMode_t mode) { + int i = 0; + while (EmojiTable[i].alias) { + if ((strlen(EmojiTable[i].alias) == token_length) && (0 == memcmp(EmojiTable[i].alias, token, token_length))) { + switch (mode) { + case EMOJI: { + *emojified_token = EmojiTable[i].emoji; + *emojified_token_length = strlen(EmojiTable[i].emoji); + break; + } + case ALTTEXT: { + int j = 0; + *emojified_token_length = 0; + while (EmojiAltTable[j].alias) { + if ((strlen(EmojiAltTable[j].alias) == token_length) && (0 == memcmp(EmojiAltTable[j].alias, token, token_length))) { + *emojified_token = EmojiAltTable[j].alttext; + *emojified_token_length = strlen(EmojiAltTable[j].alttext); + break; + } + ++j; + } + break; + } + default: {// ERASE + *emojified_token_length = 0; + break; + } + } + return true; + } + ++i; + } + return false; +} + +static bool token_charset(uint8_t c) { + if ((c >= '0') && (c <= '9')) return true; + if ((c >= 'a') && (c <= 'z')) return true; + if ((c >= 'A') && (c <= 'Z')) return true; + if ((c == '_') || (c == '+') || (c == '-')) return true; + return false; +} + +void memcpy_filter_emoji(void *dest, const void *src, size_t n, emojiMode_t mode) { + if (mode == ALIAS) { + memcpy(dest, src, n); + } else { + // tokenize emoji + const char *emojified_token = NULL; + uint8_t emojified_token_length = 0; + char *current_token = NULL; + uint8_t current_token_length=0; + char current_char; + char *rdest = (char *)dest; + char *rsrc = (char *)src; + uint16_t si = 0; + for (uint16_t i = 0; i < n; i++) { + current_char = rsrc[i]; + + if (current_token_length == 0) { + // starting a new token. + if (current_char == ':') { + current_token = rsrc + i; + current_token_length = 1; + } else { // not starting a new token. + rdest[si++] = current_char; + } + } else { + // finishing the current token. + if (current_char == ':') { + // nothing changed? we still need the ending ':' as it might serve for an upcoming emoji + if (! emojify_token(current_token, current_token_length + 1, &emojified_token, &emojified_token_length, mode)) { + memcpy(rdest + si, current_token, current_token_length); + si += current_token_length; + current_token = rsrc + i; + current_token_length = 1; + } else { + memcpy(rdest + si, emojified_token, emojified_token_length); + si += emojified_token_length; + current_token_length = 0; + } + } else if (token_charset(current_char)) { // continuing the current token. + current_token_length++; + } else { // dropping the current token. + current_token_length++; + memcpy(rdest + si, current_token, current_token_length); + si += current_token_length; + current_token_length = 0; + } + } + } + memcpy(rdest + si, current_token, current_token_length); + si += current_token_length; + } +} + void iceIIR_Butterworth(int *data, const size_t len) { int *output = (int *) calloc(sizeof(int) * len, sizeof(uint8_t)); diff --git a/client/ui.h b/client/ui.h index c67865593..3b07caf46 100644 --- a/client/ui.h +++ b/client/ui.h @@ -17,10 +17,14 @@ #define _USE_MATH_DEFINES +typedef enum logLevel {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG, INPLACE, HINT} logLevel_t; +typedef enum emojiMode {ALIAS, EMOJI, ALTTEXT, ERASE} emojiMode_t; + typedef struct { bool stdinOnTTY; bool stdoutOnTTY; bool supports_colors; + emojiMode_t emoji_mode; bool pm3_present; bool help_dump_mode; } session_arg_t; @@ -31,7 +35,6 @@ extern session_arg_t session; #define M_PI 3.14159265358979323846264338327 #endif #define MAX_PRINT_BUFFER 2048 -typedef enum logLevel {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG, INPLACE, HINT} logLevel_t; void ShowGui(void); void HideGraphWindow(void); @@ -41,6 +44,7 @@ void PrintAndLogOptions(const char *str[][2], size_t size, size_t space); void PrintAndLogEx(logLevel_t level, const char *fmt, ...); void SetFlushAfterWrite(bool value); void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter); +void memcpy_filter_emoji(void *dest, const void *src, size_t n, emojiMode_t mode); extern double CursorScaleFactor; extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, GridOffset; From 82b3bfd936d85bd89efbdc41075fcd10ed5111dc Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 16 Mar 2020 11:38:13 +0100 Subject: [PATCH 150/298] :smiling_imp: support in changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1066a1f92..2b75de3ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - :smiling_imp: support (@doegox) - Additional colour changes as recommended by @iceman (@dunderhay) - Change type colour for `hf 14a` card types (@dunderhay) - Add colour to `hf mfdes` command (@dunderhay) From 9ebfe0908f1557476becbc4f1a773b114010f6c0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 16 Mar 2020 17:47:13 +0100 Subject: [PATCH 151/298] Prevent emoji on ProxSpace --- client/emojis.h | 3697 ++++++++++++++++----------------- client/emojis_scrap_github.py | 11 +- client/ui.c | 4 +- 3 files changed, 1857 insertions(+), 1855 deletions(-) diff --git a/client/emojis.h b/client/emojis.h index b7ef0e92a..2e5a75c62 100644 --- a/client/emojis.h +++ b/client/emojis.h @@ -8,1855 +8,1854 @@ typedef struct emoji_s { // emoji_t array are expected to be NULL terminated static emoji_t EmojiTable[] = { - {":grinning:", "😀"}, - {":smiley:", "😃"}, - {":smile:", "😄"}, - {":grin:", "😁"}, - {":laughing:", "😆"}, - {":satisfied:", "😆"}, - {":sweat_smile:", "😅"}, - {":rofl:", "🤣"}, - {":joy:", "😂"}, - {":slightly_smiling_face:", "🙂"}, - {":upside_down_face:", "🙃"}, - {":wink:", "😉"}, - {":blush:", "😊"}, - {":innocent:", "😇"}, - {":smiling_face_with_three_hearts:", "🥰"}, - {":heart_eyes:", "😍"}, - {":star_struck:", "🤩"}, - {":kissing_heart:", "😘"}, - {":kissing:", "😗"}, - {":relaxed:", "☺️"}, - {":kissing_closed_eyes:", "😚"}, - {":kissing_smiling_eyes:", "😙"}, - {":smiling_face_with_tear:", "🥲"}, - {":yum:", "😋"}, - {":stuck_out_tongue:", "😛"}, - {":stuck_out_tongue_winking_eye:", "😜"}, - {":zany_face:", "🤪"}, - {":stuck_out_tongue_closed_eyes:", "😝"}, - {":money_mouth_face:", "🤑"}, - {":hugs:", "🤗"}, - {":hand_over_mouth:", "🤭"}, - {":shushing_face:", "🤫"}, - {":thinking:", "🤔"}, - {":zipper_mouth_face:", "🤐"}, - {":raised_eyebrow:", "🤨"}, - {":neutral_face:", "😐"}, - {":expressionless:", "😑"}, - {":no_mouth:", "😶"}, - {":smirk:", "😏"}, - {":unamused:", "😒"}, - {":roll_eyes:", "🙄"}, - {":grimacing:", "😬"}, - {":lying_face:", "🤥"}, - {":relieved:", "😌"}, - {":pensive:", "😔"}, - {":sleepy:", "😪"}, - {":drooling_face:", "🤤"}, - {":sleeping:", "😴"}, - {":mask:", "😷"}, - {":face_with_thermometer:", "🤒"}, - {":face_with_head_bandage:", "🤕"}, - {":nauseated_face:", "🤢"}, - {":vomiting_face:", "🤮"}, - {":sneezing_face:", "🤧"}, - {":hot_face:", "🥵"}, - {":cold_face:", "🥶"}, - {":woozy_face:", "🥴"}, - {":dizzy_face:", "😵"}, - {":exploding_head:", "🤯"}, - {":cowboy_hat_face:", "🤠"}, - {":partying_face:", "🥳"}, - {":disguised_face:", "🥸"}, - {":sunglasses:", "😎"}, - {":nerd_face:", "🤓"}, - {":monocle_face:", "🧐"}, - {":confused:", "😕"}, - {":worried:", "😟"}, - {":slightly_frowning_face:", "🙁"}, - {":frowning_face:", "☹️"}, - {":open_mouth:", "😮"}, - {":hushed:", "😯"}, - {":astonished:", "😲"}, - {":flushed:", "😳"}, - {":pleading_face:", "🥺"}, - {":frowning:", "😦"}, - {":anguished:", "😧"}, - {":fearful:", "😨"}, - {":cold_sweat:", "😰"}, - {":disappointed_relieved:", "😥"}, - {":cry:", "😢"}, - {":sob:", "😭"}, - {":scream:", "😱"}, - {":confounded:", "😖"}, - {":persevere:", "😣"}, - {":disappointed:", "😞"}, - {":sweat:", "😓"}, - {":weary:", "😩"}, - {":tired_face:", "😫"}, - {":yawning_face:", "🥱"}, - {":triumph:", "😤"}, - {":rage:", "😡"}, - {":pout:", "😡"}, - {":angry:", "😠"}, - {":cursing_face:", "🤬"}, - {":smiling_imp:", "😈"}, - {":imp:", "👿"}, - {":skull:", "💀"}, - {":skull_and_crossbones:", "☠️"}, - {":hankey:", "💩"}, - {":poop:", "💩"}, - {":shit:", "💩"}, - {":clown_face:", "🤡"}, - {":japanese_ogre:", "👹"}, - {":japanese_goblin:", "👺"}, - {":ghost:", "👻"}, - {":alien:", "👽"}, - {":space_invader:", "👾"}, - {":robot:", "🤖"}, - {":smiley_cat:", "😺"}, - {":smile_cat:", "😸"}, - {":joy_cat:", "😹"}, - {":heart_eyes_cat:", "😻"}, - {":smirk_cat:", "😼"}, - {":kissing_cat:", "😽"}, - {":scream_cat:", "🙀"}, - {":crying_cat_face:", "😿"}, - {":pouting_cat:", "😾"}, - {":see_no_evil:", "🙈"}, - {":hear_no_evil:", "🙉"}, - {":speak_no_evil:", "🙊"}, - {":kiss:", "💋"}, - {":love_letter:", "💌"}, - {":cupid:", "💘"}, - {":gift_heart:", "💝"}, - {":sparkling_heart:", "💖"}, - {":heartpulse:", "💗"}, - {":heartbeat:", "💓"}, - {":revolving_hearts:", "💞"}, - {":two_hearts:", "💕"}, - {":heart_decoration:", "💟"}, - {":heavy_heart_exclamation:", "❣️"}, - {":broken_heart:", "💔"}, - {":heart:", "❤️"}, - {":orange_heart:", "🧡"}, - {":yellow_heart:", "💛"}, - {":green_heart:", "💚"}, - {":blue_heart:", "💙"}, - {":purple_heart:", "💜"}, - {":brown_heart:", "🤎"}, - {":black_heart:", "🖤"}, - {":white_heart:", "🤍"}, - {":100:", "💯"}, - {":anger:", "💢"}, - {":boom:", "💥"}, - {":collision:", "💥"}, - {":dizzy:", "💫"}, - {":sweat_drops:", "💦"}, - {":dash:", "💨"}, - {":hole:", "🕳️"}, - {":bomb:", "💣"}, - {":speech_balloon:", "💬"}, - {":eye_speech_bubble:", "👁️‍🗨️"}, - {":left_speech_bubble:", "🗨️"}, - {":right_anger_bubble:", "🗯️"}, - {":thought_balloon:", "💭"}, - {":zzz:", "💤"}, - {":wave:", "👋"}, - {":raised_back_of_hand:", "🤚"}, - {":raised_hand_with_fingers_splayed:", "🖐️"}, - {":hand:", "✋"}, - {":raised_hand:", "✋"}, - {":vulcan_salute:", "🖖"}, - {":ok_hand:", "👌"}, - {":pinched_fingers:", "🤌"}, - {":pinching_hand:", "🤏"}, - {":v:", "✌️"}, - {":crossed_fingers:", "🤞"}, - {":love_you_gesture:", "🤟"}, - {":metal:", "🤘"}, - {":call_me_hand:", "🤙"}, - {":point_left:", "👈"}, - {":point_right:", "👉"}, - {":point_up_2:", "👆"}, - {":middle_finger:", "🖕"}, - {":fu:", "🖕"}, - {":point_down:", "👇"}, - {":point_up:", "☝️"}, - {":+1:", "👍"}, - {":thumbsup:", "👍"}, - {":-1:", "👎"}, - {":thumbsdown:", "👎"}, - {":fist_raised:", "✊"}, - {":fist:", "✊"}, - {":fist_oncoming:", "👊"}, - {":facepunch:", "👊"}, - {":punch:", "👊"}, - {":fist_left:", "🤛"}, - {":fist_right:", "🤜"}, - {":clap:", "👏"}, - {":raised_hands:", "🙌"}, - {":open_hands:", "👐"}, - {":palms_up_together:", "🤲"}, - {":handshake:", "🤝"}, - {":pray:", "🙏"}, - {":writing_hand:", "✍️"}, - {":nail_care:", "💅"}, - {":selfie:", "🤳"}, - {":muscle:", "💪"}, - {":mechanical_arm:", "🦾"}, - {":mechanical_leg:", "🦿"}, - {":leg:", "🦵"}, - {":foot:", "🦶"}, - {":ear:", "👂"}, - {":ear_with_hearing_aid:", "🦻"}, - {":nose:", "👃"}, - {":brain:", "🧠"}, - {":anatomical_heart:", "🫀"}, - {":lungs:", "🫁"}, - {":tooth:", "🦷"}, - {":bone:", "🦴"}, - {":eyes:", "👀"}, - {":eye:", "👁️"}, - {":tongue:", "👅"}, - {":lips:", "👄"}, - {":baby:", "👶"}, - {":child:", "🧒"}, - {":boy:", "👦"}, - {":girl:", "👧"}, - {":adult:", "🧑"}, - {":blond_haired_person:", "👱"}, - {":man:", "👨"}, - {":bearded_person:", "🧔"}, - {":red_haired_man:", "👨‍🦰"}, - {":curly_haired_man:", "👨‍🦱"}, - {":white_haired_man:", "👨‍🦳"}, - {":bald_man:", "👨‍🦲"}, - {":woman:", "👩"}, - {":red_haired_woman:", "👩‍🦰"}, - {":person_red_hair:", "🧑‍🦰"}, - {":curly_haired_woman:", "👩‍🦱"}, - {":person_curly_hair:", "🧑‍🦱"}, - {":white_haired_woman:", "👩‍🦳"}, - {":person_white_hair:", "🧑‍🦳"}, - {":bald_woman:", "👩‍🦲"}, - {":person_bald:", "🧑‍🦲"}, - {":blond_haired_woman:", "👱‍♀️"}, - {":blonde_woman:", "👱‍♀️"}, - {":blond_haired_man:", "👱‍♂️"}, - {":older_adult:", "🧓"}, - {":older_man:", "👴"}, - {":older_woman:", "👵"}, - {":frowning_person:", "🙍"}, - {":frowning_man:", "🙍‍♂️"}, - {":frowning_woman:", "🙍‍♀️"}, - {":pouting_face:", "🙎"}, - {":pouting_man:", "🙎‍♂️"}, - {":pouting_woman:", "🙎‍♀️"}, - {":no_good:", "🙅"}, - {":no_good_man:", "🙅‍♂️"}, - {":ng_man:", "🙅‍♂️"}, - {":no_good_woman:", "🙅‍♀️"}, - {":ng_woman:", "🙅‍♀️"}, - {":ok_person:", "🙆"}, - {":ok_man:", "🙆‍♂️"}, - {":ok_woman:", "🙆‍♀️"}, - {":tipping_hand_person:", "💁"}, - {":information_desk_person:", "💁"}, - {":tipping_hand_man:", "💁‍♂️"}, - {":sassy_man:", "💁‍♂️"}, - {":tipping_hand_woman:", "💁‍♀️"}, - {":sassy_woman:", "💁‍♀️"}, - {":raising_hand:", "🙋"}, - {":raising_hand_man:", "🙋‍♂️"}, - {":raising_hand_woman:", "🙋‍♀️"}, - {":deaf_person:", "🧏"}, - {":deaf_man:", "🧏‍♂️"}, - {":deaf_woman:", "🧏‍♀️"}, - {":bow:", "🙇"}, - {":bowing_man:", "🙇‍♂️"}, - {":bowing_woman:", "🙇‍♀️"}, - {":facepalm:", "🤦"}, - {":man_facepalming:", "🤦‍♂️"}, - {":woman_facepalming:", "🤦‍♀️"}, - {":shrug:", "🤷"}, - {":man_shrugging:", "🤷‍♂️"}, - {":woman_shrugging:", "🤷‍♀️"}, - {":health_worker:", "🧑‍⚕️"}, - {":man_health_worker:", "👨‍⚕️"}, - {":woman_health_worker:", "👩‍⚕️"}, - {":student:", "🧑‍🎓"}, - {":man_student:", "👨‍🎓"}, - {":woman_student:", "👩‍🎓"}, - {":teacher:", "🧑‍🏫"}, - {":man_teacher:", "👨‍🏫"}, - {":woman_teacher:", "👩‍🏫"}, - {":judge:", "🧑‍⚖️"}, - {":man_judge:", "👨‍⚖️"}, - {":woman_judge:", "👩‍⚖️"}, - {":farmer:", "🧑‍🌾"}, - {":man_farmer:", "👨‍🌾"}, - {":woman_farmer:", "👩‍🌾"}, - {":cook:", "🧑‍🍳"}, - {":man_cook:", "👨‍🍳"}, - {":woman_cook:", "👩‍🍳"}, - {":mechanic:", "🧑‍🔧"}, - {":man_mechanic:", "👨‍🔧"}, - {":woman_mechanic:", "👩‍🔧"}, - {":factory_worker:", "🧑‍🏭"}, - {":man_factory_worker:", "👨‍🏭"}, - {":woman_factory_worker:", "👩‍🏭"}, - {":office_worker:", "🧑‍💼"}, - {":man_office_worker:", "👨‍💼"}, - {":woman_office_worker:", "👩‍💼"}, - {":scientist:", "🧑‍🔬"}, - {":man_scientist:", "👨‍🔬"}, - {":woman_scientist:", "👩‍🔬"}, - {":technologist:", "🧑‍💻"}, - {":man_technologist:", "👨‍💻"}, - {":woman_technologist:", "👩‍💻"}, - {":singer:", "🧑‍🎤"}, - {":man_singer:", "👨‍🎤"}, - {":woman_singer:", "👩‍🎤"}, - {":artist:", "🧑‍🎨"}, - {":man_artist:", "👨‍🎨"}, - {":woman_artist:", "👩‍🎨"}, - {":pilot:", "🧑‍✈️"}, - {":man_pilot:", "👨‍✈️"}, - {":woman_pilot:", "👩‍✈️"}, - {":astronaut:", "🧑‍🚀"}, - {":man_astronaut:", "👨‍🚀"}, - {":woman_astronaut:", "👩‍🚀"}, - {":firefighter:", "🧑‍🚒"}, - {":man_firefighter:", "👨‍🚒"}, - {":woman_firefighter:", "👩‍🚒"}, - {":police_officer:", "👮"}, - {":cop:", "👮"}, - {":policeman:", "👮‍♂️"}, - {":policewoman:", "👮‍♀️"}, - {":detective:", "🕵️"}, - {":male_detective:", "🕵️‍♂️"}, - {":female_detective:", "🕵️‍♀️"}, - {":guard:", "💂"}, - {":guardsman:", "💂‍♂️"}, - {":guardswoman:", "💂‍♀️"}, - {":ninja:", "🥷"}, - {":construction_worker:", "👷"}, - {":construction_worker_man:", "👷‍♂️"}, - {":construction_worker_woman:", "👷‍♀️"}, - {":prince:", "🤴"}, - {":princess:", "👸"}, - {":person_with_turban:", "👳"}, - {":man_with_turban:", "👳‍♂️"}, - {":woman_with_turban:", "👳‍♀️"}, - {":man_with_gua_pi_mao:", "👲"}, - {":woman_with_headscarf:", "🧕"}, - {":person_in_tuxedo:", "🤵"}, - {":man_in_tuxedo:", "🤵‍♂️"}, - {":woman_in_tuxedo:", "🤵‍♀️"}, - {":person_with_veil:", "👰"}, - {":man_with_veil:", "👰‍♂️"}, - {":woman_with_veil:", "👰‍♀️"}, - {":bride_with_veil:", "👰‍♀️"}, - {":pregnant_woman:", "🤰"}, - {":breast_feeding:", "🤱"}, - {":woman_feeding_baby:", "👩‍🍼"}, - {":man_feeding_baby:", "👨‍🍼"}, - {":person_feeding_baby:", "🧑‍🍼"}, - {":angel:", "👼"}, - {":santa:", "🎅"}, - {":mrs_claus:", "🤶"}, - {":mx_claus:", "🧑‍🎄"}, - {":superhero:", "🦸"}, - {":superhero_man:", "🦸‍♂️"}, - {":superhero_woman:", "🦸‍♀️"}, - {":supervillain:", "🦹"}, - {":supervillain_man:", "🦹‍♂️"}, - {":supervillain_woman:", "🦹‍♀️"}, - {":mage:", "🧙"}, - {":mage_man:", "🧙‍♂️"}, - {":mage_woman:", "🧙‍♀️"}, - {":fairy:", "🧚"}, - {":fairy_man:", "🧚‍♂️"}, - {":fairy_woman:", "🧚‍♀️"}, - {":vampire:", "🧛"}, - {":vampire_man:", "🧛‍♂️"}, - {":vampire_woman:", "🧛‍♀️"}, - {":merperson:", "🧜"}, - {":merman:", "🧜‍♂️"}, - {":mermaid:", "🧜‍♀️"}, - {":elf:", "🧝"}, - {":elf_man:", "🧝‍♂️"}, - {":elf_woman:", "🧝‍♀️"}, - {":genie:", "🧞"}, - {":genie_man:", "🧞‍♂️"}, - {":genie_woman:", "🧞‍♀️"}, - {":zombie:", "🧟"}, - {":zombie_man:", "🧟‍♂️"}, - {":zombie_woman:", "🧟‍♀️"}, - {":massage:", "💆"}, - {":massage_man:", "💆‍♂️"}, - {":massage_woman:", "💆‍♀️"}, - {":haircut:", "💇"}, - {":haircut_man:", "💇‍♂️"}, - {":haircut_woman:", "💇‍♀️"}, - {":walking:", "🚶"}, - {":walking_man:", "🚶‍♂️"}, - {":walking_woman:", "🚶‍♀️"}, - {":standing_person:", "🧍"}, - {":standing_man:", "🧍‍♂️"}, - {":standing_woman:", "🧍‍♀️"}, - {":kneeling_person:", "🧎"}, - {":kneeling_man:", "🧎‍♂️"}, - {":kneeling_woman:", "🧎‍♀️"}, - {":person_with_probing_cane:", "🧑‍🦯"}, - {":man_with_probing_cane:", "👨‍🦯"}, - {":woman_with_probing_cane:", "👩‍🦯"}, - {":person_in_motorized_wheelchair:", "🧑‍🦼"}, - {":man_in_motorized_wheelchair:", "👨‍🦼"}, - {":woman_in_motorized_wheelchair:", "👩‍🦼"}, - {":person_in_manual_wheelchair:", "🧑‍🦽"}, - {":man_in_manual_wheelchair:", "👨‍🦽"}, - {":woman_in_manual_wheelchair:", "👩‍🦽"}, - {":runner:", "🏃"}, - {":running:", "🏃"}, - {":running_man:", "🏃‍♂️"}, - {":running_woman:", "🏃‍♀️"}, - {":woman_dancing:", "💃"}, - {":dancer:", "💃"}, - {":man_dancing:", "🕺"}, - {":business_suit_levitating:", "🕴️"}, - {":dancers:", "👯"}, - {":dancing_men:", "👯‍♂️"}, - {":dancing_women:", "👯‍♀️"}, - {":sauna_person:", "🧖"}, - {":sauna_man:", "🧖‍♂️"}, - {":sauna_woman:", "🧖‍♀️"}, - {":climbing:", "🧗"}, - {":climbing_man:", "🧗‍♂️"}, - {":climbing_woman:", "🧗‍♀️"}, - {":person_fencing:", "🤺"}, - {":horse_racing:", "🏇"}, - {":skier:", "⛷️"}, - {":snowboarder:", "🏂"}, - {":golfing:", "🏌️"}, - {":golfing_man:", "🏌️‍♂️"}, - {":golfing_woman:", "🏌️‍♀️"}, - {":surfer:", "🏄"}, - {":surfing_man:", "🏄‍♂️"}, - {":surfing_woman:", "🏄‍♀️"}, - {":rowboat:", "🚣"}, - {":rowing_man:", "🚣‍♂️"}, - {":rowing_woman:", "🚣‍♀️"}, - {":swimmer:", "🏊"}, - {":swimming_man:", "🏊‍♂️"}, - {":swimming_woman:", "🏊‍♀️"}, - {":bouncing_ball_person:", "⛹️"}, - {":bouncing_ball_man:", "⛹️‍♂️"}, - {":basketball_man:", "⛹️‍♂️"}, - {":bouncing_ball_woman:", "⛹️‍♀️"}, - {":basketball_woman:", "⛹️‍♀️"}, - {":weight_lifting:", "🏋️"}, - {":weight_lifting_man:", "🏋️‍♂️"}, - {":weight_lifting_woman:", "🏋️‍♀️"}, - {":bicyclist:", "🚴"}, - {":biking_man:", "🚴‍♂️"}, - {":biking_woman:", "🚴‍♀️"}, - {":mountain_bicyclist:", "🚵"}, - {":mountain_biking_man:", "🚵‍♂️"}, - {":mountain_biking_woman:", "🚵‍♀️"}, - {":cartwheeling:", "🤸"}, - {":man_cartwheeling:", "🤸‍♂️"}, - {":woman_cartwheeling:", "🤸‍♀️"}, - {":wrestling:", "🤼"}, - {":men_wrestling:", "🤼‍♂️"}, - {":women_wrestling:", "🤼‍♀️"}, - {":water_polo:", "🤽"}, - {":man_playing_water_polo:", "🤽‍♂️"}, - {":woman_playing_water_polo:", "🤽‍♀️"}, - {":handball_person:", "🤾"}, - {":man_playing_handball:", "🤾‍♂️"}, - {":woman_playing_handball:", "🤾‍♀️"}, - {":juggling_person:", "🤹"}, - {":man_juggling:", "🤹‍♂️"}, - {":woman_juggling:", "🤹‍♀️"}, - {":lotus_position:", "🧘"}, - {":lotus_position_man:", "🧘‍♂️"}, - {":lotus_position_woman:", "🧘‍♀️"}, - {":bath:", "🛀"}, - {":sleeping_bed:", "🛌"}, - {":people_holding_hands:", "🧑‍🤝‍🧑"}, - {":two_women_holding_hands:", "👭"}, - {":couple:", "👫"}, - {":two_men_holding_hands:", "👬"}, - {":couplekiss:", "💏"}, - {":couplekiss_man_woman:", "👩‍❤️‍💋‍👨"}, - {":couplekiss_man_man:", "👨‍❤️‍💋‍👨"}, - {":couplekiss_woman_woman:", "👩‍❤️‍💋‍👩"}, - {":couple_with_heart:", "💑"}, - {":couple_with_heart_woman_man:", "👩‍❤️‍👨"}, - {":couple_with_heart_man_man:", "👨‍❤️‍👨"}, - {":couple_with_heart_woman_woman:", "👩‍❤️‍👩"}, - {":family:", "👪"}, - {":family_man_woman_boy:", "👨‍👩‍👦"}, - {":family_man_woman_girl:", "👨‍👩‍👧"}, - {":family_man_woman_girl_boy:", "👨‍👩‍👧‍👦"}, - {":family_man_woman_boy_boy:", "👨‍👩‍👦‍👦"}, - {":family_man_woman_girl_girl:", "👨‍👩‍👧‍👧"}, - {":family_man_man_boy:", "👨‍👨‍👦"}, - {":family_man_man_girl:", "👨‍👨‍👧"}, - {":family_man_man_girl_boy:", "👨‍👨‍👧‍👦"}, - {":family_man_man_boy_boy:", "👨‍👨‍👦‍👦"}, - {":family_man_man_girl_girl:", "👨‍👨‍👧‍👧"}, - {":family_woman_woman_boy:", "👩‍👩‍👦"}, - {":family_woman_woman_girl:", "👩‍👩‍👧"}, - {":family_woman_woman_girl_boy:", "👩‍👩‍👧‍👦"}, - {":family_woman_woman_boy_boy:", "👩‍👩‍👦‍👦"}, - {":family_woman_woman_girl_girl:", "👩‍👩‍👧‍👧"}, - {":family_man_boy:", "👨‍👦"}, - {":family_man_boy_boy:", "👨‍👦‍👦"}, - {":family_man_girl:", "👨‍👧"}, - {":family_man_girl_boy:", "👨‍👧‍👦"}, - {":family_man_girl_girl:", "👨‍👧‍👧"}, - {":family_woman_boy:", "👩‍👦"}, - {":family_woman_boy_boy:", "👩‍👦‍👦"}, - {":family_woman_girl:", "👩‍👧"}, - {":family_woman_girl_boy:", "👩‍👧‍👦"}, - {":family_woman_girl_girl:", "👩‍👧‍👧"}, - {":speaking_head:", "🗣️"}, - {":bust_in_silhouette:", "👤"}, - {":busts_in_silhouette:", "👥"}, - {":people_hugging:", "🫂"}, - {":footprints:", "👣"}, - {":monkey_face:", "🐵"}, - {":monkey:", "🐒"}, - {":gorilla:", "🦍"}, - {":orangutan:", "🦧"}, - {":dog:", "🐶"}, - {":dog2:", "🐕"}, - {":guide_dog:", "🦮"}, - {":service_dog:", "🐕‍🦺"}, - {":poodle:", "🐩"}, - {":wolf:", "🐺"}, - {":fox_face:", "🦊"}, - {":raccoon:", "🦝"}, - {":cat:", "🐱"}, - {":cat2:", "🐈"}, - {":black_cat:", "🐈‍⬛"}, - {":lion:", "🦁"}, - {":tiger:", "🐯"}, - {":tiger2:", "🐅"}, - {":leopard:", "🐆"}, - {":horse:", "🐴"}, - {":racehorse:", "🐎"}, - {":unicorn:", "🦄"}, - {":zebra:", "🦓"}, - {":deer:", "🦌"}, - {":bison:", "🦬"}, - {":cow:", "🐮"}, - {":ox:", "🐂"}, - {":water_buffalo:", "🐃"}, - {":cow2:", "🐄"}, - {":pig:", "🐷"}, - {":pig2:", "🐖"}, - {":boar:", "🐗"}, - {":pig_nose:", "🐽"}, - {":ram:", "🐏"}, - {":sheep:", "🐑"}, - {":goat:", "🐐"}, - {":dromedary_camel:", "🐪"}, - {":camel:", "🐫"}, - {":llama:", "🦙"}, - {":giraffe:", "🦒"}, - {":elephant:", "🐘"}, - {":mammoth:", "🦣"}, - {":rhinoceros:", "🦏"}, - {":hippopotamus:", "🦛"}, - {":mouse:", "🐭"}, - {":mouse2:", "🐁"}, - {":rat:", "🐀"}, - {":hamster:", "🐹"}, - {":rabbit:", "🐰"}, - {":rabbit2:", "🐇"}, - {":chipmunk:", "🐿️"}, - {":beaver:", "🦫"}, - {":hedgehog:", "🦔"}, - {":bat:", "🦇"}, - {":bear:", "🐻"}, - {":polar_bear:", "🐻‍❄️"}, - {":koala:", "🐨"}, - {":panda_face:", "🐼"}, - {":sloth:", "🦥"}, - {":otter:", "🦦"}, - {":skunk:", "🦨"}, - {":kangaroo:", "🦘"}, - {":badger:", "🦡"}, - {":feet:", "🐾"}, - {":paw_prints:", "🐾"}, - {":turkey:", "🦃"}, - {":chicken:", "🐔"}, - {":rooster:", "🐓"}, - {":hatching_chick:", "🐣"}, - {":baby_chick:", "🐤"}, - {":hatched_chick:", "🐥"}, - {":bird:", "🐦"}, - {":penguin:", "🐧"}, - {":dove:", "🕊️"}, - {":eagle:", "🦅"}, - {":duck:", "🦆"}, - {":swan:", "🦢"}, - {":owl:", "🦉"}, - {":dodo:", "🦤"}, - {":feather:", "🪶"}, - {":flamingo:", "🦩"}, - {":peacock:", "🦚"}, - {":parrot:", "🦜"}, - {":frog:", "🐸"}, - {":crocodile:", "🐊"}, - {":turtle:", "🐢"}, - {":lizard:", "🦎"}, - {":snake:", "🐍"}, - {":dragon_face:", "🐲"}, - {":dragon:", "🐉"}, - {":sauropod:", "🦕"}, - {":t-rex:", "🦖"}, - {":whale:", "🐳"}, - {":whale2:", "🐋"}, - {":dolphin:", "🐬"}, - {":flipper:", "🐬"}, - {":seal:", "🦭"}, - {":fish:", "🐟"}, - {":tropical_fish:", "🐠"}, - {":blowfish:", "🐡"}, - {":shark:", "🦈"}, - {":octopus:", "🐙"}, - {":shell:", "🐚"}, - {":snail:", "🐌"}, - {":butterfly:", "🦋"}, - {":bug:", "🐛"}, - {":ant:", "🐜"}, - {":bee:", "🐝"}, - {":honeybee:", "🐝"}, - {":beetle:", "🪲"}, - {":lady_beetle:", "🐞"}, - {":cricket:", "🦗"}, - {":cockroach:", "🪳"}, - {":spider:", "🕷️"}, - {":spider_web:", "🕸️"}, - {":scorpion:", "🦂"}, - {":mosquito:", "🦟"}, - {":fly:", "🪰"}, - {":worm:", "🪱"}, - {":microbe:", "🦠"}, - {":bouquet:", "💐"}, - {":cherry_blossom:", "🌸"}, - {":white_flower:", "💮"}, - {":rosette:", "🏵️"}, - {":rose:", "🌹"}, - {":wilted_flower:", "🥀"}, - {":hibiscus:", "🌺"}, - {":sunflower:", "🌻"}, - {":blossom:", "🌼"}, - {":tulip:", "🌷"}, - {":seedling:", "🌱"}, - {":potted_plant:", "🪴"}, - {":evergreen_tree:", "🌲"}, - {":deciduous_tree:", "🌳"}, - {":palm_tree:", "🌴"}, - {":cactus:", "🌵"}, - {":ear_of_rice:", "🌾"}, - {":herb:", "🌿"}, - {":shamrock:", "☘️"}, - {":four_leaf_clover:", "🍀"}, - {":maple_leaf:", "🍁"}, - {":fallen_leaf:", "🍂"}, - {":leaves:", "🍃"}, - {":grapes:", "🍇"}, - {":melon:", "🍈"}, - {":watermelon:", "🍉"}, - {":tangerine:", "🍊"}, - {":orange:", "🍊"}, - {":mandarin:", "🍊"}, - {":lemon:", "🍋"}, - {":banana:", "🍌"}, - {":pineapple:", "🍍"}, - {":mango:", "🥭"}, - {":apple:", "🍎"}, - {":green_apple:", "🍏"}, - {":pear:", "🍐"}, - {":peach:", "🍑"}, - {":cherries:", "🍒"}, - {":strawberry:", "🍓"}, - {":blueberries:", "🫐"}, - {":kiwi_fruit:", "🥝"}, - {":tomato:", "🍅"}, - {":olive:", "🫒"}, - {":coconut:", "🥥"}, - {":avocado:", "🥑"}, - {":eggplant:", "🍆"}, - {":potato:", "🥔"}, - {":carrot:", "🥕"}, - {":corn:", "🌽"}, - {":hot_pepper:", "🌶️"}, - {":bell_pepper:", "🫑"}, - {":cucumber:", "🥒"}, - {":leafy_green:", "🥬"}, - {":broccoli:", "🥦"}, - {":garlic:", "🧄"}, - {":onion:", "🧅"}, - {":mushroom:", "🍄"}, - {":peanuts:", "🥜"}, - {":chestnut:", "🌰"}, - {":bread:", "🍞"}, - {":croissant:", "🥐"}, - {":baguette_bread:", "🥖"}, - {":flatbread:", "🫓"}, - {":pretzel:", "🥨"}, - {":bagel:", "🥯"}, - {":pancakes:", "🥞"}, - {":waffle:", "🧇"}, - {":cheese:", "🧀"}, - {":meat_on_bone:", "🍖"}, - {":poultry_leg:", "🍗"}, - {":cut_of_meat:", "🥩"}, - {":bacon:", "🥓"}, - {":hamburger:", "🍔"}, - {":fries:", "🍟"}, - {":pizza:", "🍕"}, - {":hotdog:", "🌭"}, - {":sandwich:", "🥪"}, - {":taco:", "🌮"}, - {":burrito:", "🌯"}, - {":tamale:", "🫔"}, - {":stuffed_flatbread:", "🥙"}, - {":falafel:", "🧆"}, - {":egg:", "🥚"}, - {":fried_egg:", "🍳"}, - {":shallow_pan_of_food:", "🥘"}, - {":stew:", "🍲"}, - {":fondue:", "🫕"}, - {":bowl_with_spoon:", "🥣"}, - {":green_salad:", "🥗"}, - {":popcorn:", "🍿"}, - {":butter:", "🧈"}, - {":salt:", "🧂"}, - {":canned_food:", "🥫"}, - {":bento:", "🍱"}, - {":rice_cracker:", "🍘"}, - {":rice_ball:", "🍙"}, - {":rice:", "🍚"}, - {":curry:", "🍛"}, - {":ramen:", "🍜"}, - {":spaghetti:", "🍝"}, - {":sweet_potato:", "🍠"}, - {":oden:", "🍢"}, - {":sushi:", "🍣"}, - {":fried_shrimp:", "🍤"}, - {":fish_cake:", "🍥"}, - {":moon_cake:", "🥮"}, - {":dango:", "🍡"}, - {":dumpling:", "🥟"}, - {":fortune_cookie:", "🥠"}, - {":takeout_box:", "🥡"}, - {":crab:", "🦀"}, - {":lobster:", "🦞"}, - {":shrimp:", "🦐"}, - {":squid:", "🦑"}, - {":oyster:", "🦪"}, - {":icecream:", "🍦"}, - {":shaved_ice:", "🍧"}, - {":ice_cream:", "🍨"}, - {":doughnut:", "🍩"}, - {":cookie:", "🍪"}, - {":birthday:", "🎂"}, - {":cake:", "🍰"}, - {":cupcake:", "🧁"}, - {":pie:", "🥧"}, - {":chocolate_bar:", "🍫"}, - {":candy:", "🍬"}, - {":lollipop:", "🍭"}, - {":custard:", "🍮"}, - {":honey_pot:", "🍯"}, - {":baby_bottle:", "🍼"}, - {":milk_glass:", "🥛"}, - {":coffee:", "☕"}, - {":teapot:", "🫖"}, - {":tea:", "🍵"}, - {":sake:", "🍶"}, - {":champagne:", "🍾"}, - {":wine_glass:", "🍷"}, - {":cocktail:", "🍸"}, - {":tropical_drink:", "🍹"}, - {":beer:", "🍺"}, - {":beers:", "🍻"}, - {":clinking_glasses:", "🥂"}, - {":tumbler_glass:", "🥃"}, - {":cup_with_straw:", "🥤"}, - {":bubble_tea:", "🧋"}, - {":beverage_box:", "🧃"}, - {":mate:", "🧉"}, - {":ice_cube:", "🧊"}, - {":chopsticks:", "🥢"}, - {":plate_with_cutlery:", "🍽️"}, - {":fork_and_knife:", "🍴"}, - {":spoon:", "🥄"}, - {":hocho:", "🔪"}, - {":knife:", "🔪"}, - {":amphora:", "🏺"}, - {":earth_africa:", "🌍"}, - {":earth_americas:", "🌎"}, - {":earth_asia:", "🌏"}, - {":globe_with_meridians:", "🌐"}, - {":world_map:", "🗺️"}, - {":japan:", "🗾"}, - {":compass:", "🧭"}, - {":mountain_snow:", "🏔️"}, - {":mountain:", "⛰️"}, - {":volcano:", "🌋"}, - {":mount_fuji:", "🗻"}, - {":camping:", "🏕️"}, - {":beach_umbrella:", "🏖️"}, - {":desert:", "🏜️"}, - {":desert_island:", "🏝️"}, - {":national_park:", "🏞️"}, - {":stadium:", "🏟️"}, - {":classical_building:", "🏛️"}, - {":building_construction:", "🏗️"}, - {":bricks:", "🧱"}, - {":rock:", "🪨"}, - {":wood:", "🪵"}, - {":hut:", "🛖"}, - {":houses:", "🏘️"}, - {":derelict_house:", "🏚️"}, - {":house:", "🏠"}, - {":house_with_garden:", "🏡"}, - {":office:", "🏢"}, - {":post_office:", "🏣"}, - {":european_post_office:", "🏤"}, - {":hospital:", "🏥"}, - {":bank:", "🏦"}, - {":hotel:", "🏨"}, - {":love_hotel:", "🏩"}, - {":convenience_store:", "🏪"}, - {":school:", "🏫"}, - {":department_store:", "🏬"}, - {":factory:", "🏭"}, - {":japanese_castle:", "🏯"}, - {":european_castle:", "🏰"}, - {":wedding:", "💒"}, - {":tokyo_tower:", "🗼"}, - {":statue_of_liberty:", "🗽"}, - {":church:", "⛪"}, - {":mosque:", "🕌"}, - {":hindu_temple:", "🛕"}, - {":synagogue:", "🕍"}, - {":shinto_shrine:", "⛩️"}, - {":kaaba:", "🕋"}, - {":fountain:", "⛲"}, - {":tent:", "⛺"}, - {":foggy:", "🌁"}, - {":night_with_stars:", "🌃"}, - {":cityscape:", "🏙️"}, - {":sunrise_over_mountains:", "🌄"}, - {":sunrise:", "🌅"}, - {":city_sunset:", "🌆"}, - {":city_sunrise:", "🌇"}, - {":bridge_at_night:", "🌉"}, - {":hotsprings:", "♨️"}, - {":carousel_horse:", "🎠"}, - {":ferris_wheel:", "🎡"}, - {":roller_coaster:", "🎢"}, - {":barber:", "💈"}, - {":circus_tent:", "🎪"}, - {":steam_locomotive:", "🚂"}, - {":railway_car:", "🚃"}, - {":bullettrain_side:", "🚄"}, - {":bullettrain_front:", "🚅"}, - {":train2:", "🚆"}, - {":metro:", "🚇"}, - {":light_rail:", "🚈"}, - {":station:", "🚉"}, - {":tram:", "🚊"}, - {":monorail:", "🚝"}, - {":mountain_railway:", "🚞"}, - {":train:", "🚋"}, - {":bus:", "🚌"}, - {":oncoming_bus:", "🚍"}, - {":trolleybus:", "🚎"}, - {":minibus:", "🚐"}, - {":ambulance:", "🚑"}, - {":fire_engine:", "🚒"}, - {":police_car:", "🚓"}, - {":oncoming_police_car:", "🚔"}, - {":taxi:", "🚕"}, - {":oncoming_taxi:", "🚖"}, - {":car:", "🚗"}, - {":red_car:", "🚗"}, - {":oncoming_automobile:", "🚘"}, - {":blue_car:", "🚙"}, - {":pickup_truck:", "🛻"}, - {":truck:", "🚚"}, - {":articulated_lorry:", "🚛"}, - {":tractor:", "🚜"}, - {":racing_car:", "🏎️"}, - {":motorcycle:", "🏍️"}, - {":motor_scooter:", "🛵"}, - {":manual_wheelchair:", "🦽"}, - {":motorized_wheelchair:", "🦼"}, - {":auto_rickshaw:", "🛺"}, - {":bike:", "🚲"}, - {":kick_scooter:", "🛴"}, - {":skateboard:", "🛹"}, - {":roller_skate:", "🛼"}, - {":busstop:", "🚏"}, - {":motorway:", "🛣️"}, - {":railway_track:", "🛤️"}, - {":oil_drum:", "🛢️"}, - {":fuelpump:", "⛽"}, - {":rotating_light:", "🚨"}, - {":traffic_light:", "🚥"}, - {":vertical_traffic_light:", "🚦"}, - {":stop_sign:", "🛑"}, - {":construction:", "🚧"}, - {":anchor:", "⚓"}, - {":boat:", "⛵"}, - {":sailboat:", "⛵"}, - {":canoe:", "🛶"}, - {":speedboat:", "🚤"}, - {":passenger_ship:", "🛳️"}, - {":ferry:", "⛴️"}, - {":motor_boat:", "🛥️"}, - {":ship:", "🚢"}, - {":airplane:", "✈️"}, - {":small_airplane:", "🛩️"}, - {":flight_departure:", "🛫"}, - {":flight_arrival:", "🛬"}, - {":parachute:", "🪂"}, - {":seat:", "💺"}, - {":helicopter:", "🚁"}, - {":suspension_railway:", "🚟"}, - {":mountain_cableway:", "🚠"}, - {":aerial_tramway:", "🚡"}, - {":artificial_satellite:", "🛰️"}, - {":rocket:", "🚀"}, - {":flying_saucer:", "🛸"}, - {":bellhop_bell:", "🛎️"}, - {":luggage:", "🧳"}, - {":hourglass:", "⌛"}, - {":hourglass_flowing_sand:", "⏳"}, - {":watch:", "⌚"}, - {":alarm_clock:", "⏰"}, - {":stopwatch:", "⏱️"}, - {":timer_clock:", "⏲️"}, - {":mantelpiece_clock:", "🕰️"}, - {":clock12:", "🕛"}, - {":clock1230:", "🕧"}, - {":clock1:", "🕐"}, - {":clock130:", "🕜"}, - {":clock2:", "🕑"}, - {":clock230:", "🕝"}, - {":clock3:", "🕒"}, - {":clock330:", "🕞"}, - {":clock4:", "🕓"}, - {":clock430:", "🕟"}, - {":clock5:", "🕔"}, - {":clock530:", "🕠"}, - {":clock6:", "🕕"}, - {":clock630:", "🕡"}, - {":clock7:", "🕖"}, - {":clock730:", "🕢"}, - {":clock8:", "🕗"}, - {":clock830:", "🕣"}, - {":clock9:", "🕘"}, - {":clock930:", "🕤"}, - {":clock10:", "🕙"}, - {":clock1030:", "🕥"}, - {":clock11:", "🕚"}, - {":clock1130:", "🕦"}, - {":new_moon:", "🌑"}, - {":waxing_crescent_moon:", "🌒"}, - {":first_quarter_moon:", "🌓"}, - {":moon:", "🌔"}, - {":waxing_gibbous_moon:", "🌔"}, - {":full_moon:", "🌕"}, - {":waning_gibbous_moon:", "🌖"}, - {":last_quarter_moon:", "🌗"}, - {":waning_crescent_moon:", "🌘"}, - {":crescent_moon:", "🌙"}, - {":new_moon_with_face:", "🌚"}, - {":first_quarter_moon_with_face:", "🌛"}, - {":last_quarter_moon_with_face:", "🌜"}, - {":thermometer:", "🌡️"}, - {":sunny:", "☀️"}, - {":full_moon_with_face:", "🌝"}, - {":sun_with_face:", "🌞"}, - {":ringed_planet:", "🪐"}, - {":star:", "⭐"}, - {":star2:", "🌟"}, - {":stars:", "🌠"}, - {":milky_way:", "🌌"}, - {":cloud:", "☁️"}, - {":partly_sunny:", "⛅"}, - {":cloud_with_lightning_and_rain:", "⛈️"}, - {":sun_behind_small_cloud:", "🌤️"}, - {":sun_behind_large_cloud:", "🌥️"}, - {":sun_behind_rain_cloud:", "🌦️"}, - {":cloud_with_rain:", "🌧️"}, - {":cloud_with_snow:", "🌨️"}, - {":cloud_with_lightning:", "🌩️"}, - {":tornado:", "🌪️"}, - {":fog:", "🌫️"}, - {":wind_face:", "🌬️"}, - {":cyclone:", "🌀"}, - {":rainbow:", "🌈"}, - {":closed_umbrella:", "🌂"}, - {":open_umbrella:", "☂️"}, - {":umbrella:", "☔"}, - {":parasol_on_ground:", "⛱️"}, - {":zap:", "⚡"}, - {":snowflake:", "❄️"}, - {":snowman_with_snow:", "☃️"}, - {":snowman:", "⛄"}, - {":comet:", "☄️"}, - {":fire:", "🔥"}, - {":droplet:", "💧"}, - {":ocean:", "🌊"}, - {":jack_o_lantern:", "🎃"}, - {":christmas_tree:", "🎄"}, - {":fireworks:", "🎆"}, - {":sparkler:", "🎇"}, - {":firecracker:", "🧨"}, - {":sparkles:", "✨"}, - {":balloon:", "🎈"}, - {":tada:", "🎉"}, - {":confetti_ball:", "🎊"}, - {":tanabata_tree:", "🎋"}, - {":bamboo:", "🎍"}, - {":dolls:", "🎎"}, - {":flags:", "🎏"}, - {":wind_chime:", "🎐"}, - {":rice_scene:", "🎑"}, - {":red_envelope:", "🧧"}, - {":ribbon:", "🎀"}, - {":gift:", "🎁"}, - {":reminder_ribbon:", "🎗️"}, - {":tickets:", "🎟️"}, - {":ticket:", "🎫"}, - {":medal_military:", "🎖️"}, - {":trophy:", "🏆"}, - {":medal_sports:", "🏅"}, - {":1st_place_medal:", "🥇"}, - {":2nd_place_medal:", "🥈"}, - {":3rd_place_medal:", "🥉"}, - {":soccer:", "⚽"}, - {":baseball:", "⚾"}, - {":softball:", "🥎"}, - {":basketball:", "🏀"}, - {":volleyball:", "🏐"}, - {":football:", "🏈"}, - {":rugby_football:", "🏉"}, - {":tennis:", "🎾"}, - {":flying_disc:", "🥏"}, - {":bowling:", "🎳"}, - {":cricket_game:", "🏏"}, - {":field_hockey:", "🏑"}, - {":ice_hockey:", "🏒"}, - {":lacrosse:", "🥍"}, - {":ping_pong:", "🏓"}, - {":badminton:", "🏸"}, - {":boxing_glove:", "🥊"}, - {":martial_arts_uniform:", "🥋"}, - {":goal_net:", "🥅"}, - {":golf:", "⛳"}, - {":ice_skate:", "⛸️"}, - {":fishing_pole_and_fish:", "🎣"}, - {":diving_mask:", "🤿"}, - {":running_shirt_with_sash:", "🎽"}, - {":ski:", "🎿"}, - {":sled:", "🛷"}, - {":curling_stone:", "🥌"}, - {":dart:", "🎯"}, - {":yo_yo:", "🪀"}, - {":kite:", "🪁"}, - {":8ball:", "🎱"}, - {":crystal_ball:", "🔮"}, - {":magic_wand:", "🪄"}, - {":nazar_amulet:", "🧿"}, - {":video_game:", "🎮"}, - {":joystick:", "🕹️"}, - {":slot_machine:", "🎰"}, - {":game_die:", "🎲"}, - {":jigsaw:", "🧩"}, - {":teddy_bear:", "🧸"}, - {":pi_ata:", "🪅"}, - {":nesting_dolls:", "🪆"}, - {":spades:", "♠️"}, - {":hearts:", "♥️"}, - {":diamonds:", "♦️"}, - {":clubs:", "♣️"}, - {":chess_pawn:", "♟️"}, - {":black_joker:", "🃏"}, - {":mahjong:", "🀄"}, - {":flower_playing_cards:", "🎴"}, - {":performing_arts:", "🎭"}, - {":framed_picture:", "🖼️"}, - {":art:", "🎨"}, - {":thread:", "🧵"}, - {":sewing_needle:", "🪡"}, - {":yarn:", "🧶"}, - {":knot:", "🪢"}, - {":eyeglasses:", "👓"}, - {":dark_sunglasses:", "🕶️"}, - {":goggles:", "🥽"}, - {":lab_coat:", "🥼"}, - {":safety_vest:", "🦺"}, - {":necktie:", "👔"}, - {":shirt:", "👕"}, - {":tshirt:", "👕"}, - {":jeans:", "👖"}, - {":scarf:", "🧣"}, - {":gloves:", "🧤"}, - {":coat:", "🧥"}, - {":socks:", "🧦"}, - {":dress:", "👗"}, - {":kimono:", "👘"}, - {":sari:", "🥻"}, - {":one_piece_swimsuit:", "🩱"}, - {":swim_brief:", "🩲"}, - {":shorts:", "🩳"}, - {":bikini:", "👙"}, - {":womans_clothes:", "👚"}, - {":purse:", "👛"}, - {":handbag:", "👜"}, - {":pouch:", "👝"}, - {":shopping:", "🛍️"}, - {":school_satchel:", "🎒"}, - {":thong_sandal:", "🩴"}, - {":mans_shoe:", "👞"}, - {":shoe:", "👞"}, - {":athletic_shoe:", "👟"}, - {":hiking_boot:", "🥾"}, - {":flat_shoe:", "🥿"}, - {":high_heel:", "👠"}, - {":sandal:", "👡"}, - {":ballet_shoes:", "🩰"}, - {":boot:", "👢"}, - {":crown:", "👑"}, - {":womans_hat:", "👒"}, - {":tophat:", "🎩"}, - {":mortar_board:", "🎓"}, - {":billed_cap:", "🧢"}, - {":military_helmet:", "🪖"}, - {":rescue_worker_helmet:", "⛑️"}, - {":prayer_beads:", "📿"}, - {":lipstick:", "💄"}, - {":ring:", "💍"}, - {":gem:", "💎"}, - {":mute:", "🔇"}, - {":speaker:", "🔈"}, - {":sound:", "🔉"}, - {":loud_sound:", "🔊"}, - {":loudspeaker:", "📢"}, - {":mega:", "📣"}, - {":postal_horn:", "📯"}, - {":bell:", "🔔"}, - {":no_bell:", "🔕"}, - {":musical_score:", "🎼"}, - {":musical_note:", "🎵"}, - {":notes:", "🎶"}, - {":studio_microphone:", "🎙️"}, - {":level_slider:", "🎚️"}, - {":control_knobs:", "🎛️"}, - {":microphone:", "🎤"}, - {":headphones:", "🎧"}, - {":radio:", "📻"}, - {":saxophone:", "🎷"}, - {":accordion:", "🪗"}, - {":guitar:", "🎸"}, - {":musical_keyboard:", "🎹"}, - {":trumpet:", "🎺"}, - {":violin:", "🎻"}, - {":banjo:", "🪕"}, - {":drum:", "🥁"}, - {":long_drum:", "🪘"}, - {":iphone:", "📱"}, - {":calling:", "📲"}, - {":phone:", "☎️"}, - {":telephone:", "☎️"}, - {":telephone_receiver:", "📞"}, - {":pager:", "📟"}, - {":fax:", "📠"}, - {":battery:", "🔋"}, - {":electric_plug:", "🔌"}, - {":computer:", "💻"}, - {":desktop_computer:", "🖥️"}, - {":printer:", "🖨️"}, - {":keyboard:", "⌨️"}, - {":computer_mouse:", "🖱️"}, - {":trackball:", "🖲️"}, - {":minidisc:", "💽"}, - {":floppy_disk:", "💾"}, - {":cd:", "💿"}, - {":dvd:", "📀"}, - {":abacus:", "🧮"}, - {":movie_camera:", "🎥"}, - {":film_strip:", "🎞️"}, - {":film_projector:", "📽️"}, - {":clapper:", "🎬"}, - {":tv:", "📺"}, - {":camera:", "📷"}, - {":camera_flash:", "📸"}, - {":video_camera:", "📹"}, - {":vhs:", "📼"}, - {":mag:", "🔍"}, - {":mag_right:", "🔎"}, - {":candle:", "🕯️"}, - {":bulb:", "💡"}, - {":flashlight:", "🔦"}, - {":izakaya_lantern:", "🏮"}, - {":lantern:", "🏮"}, - {":diya_lamp:", "🪔"}, - {":notebook_with_decorative_cover:", "📔"}, - {":closed_book:", "📕"}, - {":book:", "📖"}, - {":open_book:", "📖"}, - {":green_book:", "📗"}, - {":blue_book:", "📘"}, - {":orange_book:", "📙"}, - {":books:", "📚"}, - {":notebook:", "📓"}, - {":ledger:", "📒"}, - {":page_with_curl:", "📃"}, - {":scroll:", "📜"}, - {":page_facing_up:", "📄"}, - {":newspaper:", "📰"}, - {":newspaper_roll:", "🗞️"}, - {":bookmark_tabs:", "📑"}, - {":bookmark:", "🔖"}, - {":label:", "🏷️"}, - {":moneybag:", "💰"}, - {":coin:", "🪙"}, - {":yen:", "💴"}, - {":dollar:", "💵"}, - {":euro:", "💶"}, - {":pound:", "💷"}, - {":money_with_wings:", "💸"}, - {":credit_card:", "💳"}, - {":receipt:", "🧾"}, - {":chart:", "💹"}, - {":email:", "✉️"}, - {":envelope:", "✉️"}, - {":e-mail:", "📧"}, - {":incoming_envelope:", "📨"}, - {":envelope_with_arrow:", "📩"}, - {":outbox_tray:", "📤"}, - {":inbox_tray:", "📥"}, - {":package:", "📦"}, - {":mailbox:", "📫"}, - {":mailbox_closed:", "📪"}, - {":mailbox_with_mail:", "📬"}, - {":mailbox_with_no_mail:", "📭"}, - {":postbox:", "📮"}, - {":ballot_box:", "🗳️"}, - {":pencil2:", "✏️"}, - {":black_nib:", "✒️"}, - {":fountain_pen:", "🖋️"}, - {":pen:", "🖊️"}, - {":paintbrush:", "🖌️"}, - {":crayon:", "🖍️"}, - {":memo:", "📝"}, - {":pencil:", "📝"}, - {":briefcase:", "💼"}, - {":file_folder:", "📁"}, - {":open_file_folder:", "📂"}, - {":card_index_dividers:", "🗂️"}, - {":date:", "📅"}, - {":calendar:", "📆"}, - {":spiral_notepad:", "🗒️"}, - {":spiral_calendar:", "🗓️"}, - {":card_index:", "📇"}, - {":chart_with_upwards_trend:", "📈"}, - {":chart_with_downwards_trend:", "📉"}, - {":bar_chart:", "📊"}, - {":clipboard:", "📋"}, - {":pushpin:", "📌"}, - {":round_pushpin:", "📍"}, - {":paperclip:", "📎"}, - {":paperclips:", "🖇️"}, - {":straight_ruler:", "📏"}, - {":triangular_ruler:", "📐"}, - {":scissors:", "✂️"}, - {":card_file_box:", "🗃️"}, - {":file_cabinet:", "🗄️"}, - {":wastebasket:", "🗑️"}, - {":lock:", "🔒"}, - {":unlock:", "🔓"}, - {":lock_with_ink_pen:", "🔏"}, - {":closed_lock_with_key:", "🔐"}, - {":key:", "🔑"}, - {":old_key:", "🗝️"}, - {":hammer:", "🔨"}, - {":axe:", "🪓"}, - {":pick:", "⛏️"}, - {":hammer_and_pick:", "⚒️"}, - {":hammer_and_wrench:", "🛠️"}, - {":dagger:", "🗡️"}, - {":crossed_swords:", "⚔️"}, - {":gun:", "🔫"}, - {":boomerang:", "🪃"}, - {":bow_and_arrow:", "🏹"}, - {":shield:", "🛡️"}, - {":carpentry_saw:", "🪚"}, - {":wrench:", "🔧"}, - {":screwdriver:", "🪛"}, - {":nut_and_bolt:", "🔩"}, - {":gear:", "⚙️"}, - {":clamp:", "🗜️"}, - {":balance_scale:", "⚖️"}, - {":probing_cane:", "🦯"}, - {":link:", "🔗"}, - {":chains:", "⛓️"}, - {":hook:", "🪝"}, - {":toolbox:", "🧰"}, - {":magnet:", "🧲"}, - {":ladder:", "🪜"}, - {":alembic:", "⚗️"}, - {":test_tube:", "🧪"}, - {":petri_dish:", "🧫"}, - {":dna:", "🧬"}, - {":microscope:", "🔬"}, - {":telescope:", "🔭"}, - {":satellite:", "📡"}, - {":syringe:", "💉"}, - {":drop_of_blood:", "🩸"}, - {":pill:", "💊"}, - {":adhesive_bandage:", "🩹"}, - {":stethoscope:", "🩺"}, - {":door:", "🚪"}, - {":elevator:", "🛗"}, - {":mirror:", "🪞"}, - {":window:", "🪟"}, - {":bed:", "🛏️"}, - {":couch_and_lamp:", "🛋️"}, - {":chair:", "🪑"}, - {":toilet:", "🚽"}, - {":plunger:", "🪠"}, - {":shower:", "🚿"}, - {":bathtub:", "🛁"}, - {":mouse_trap:", "🪤"}, - {":razor:", "🪒"}, - {":lotion_bottle:", "🧴"}, - {":safety_pin:", "🧷"}, - {":broom:", "🧹"}, - {":basket:", "🧺"}, - {":roll_of_paper:", "🧻"}, - {":bucket:", "🪣"}, - {":soap:", "🧼"}, - {":toothbrush:", "🪥"}, - {":sponge:", "🧽"}, - {":fire_extinguisher:", "🧯"}, - {":shopping_cart:", "🛒"}, - {":smoking:", "🚬"}, - {":coffin:", "⚰️"}, - {":headstone:", "🪦"}, - {":funeral_urn:", "⚱️"}, - {":moyai:", "🗿"}, - {":placard:", "🪧"}, - {":atm:", "🏧"}, - {":put_litter_in_its_place:", "🚮"}, - {":potable_water:", "🚰"}, - {":wheelchair:", "♿"}, - {":mens:", "🚹"}, - {":womens:", "🚺"}, - {":restroom:", "🚻"}, - {":baby_symbol:", "🚼"}, - {":wc:", "🚾"}, - {":passport_control:", "🛂"}, - {":customs:", "🛃"}, - {":baggage_claim:", "🛄"}, - {":left_luggage:", "🛅"}, - {":warning:", "⚠️"}, - {":children_crossing:", "🚸"}, - {":no_entry:", "⛔"}, - {":no_entry_sign:", "🚫"}, - {":no_bicycles:", "🚳"}, - {":no_smoking:", "🚭"}, - {":do_not_litter:", "🚯"}, - {":non-potable_water:", "🚱"}, - {":no_pedestrians:", "🚷"}, - {":no_mobile_phones:", "📵"}, - {":underage:", "🔞"}, - {":radioactive:", "☢️"}, - {":biohazard:", "☣️"}, - {":arrow_up:", "⬆️"}, - {":arrow_upper_right:", "↗️"}, - {":arrow_right:", "➡️"}, - {":arrow_lower_right:", "↘️"}, - {":arrow_down:", "⬇️"}, - {":arrow_lower_left:", "↙️"}, - {":arrow_left:", "⬅️"}, - {":arrow_upper_left:", "↖️"}, - {":arrow_up_down:", "↕️"}, - {":left_right_arrow:", "↔️"}, - {":leftwards_arrow_with_hook:", "↩️"}, - {":arrow_right_hook:", "↪️"}, - {":arrow_heading_up:", "⤴️"}, - {":arrow_heading_down:", "⤵️"}, - {":arrows_clockwise:", "🔃"}, - {":arrows_counterclockwise:", "🔄"}, - {":back:", "🔙"}, - {":end:", "🔚"}, - {":on:", "🔛"}, - {":soon:", "🔜"}, - {":top:", "🔝"}, - {":place_of_worship:", "🛐"}, - {":atom_symbol:", "⚛️"}, - {":om:", "🕉️"}, - {":star_of_david:", "✡️"}, - {":wheel_of_dharma:", "☸️"}, - {":yin_yang:", "☯️"}, - {":latin_cross:", "✝️"}, - {":orthodox_cross:", "☦️"}, - {":star_and_crescent:", "☪️"}, - {":peace_symbol:", "☮️"}, - {":menorah:", "🕎"}, - {":six_pointed_star:", "🔯"}, - {":aries:", "♈"}, - {":taurus:", "♉"}, - {":gemini:", "♊"}, - {":cancer:", "♋"}, - {":leo:", "♌"}, - {":virgo:", "♍"}, - {":libra:", "♎"}, - {":scorpius:", "♏"}, - {":sagittarius:", "♐"}, - {":capricorn:", "♑"}, - {":aquarius:", "♒"}, - {":pisces:", "♓"}, - {":ophiuchus:", "⛎"}, - {":twisted_rightwards_arrows:", "🔀"}, - {":repeat:", "🔁"}, - {":repeat_one:", "🔂"}, - {":arrow_forward:", "▶️"}, - {":fast_forward:", "⏩"}, - {":next_track_button:", "⏭️"}, - {":play_or_pause_button:", "⏯️"}, - {":arrow_backward:", "◀️"}, - {":rewind:", "⏪"}, - {":previous_track_button:", "⏮️"}, - {":arrow_up_small:", "🔼"}, - {":arrow_double_up:", "⏫"}, - {":arrow_down_small:", "🔽"}, - {":arrow_double_down:", "⏬"}, - {":pause_button:", "⏸️"}, - {":stop_button:", "⏹️"}, - {":record_button:", "⏺️"}, - {":eject_button:", "⏏️"}, - {":cinema:", "🎦"}, - {":low_brightness:", "🔅"}, - {":high_brightness:", "🔆"}, - {":signal_strength:", "📶"}, - {":vibration_mode:", "📳"}, - {":mobile_phone_off:", "📴"}, - {":female_sign:", "♀️"}, - {":male_sign:", "♂️"}, - {":transgender_symbol:", "⚧️"}, - {":heavy_multiplication_x:", "✖️"}, - {":heavy_plus_sign:", "➕"}, - {":heavy_minus_sign:", "➖"}, - {":heavy_division_sign:", "➗"}, - {":infinity:", "♾️"}, - {":bangbang:", "‼️"}, - {":interrobang:", "⁉️"}, - {":question:", "❓"}, - {":grey_question:", "❔"}, - {":grey_exclamation:", "❕"}, - {":exclamation:", "❗"}, - {":heavy_exclamation_mark:", "❗"}, - {":wavy_dash:", "〰️"}, - {":currency_exchange:", "💱"}, - {":heavy_dollar_sign:", "💲"}, - {":medical_symbol:", "⚕️"}, - {":recycle:", "♻️"}, - {":fleur_de_lis:", "⚜️"}, - {":trident:", "🔱"}, - {":name_badge:", "📛"}, - {":beginner:", "🔰"}, - {":o:", "⭕"}, - {":white_check_mark:", "✅"}, - {":ballot_box_with_check:", "☑️"}, - {":heavy_check_mark:", "✔️"}, - {":x:", "❌"}, - {":negative_squared_cross_mark:", "❎"}, - {":curly_loop:", "➰"}, - {":loop:", "➿"}, - {":part_alternation_mark:", "〽️"}, - {":eight_spoked_asterisk:", "✳️"}, - {":eight_pointed_black_star:", "✴️"}, - {":sparkle:", "❇️"}, - {":copyright:", "©️"}, - {":registered:", "®️"}, - {":tm:", "™️"}, - {":hash:", "#️⃣"}, - {":asterisk:", "*️⃣"}, - {":zero:", "0️⃣"}, - {":one:", "1️⃣"}, - {":two:", "2️⃣"}, - {":three:", "3️⃣"}, - {":four:", "4️⃣"}, - {":five:", "5️⃣"}, - {":six:", "6️⃣"}, - {":seven:", "7️⃣"}, - {":eight:", "8️⃣"}, - {":nine:", "9️⃣"}, - {":keycap_ten:", "🔟"}, - {":capital_abcd:", "🔠"}, - {":abcd:", "🔡"}, - {":1234:", "🔢"}, - {":symbols:", "🔣"}, - {":abc:", "🔤"}, - {":a:", "🅰️"}, - {":ab:", "🆎"}, - {":b:", "🅱️"}, - {":cl:", "🆑"}, - {":cool:", "🆒"}, - {":free:", "🆓"}, - {":information_source:", "ℹ️"}, - {":id:", "🆔"}, - {":m:", "Ⓜ️"}, - {":new:", "🆕"}, - {":ng:", "🆖"}, - {":o2:", "🅾️"}, - {":ok:", "🆗"}, - {":parking:", "🅿️"}, - {":sos:", "🆘"}, - {":up:", "🆙"}, - {":vs:", "🆚"}, - {":koko:", "🈁"}, - {":sa:", "🈂️"}, - {":u6708:", "🈷️"}, - {":u6709:", "🈶"}, - {":u6307:", "🈯"}, - {":ideograph_advantage:", "🉐"}, - {":u5272:", "🈹"}, - {":u7121:", "🈚"}, - {":u7981:", "🈲"}, - {":accept:", "🉑"}, - {":u7533:", "🈸"}, - {":u5408:", "🈴"}, - {":u7a7a:", "🈳"}, - {":congratulations:", "㊗️"}, - {":secret:", "㊙️"}, - {":u55b6:", "🈺"}, - {":u6e80:", "🈵"}, - {":red_circle:", "🔴"}, - {":orange_circle:", "🟠"}, - {":yellow_circle:", "🟡"}, - {":green_circle:", "🟢"}, - {":large_blue_circle:", "🔵"}, - {":purple_circle:", "🟣"}, - {":brown_circle:", "🟤"}, - {":black_circle:", "⚫"}, - {":white_circle:", "⚪"}, - {":red_square:", "🟥"}, - {":orange_square:", "🟧"}, - {":yellow_square:", "🟨"}, - {":green_square:", "🟩"}, - {":blue_square:", "🟦"}, - {":purple_square:", "🟪"}, - {":brown_square:", "🟫"}, - {":black_large_square:", "⬛"}, - {":white_large_square:", "⬜"}, - {":black_medium_square:", "◼️"}, - {":white_medium_square:", "◻️"}, - {":black_medium_small_square:", "◾"}, - {":white_medium_small_square:", "◽"}, - {":black_small_square:", "▪️"}, - {":white_small_square:", "▫️"}, - {":large_orange_diamond:", "🔶"}, - {":large_blue_diamond:", "🔷"}, - {":small_orange_diamond:", "🔸"}, - {":small_blue_diamond:", "🔹"}, - {":small_red_triangle:", "🔺"}, - {":small_red_triangle_down:", "🔻"}, - {":diamond_shape_with_a_dot_inside:", "💠"}, - {":radio_button:", "🔘"}, - {":white_square_button:", "🔳"}, - {":black_square_button:", "🔲"}, - {":checkered_flag:", "🏁"}, - {":triangular_flag_on_post:", "🚩"}, - {":crossed_flags:", "🎌"}, - {":black_flag:", "🏴"}, - {":white_flag:", "🏳️"}, - {":rainbow_flag:", "🏳️‍🌈"}, - {":transgender_flag:", "🏳️‍⚧️"}, - {":pirate_flag:", "🏴‍☠️"}, - {":ascension_island:", "🇦🇨"}, - {":andorra:", "🇦🇩"}, - {":united_arab_emirates:", "🇦🇪"}, - {":afghanistan:", "🇦🇫"}, - {":antigua_barbuda:", "🇦🇬"}, - {":anguilla:", "🇦🇮"}, - {":albania:", "🇦🇱"}, - {":armenia:", "🇦🇲"}, - {":angola:", "🇦🇴"}, - {":antarctica:", "🇦🇶"}, - {":argentina:", "🇦🇷"}, - {":american_samoa:", "🇦🇸"}, - {":austria:", "🇦🇹"}, - {":australia:", "🇦🇺"}, - {":aruba:", "🇦🇼"}, - {":aland_islands:", "🇦🇽"}, - {":azerbaijan:", "🇦🇿"}, - {":bosnia_herzegovina:", "🇧🇦"}, - {":barbados:", "🇧🇧"}, - {":bangladesh:", "🇧🇩"}, - {":belgium:", "🇧🇪"}, - {":burkina_faso:", "🇧🇫"}, - {":bulgaria:", "🇧🇬"}, - {":bahrain:", "🇧🇭"}, - {":burundi:", "🇧🇮"}, - {":benin:", "🇧🇯"}, - {":st_barthelemy:", "🇧🇱"}, - {":bermuda:", "🇧🇲"}, - {":brunei:", "🇧🇳"}, - {":bolivia:", "🇧🇴"}, - {":caribbean_netherlands:", "🇧🇶"}, - {":brazil:", "🇧🇷"}, - {":bahamas:", "🇧🇸"}, - {":bhutan:", "🇧🇹"}, - {":bouvet_island:", "🇧🇻"}, - {":botswana:", "🇧🇼"}, - {":belarus:", "🇧🇾"}, - {":belize:", "🇧🇿"}, - {":canada:", "🇨🇦"}, - {":cocos_islands:", "🇨🇨"}, - {":congo_kinshasa:", "🇨🇩"}, - {":central_african_republic:", "🇨🇫"}, - {":congo_brazzaville:", "🇨🇬"}, - {":switzerland:", "🇨🇭"}, - {":cote_divoire:", "🇨🇮"}, - {":cook_islands:", "🇨🇰"}, - {":chile:", "🇨🇱"}, - {":cameroon:", "🇨🇲"}, - {":cn:", "🇨🇳"}, - {":colombia:", "🇨🇴"}, - {":clipperton_island:", "🇨🇵"}, - {":costa_rica:", "🇨🇷"}, - {":cuba:", "🇨🇺"}, - {":cape_verde:", "🇨🇻"}, - {":curacao:", "🇨🇼"}, - {":christmas_island:", "🇨🇽"}, - {":cyprus:", "🇨🇾"}, - {":czech_republic:", "🇨🇿"}, - {":de:", "🇩🇪"}, - {":diego_garcia:", "🇩🇬"}, - {":djibouti:", "🇩🇯"}, - {":denmark:", "🇩🇰"}, - {":dominica:", "🇩🇲"}, - {":dominican_republic:", "🇩🇴"}, - {":algeria:", "🇩🇿"}, - {":ceuta_melilla:", "🇪🇦"}, - {":ecuador:", "🇪🇨"}, - {":estonia:", "🇪🇪"}, - {":egypt:", "🇪🇬"}, - {":western_sahara:", "🇪🇭"}, - {":eritrea:", "🇪🇷"}, - {":es:", "🇪🇸"}, - {":ethiopia:", "🇪🇹"}, - {":eu:", "🇪🇺"}, - {":european_union:", "🇪🇺"}, - {":finland:", "🇫🇮"}, - {":fiji:", "🇫🇯"}, - {":falkland_islands:", "🇫🇰"}, - {":micronesia:", "🇫🇲"}, - {":faroe_islands:", "🇫🇴"}, - {":fr:", "🇫🇷"}, - {":gabon:", "🇬🇦"}, - {":gb:", "🇬🇧"}, - {":uk:", "🇬🇧"}, - {":grenada:", "🇬🇩"}, - {":georgia:", "🇬🇪"}, - {":french_guiana:", "🇬🇫"}, - {":guernsey:", "🇬🇬"}, - {":ghana:", "🇬🇭"}, - {":gibraltar:", "🇬🇮"}, - {":greenland:", "🇬🇱"}, - {":gambia:", "🇬🇲"}, - {":guinea:", "🇬🇳"}, - {":guadeloupe:", "🇬🇵"}, - {":equatorial_guinea:", "🇬🇶"}, - {":greece:", "🇬🇷"}, - {":south_georgia_south_sandwich_islands:", "🇬🇸"}, - {":guatemala:", "🇬🇹"}, - {":guam:", "🇬🇺"}, - {":guinea_bissau:", "🇬🇼"}, - {":guyana:", "🇬🇾"}, - {":hong_kong:", "🇭🇰"}, - {":heard_mcdonald_islands:", "🇭🇲"}, - {":honduras:", "🇭🇳"}, - {":croatia:", "🇭🇷"}, - {":haiti:", "🇭🇹"}, - {":hungary:", "🇭🇺"}, - {":canary_islands:", "🇮🇨"}, - {":indonesia:", "🇮🇩"}, - {":ireland:", "🇮🇪"}, - {":israel:", "🇮🇱"}, - {":isle_of_man:", "🇮🇲"}, - {":india:", "🇮🇳"}, - {":british_indian_ocean_territory:", "🇮🇴"}, - {":iraq:", "🇮🇶"}, - {":iran:", "🇮🇷"}, - {":iceland:", "🇮🇸"}, - {":it:", "🇮🇹"}, - {":jersey:", "🇯🇪"}, - {":jamaica:", "🇯🇲"}, - {":jordan:", "🇯🇴"}, - {":jp:", "🇯🇵"}, - {":kenya:", "🇰🇪"}, - {":kyrgyzstan:", "🇰🇬"}, - {":cambodia:", "🇰🇭"}, - {":kiribati:", "🇰🇮"}, - {":comoros:", "🇰🇲"}, - {":st_kitts_nevis:", "🇰🇳"}, - {":north_korea:", "🇰🇵"}, - {":kr:", "🇰🇷"}, - {":kuwait:", "🇰🇼"}, - {":cayman_islands:", "🇰🇾"}, - {":kazakhstan:", "🇰🇿"}, - {":laos:", "🇱🇦"}, - {":lebanon:", "🇱🇧"}, - {":st_lucia:", "🇱🇨"}, - {":liechtenstein:", "🇱🇮"}, - {":sri_lanka:", "🇱🇰"}, - {":liberia:", "🇱🇷"}, - {":lesotho:", "🇱🇸"}, - {":lithuania:", "🇱🇹"}, - {":luxembourg:", "🇱🇺"}, - {":latvia:", "🇱🇻"}, - {":libya:", "🇱🇾"}, - {":morocco:", "🇲🇦"}, - {":monaco:", "🇲🇨"}, - {":moldova:", "🇲🇩"}, - {":montenegro:", "🇲🇪"}, - {":st_martin:", "🇲🇫"}, - {":madagascar:", "🇲🇬"}, - {":marshall_islands:", "🇲🇭"}, - {":macedonia:", "🇲🇰"}, - {":mali:", "🇲🇱"}, - {":myanmar:", "🇲🇲"}, - {":mongolia:", "🇲🇳"}, - {":macau:", "🇲🇴"}, - {":northern_mariana_islands:", "🇲🇵"}, - {":martinique:", "🇲🇶"}, - {":mauritania:", "🇲🇷"}, - {":montserrat:", "🇲🇸"}, - {":malta:", "🇲🇹"}, - {":mauritius:", "🇲🇺"}, - {":maldives:", "🇲🇻"}, - {":malawi:", "🇲🇼"}, - {":mexico:", "🇲🇽"}, - {":malaysia:", "🇲🇾"}, - {":mozambique:", "🇲🇿"}, - {":namibia:", "🇳🇦"}, - {":new_caledonia:", "🇳🇨"}, - {":niger:", "🇳🇪"}, - {":norfolk_island:", "🇳🇫"}, - {":nigeria:", "🇳🇬"}, - {":nicaragua:", "🇳🇮"}, - {":netherlands:", "🇳🇱"}, - {":norway:", "🇳🇴"}, - {":nepal:", "🇳🇵"}, - {":nauru:", "🇳🇷"}, - {":niue:", "🇳🇺"}, - {":new_zealand:", "🇳🇿"}, - {":oman:", "🇴🇲"}, - {":panama:", "🇵🇦"}, - {":peru:", "🇵🇪"}, - {":french_polynesia:", "🇵🇫"}, - {":papua_new_guinea:", "🇵🇬"}, - {":philippines:", "🇵🇭"}, - {":pakistan:", "🇵🇰"}, - {":poland:", "🇵🇱"}, - {":st_pierre_miquelon:", "🇵🇲"}, - {":pitcairn_islands:", "🇵🇳"}, - {":puerto_rico:", "🇵🇷"}, - {":palestinian_territories:", "🇵🇸"}, - {":portugal:", "🇵🇹"}, - {":palau:", "🇵🇼"}, - {":paraguay:", "🇵🇾"}, - {":qatar:", "🇶🇦"}, - {":reunion:", "🇷🇪"}, - {":romania:", "🇷🇴"}, - {":serbia:", "🇷🇸"}, - {":ru:", "🇷🇺"}, - {":rwanda:", "🇷🇼"}, - {":saudi_arabia:", "🇸🇦"}, - {":solomon_islands:", "🇸🇧"}, - {":seychelles:", "🇸🇨"}, - {":sudan:", "🇸🇩"}, - {":sweden:", "🇸🇪"}, - {":singapore:", "🇸🇬"}, - {":st_helena:", "🇸🇭"}, - {":slovenia:", "🇸🇮"}, - {":svalbard_jan_mayen:", "🇸🇯"}, - {":slovakia:", "🇸🇰"}, - {":sierra_leone:", "🇸🇱"}, - {":san_marino:", "🇸🇲"}, - {":senegal:", "🇸🇳"}, - {":somalia:", "🇸🇴"}, - {":suriname:", "🇸🇷"}, - {":south_sudan:", "🇸🇸"}, - {":sao_tome_principe:", "🇸🇹"}, - {":el_salvador:", "🇸🇻"}, - {":sint_maarten:", "🇸🇽"}, - {":syria:", "🇸🇾"}, - {":swaziland:", "🇸🇿"}, - {":tristan_da_cunha:", "🇹🇦"}, - {":turks_caicos_islands:", "🇹🇨"}, - {":chad:", "🇹🇩"}, - {":french_southern_territories:", "🇹🇫"}, - {":togo:", "🇹🇬"}, - {":thailand:", "🇹🇭"}, - {":tajikistan:", "🇹🇯"}, - {":tokelau:", "🇹🇰"}, - {":timor_leste:", "🇹🇱"}, - {":turkmenistan:", "🇹🇲"}, - {":tunisia:", "🇹🇳"}, - {":tonga:", "🇹🇴"}, - {":tr:", "🇹🇷"}, - {":trinidad_tobago:", "🇹🇹"}, - {":tuvalu:", "🇹🇻"}, - {":taiwan:", "🇹🇼"}, - {":tanzania:", "🇹🇿"}, - {":ukraine:", "🇺🇦"}, - {":uganda:", "🇺🇬"}, - {":us_outlying_islands:", "🇺🇲"}, - {":united_nations:", "🇺🇳"}, - {":us:", "🇺🇸"}, - {":uruguay:", "🇺🇾"}, - {":uzbekistan:", "🇺🇿"}, - {":vatican_city:", "🇻🇦"}, - {":st_vincent_grenadines:", "🇻🇨"}, - {":venezuela:", "🇻🇪"}, - {":british_virgin_islands:", "🇻🇬"}, - {":us_virgin_islands:", "🇻🇮"}, - {":vietnam:", "🇻🇳"}, - {":vanuatu:", "🇻🇺"}, - {":wallis_futuna:", "🇼🇫"}, - {":samoa:", "🇼🇸"}, - {":kosovo:", "🇽🇰"}, - {":yemen:", "🇾🇪"}, - {":mayotte:", "🇾🇹"}, - {":south_africa:", "🇿🇦"}, - {":zambia:", "🇿🇲"}, - {":zimbabwe:", "🇿🇼"}, - {":england:", "🏴󠁧󠁢󠁥󠁮󠁧󠁿"}, - {":scotland:", "🏴󠁧󠁢󠁳󠁣󠁴󠁿"}, - {":wales:", "🏴󠁧󠁢󠁷󠁬󠁳󠁿"}, + {":grinning:", "\xf0\x9f\x98\x80"}, // 😀 + {":smiley:", "\xf0\x9f\x98\x83"}, // 😃 + {":smile:", "\xf0\x9f\x98\x84"}, // 😄 + {":grin:", "\xf0\x9f\x98\x81"}, // 😁 + {":laughing:", "\xf0\x9f\x98\x86"}, // 😆 + {":satisfied:", "\xf0\x9f\x98\x86"}, // 😆 + {":sweat_smile:", "\xf0\x9f\x98\x85"}, // 😅 + {":rofl:", "\xf0\x9f\xa4\xa3"}, // 🤣 + {":joy:", "\xf0\x9f\x98\x82"}, // 😂 + {":slightly_smiling_face:", "\xf0\x9f\x99\x82"}, // 🙂 + {":upside_down_face:", "\xf0\x9f\x99\x83"}, // 🙃 + {":wink:", "\xf0\x9f\x98\x89"}, // 😉 + {":blush:", "\xf0\x9f\x98\x8a"}, // 😊 + {":innocent:", "\xf0\x9f\x98\x87"}, // 😇 + {":smiling_face_with_three_hearts:", "\xf0\x9f\xa5\xb0"}, // 🥰 + {":heart_eyes:", "\xf0\x9f\x98\x8d"}, // 😍 + {":star_struck:", "\xf0\x9f\xa4\xa9"}, // 🤩 + {":kissing_heart:", "\xf0\x9f\x98\x98"}, // 😘 + {":kissing:", "\xf0\x9f\x98\x97"}, // 😗 + {":relaxed:", "\xe2\x98\xba\xef\xb8\x8f"}, // ☺️ + {":kissing_closed_eyes:", "\xf0\x9f\x98\x9a"}, // 😚 + {":kissing_smiling_eyes:", "\xf0\x9f\x98\x99"}, // 😙 + {":smiling_face_with_tear:", "\xf0\x9f\xa5\xb2"}, // 🥲 + {":yum:", "\xf0\x9f\x98\x8b"}, // 😋 + {":stuck_out_tongue:", "\xf0\x9f\x98\x9b"}, // 😛 + {":stuck_out_tongue_winking_eye:", "\xf0\x9f\x98\x9c"}, // 😜 + {":zany_face:", "\xf0\x9f\xa4\xaa"}, // 🤪 + {":stuck_out_tongue_closed_eyes:", "\xf0\x9f\x98\x9d"}, // 😝 + {":money_mouth_face:", "\xf0\x9f\xa4\x91"}, // 🤑 + {":hugs:", "\xf0\x9f\xa4\x97"}, // 🤗 + {":hand_over_mouth:", "\xf0\x9f\xa4\xad"}, // 🤭 + {":shushing_face:", "\xf0\x9f\xa4\xab"}, // 🤫 + {":thinking:", "\xf0\x9f\xa4\x94"}, // 🤔 + {":zipper_mouth_face:", "\xf0\x9f\xa4\x90"}, // 🤐 + {":raised_eyebrow:", "\xf0\x9f\xa4\xa8"}, // 🤨 + {":neutral_face:", "\xf0\x9f\x98\x90"}, // 😐 + {":expressionless:", "\xf0\x9f\x98\x91"}, // 😑 + {":no_mouth:", "\xf0\x9f\x98\xb6"}, // 😶 + {":smirk:", "\xf0\x9f\x98\x8f"}, // 😏 + {":unamused:", "\xf0\x9f\x98\x92"}, // 😒 + {":roll_eyes:", "\xf0\x9f\x99\x84"}, // 🙄 + {":grimacing:", "\xf0\x9f\x98\xac"}, // 😬 + {":lying_face:", "\xf0\x9f\xa4\xa5"}, // 🤥 + {":relieved:", "\xf0\x9f\x98\x8c"}, // 😌 + {":pensive:", "\xf0\x9f\x98\x94"}, // 😔 + {":sleepy:", "\xf0\x9f\x98\xaa"}, // 😪 + {":drooling_face:", "\xf0\x9f\xa4\xa4"}, // 🤤 + {":sleeping:", "\xf0\x9f\x98\xb4"}, // 😴 + {":mask:", "\xf0\x9f\x98\xb7"}, // 😷 + {":face_with_thermometer:", "\xf0\x9f\xa4\x92"}, // 🤒 + {":face_with_head_bandage:", "\xf0\x9f\xa4\x95"}, // 🤕 + {":nauseated_face:", "\xf0\x9f\xa4\xa2"}, // 🤢 + {":vomiting_face:", "\xf0\x9f\xa4\xae"}, // 🤮 + {":sneezing_face:", "\xf0\x9f\xa4\xa7"}, // 🤧 + {":hot_face:", "\xf0\x9f\xa5\xb5"}, // 🥵 + {":cold_face:", "\xf0\x9f\xa5\xb6"}, // 🥶 + {":woozy_face:", "\xf0\x9f\xa5\xb4"}, // 🥴 + {":dizzy_face:", "\xf0\x9f\x98\xb5"}, // 😵 + {":exploding_head:", "\xf0\x9f\xa4\xaf"}, // 🤯 + {":cowboy_hat_face:", "\xf0\x9f\xa4\xa0"}, // 🤠 + {":partying_face:", "\xf0\x9f\xa5\xb3"}, // 🥳 + {":disguised_face:", "\xf0\x9f\xa5\xb8"}, // 🥸 + {":sunglasses:", "\xf0\x9f\x98\x8e"}, // 😎 + {":nerd_face:", "\xf0\x9f\xa4\x93"}, // 🤓 + {":monocle_face:", "\xf0\x9f\xa7\x90"}, // 🧐 + {":confused:", "\xf0\x9f\x98\x95"}, // 😕 + {":worried:", "\xf0\x9f\x98\x9f"}, // 😟 + {":slightly_frowning_face:", "\xf0\x9f\x99\x81"}, // 🙁 + {":frowning_face:", "\xe2\x98\xb9\xef\xb8\x8f"}, // ☹️ + {":open_mouth:", "\xf0\x9f\x98\xae"}, // 😮 + {":hushed:", "\xf0\x9f\x98\xaf"}, // 😯 + {":astonished:", "\xf0\x9f\x98\xb2"}, // 😲 + {":flushed:", "\xf0\x9f\x98\xb3"}, // 😳 + {":pleading_face:", "\xf0\x9f\xa5\xba"}, // 🥺 + {":frowning:", "\xf0\x9f\x98\xa6"}, // 😦 + {":anguished:", "\xf0\x9f\x98\xa7"}, // 😧 + {":fearful:", "\xf0\x9f\x98\xa8"}, // 😨 + {":cold_sweat:", "\xf0\x9f\x98\xb0"}, // 😰 + {":disappointed_relieved:", "\xf0\x9f\x98\xa5"}, // 😥 + {":cry:", "\xf0\x9f\x98\xa2"}, // 😢 + {":sob:", "\xf0\x9f\x98\xad"}, // 😭 + {":scream:", "\xf0\x9f\x98\xb1"}, // 😱 + {":confounded:", "\xf0\x9f\x98\x96"}, // 😖 + {":persevere:", "\xf0\x9f\x98\xa3"}, // 😣 + {":disappointed:", "\xf0\x9f\x98\x9e"}, // 😞 + {":sweat:", "\xf0\x9f\x98\x93"}, // 😓 + {":weary:", "\xf0\x9f\x98\xa9"}, // 😩 + {":tired_face:", "\xf0\x9f\x98\xab"}, // 😫 + {":yawning_face:", "\xf0\x9f\xa5\xb1"}, // 🥱 + {":triumph:", "\xf0\x9f\x98\xa4"}, // 😤 + {":rage:", "\xf0\x9f\x98\xa1"}, // 😡 + {":pout:", "\xf0\x9f\x98\xa1"}, // 😡 + {":angry:", "\xf0\x9f\x98\xa0"}, // 😠 + {":cursing_face:", "\xf0\x9f\xa4\xac"}, // 🤬 + {":smiling_imp:", "\xf0\x9f\x98\x88"}, // 😈 + {":imp:", "\xf0\x9f\x91\xbf"}, // 👿 + {":skull:", "\xf0\x9f\x92\x80"}, // 💀 + {":skull_and_crossbones:", "\xe2\x98\xa0\xef\xb8\x8f"}, // ☠️ + {":hankey:", "\xf0\x9f\x92\xa9"}, // 💩 + {":poop:", "\xf0\x9f\x92\xa9"}, // 💩 + {":shit:", "\xf0\x9f\x92\xa9"}, // 💩 + {":clown_face:", "\xf0\x9f\xa4\xa1"}, // 🤡 + {":japanese_ogre:", "\xf0\x9f\x91\xb9"}, // 👹 + {":japanese_goblin:", "\xf0\x9f\x91\xba"}, // 👺 + {":ghost:", "\xf0\x9f\x91\xbb"}, // 👻 + {":alien:", "\xf0\x9f\x91\xbd"}, // 👽 + {":space_invader:", "\xf0\x9f\x91\xbe"}, // 👾 + {":robot:", "\xf0\x9f\xa4\x96"}, // 🤖 + {":smiley_cat:", "\xf0\x9f\x98\xba"}, // 😺 + {":smile_cat:", "\xf0\x9f\x98\xb8"}, // 😸 + {":joy_cat:", "\xf0\x9f\x98\xb9"}, // 😹 + {":heart_eyes_cat:", "\xf0\x9f\x98\xbb"}, // 😻 + {":smirk_cat:", "\xf0\x9f\x98\xbc"}, // 😼 + {":kissing_cat:", "\xf0\x9f\x98\xbd"}, // 😽 + {":scream_cat:", "\xf0\x9f\x99\x80"}, // 🙀 + {":crying_cat_face:", "\xf0\x9f\x98\xbf"}, // 😿 + {":pouting_cat:", "\xf0\x9f\x98\xbe"}, // 😾 + {":see_no_evil:", "\xf0\x9f\x99\x88"}, // 🙈 + {":hear_no_evil:", "\xf0\x9f\x99\x89"}, // 🙉 + {":speak_no_evil:", "\xf0\x9f\x99\x8a"}, // 🙊 + {":kiss:", "\xf0\x9f\x92\x8b"}, // 💋 + {":love_letter:", "\xf0\x9f\x92\x8c"}, // 💌 + {":cupid:", "\xf0\x9f\x92\x98"}, // 💘 + {":gift_heart:", "\xf0\x9f\x92\x9d"}, // 💝 + {":sparkling_heart:", "\xf0\x9f\x92\x96"}, // 💖 + {":heartpulse:", "\xf0\x9f\x92\x97"}, // 💗 + {":heartbeat:", "\xf0\x9f\x92\x93"}, // 💓 + {":revolving_hearts:", "\xf0\x9f\x92\x9e"}, // 💞 + {":two_hearts:", "\xf0\x9f\x92\x95"}, // 💕 + {":heart_decoration:", "\xf0\x9f\x92\x9f"}, // 💟 + {":heavy_heart_exclamation:", "\xe2\x9d\xa3\xef\xb8\x8f"}, // ❣️ + {":broken_heart:", "\xf0\x9f\x92\x94"}, // 💔 + {":heart:", "\xe2\x9d\xa4\xef\xb8\x8f"}, // ❤️ + {":orange_heart:", "\xf0\x9f\xa7\xa1"}, // 🧡 + {":yellow_heart:", "\xf0\x9f\x92\x9b"}, // 💛 + {":green_heart:", "\xf0\x9f\x92\x9a"}, // 💚 + {":blue_heart:", "\xf0\x9f\x92\x99"}, // 💙 + {":purple_heart:", "\xf0\x9f\x92\x9c"}, // 💜 + {":brown_heart:", "\xf0\x9f\xa4\x8e"}, // 🤎 + {":black_heart:", "\xf0\x9f\x96\xa4"}, // 🖤 + {":white_heart:", "\xf0\x9f\xa4\x8d"}, // 🤍 + {":100:", "\xf0\x9f\x92\xaf"}, // 💯 + {":anger:", "\xf0\x9f\x92\xa2"}, // 💢 + {":boom:", "\xf0\x9f\x92\xa5"}, // 💥 + {":collision:", "\xf0\x9f\x92\xa5"}, // 💥 + {":dizzy:", "\xf0\x9f\x92\xab"}, // 💫 + {":sweat_drops:", "\xf0\x9f\x92\xa6"}, // 💦 + {":dash:", "\xf0\x9f\x92\xa8"}, // 💨 + {":hole:", "\xf0\x9f\x95\xb3\xef\xb8\x8f"}, // 🕳️ + {":bomb:", "\xf0\x9f\x92\xa3"}, // 💣 + {":speech_balloon:", "\xf0\x9f\x92\xac"}, // 💬 + {":eye_speech_bubble:", "\xf0\x9f\x91\x81\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x97\xa8\xef\xb8\x8f"}, // 👁️‍🗨️ + {":left_speech_bubble:", "\xf0\x9f\x97\xa8\xef\xb8\x8f"}, // 🗨️ + {":right_anger_bubble:", "\xf0\x9f\x97\xaf\xef\xb8\x8f"}, // 🗯️ + {":thought_balloon:", "\xf0\x9f\x92\xad"}, // 💭 + {":zzz:", "\xf0\x9f\x92\xa4"}, // 💤 + {":wave:", "\xf0\x9f\x91\x8b"}, // 👋 + {":raised_back_of_hand:", "\xf0\x9f\xa4\x9a"}, // 🤚 + {":raised_hand_with_fingers_splayed:", "\xf0\x9f\x96\x90\xef\xb8\x8f"}, // 🖐️ + {":hand:", "\xe2\x9c\x8b"}, // ✋ + {":raised_hand:", "\xe2\x9c\x8b"}, // ✋ + {":vulcan_salute:", "\xf0\x9f\x96\x96"}, // 🖖 + {":ok_hand:", "\xf0\x9f\x91\x8c"}, // 👌 + {":pinched_fingers:", "\xf0\x9f\xa4\x8c"}, // 🤌 + {":pinching_hand:", "\xf0\x9f\xa4\x8f"}, // 🤏 + {":v:", "\xe2\x9c\x8c\xef\xb8\x8f"}, // ✌️ + {":crossed_fingers:", "\xf0\x9f\xa4\x9e"}, // 🤞 + {":love_you_gesture:", "\xf0\x9f\xa4\x9f"}, // 🤟 + {":metal:", "\xf0\x9f\xa4\x98"}, // 🤘 + {":call_me_hand:", "\xf0\x9f\xa4\x99"}, // 🤙 + {":point_left:", "\xf0\x9f\x91\x88"}, // 👈 + {":point_right:", "\xf0\x9f\x91\x89"}, // 👉 + {":point_up_2:", "\xf0\x9f\x91\x86"}, // 👆 + {":middle_finger:", "\xf0\x9f\x96\x95"}, // 🖕 + {":fu:", "\xf0\x9f\x96\x95"}, // 🖕 + {":point_down:", "\xf0\x9f\x91\x87"}, // 👇 + {":point_up:", "\xe2\x98\x9d\xef\xb8\x8f"}, // ☝️ + {":+1:", "\xf0\x9f\x91\x8d"}, // 👍 + {":thumbsup:", "\xf0\x9f\x91\x8d"}, // 👍 + {":-1:", "\xf0\x9f\x91\x8e"}, // 👎 + {":thumbsdown:", "\xf0\x9f\x91\x8e"}, // 👎 + {":fist_raised:", "\xe2\x9c\x8a"}, // ✊ + {":fist:", "\xe2\x9c\x8a"}, // ✊ + {":fist_oncoming:", "\xf0\x9f\x91\x8a"}, // 👊 + {":facepunch:", "\xf0\x9f\x91\x8a"}, // 👊 + {":punch:", "\xf0\x9f\x91\x8a"}, // 👊 + {":fist_left:", "\xf0\x9f\xa4\x9b"}, // 🤛 + {":fist_right:", "\xf0\x9f\xa4\x9c"}, // 🤜 + {":clap:", "\xf0\x9f\x91\x8f"}, // 👏 + {":raised_hands:", "\xf0\x9f\x99\x8c"}, // 🙌 + {":open_hands:", "\xf0\x9f\x91\x90"}, // 👐 + {":palms_up_together:", "\xf0\x9f\xa4\xb2"}, // 🤲 + {":handshake:", "\xf0\x9f\xa4\x9d"}, // 🤝 + {":pray:", "\xf0\x9f\x99\x8f"}, // 🙏 + {":writing_hand:", "\xe2\x9c\x8d\xef\xb8\x8f"}, // ✍️ + {":nail_care:", "\xf0\x9f\x92\x85"}, // 💅 + {":selfie:", "\xf0\x9f\xa4\xb3"}, // 🤳 + {":muscle:", "\xf0\x9f\x92\xaa"}, // 💪 + {":mechanical_arm:", "\xf0\x9f\xa6\xbe"}, // 🦾 + {":mechanical_leg:", "\xf0\x9f\xa6\xbf"}, // 🦿 + {":leg:", "\xf0\x9f\xa6\xb5"}, // 🦵 + {":foot:", "\xf0\x9f\xa6\xb6"}, // 🦶 + {":ear:", "\xf0\x9f\x91\x82"}, // 👂 + {":ear_with_hearing_aid:", "\xf0\x9f\xa6\xbb"}, // 🦻 + {":nose:", "\xf0\x9f\x91\x83"}, // 👃 + {":brain:", "\xf0\x9f\xa7\xa0"}, // 🧠 + {":anatomical_heart:", "\xf0\x9f\xab\x80"}, // 🫀 + {":lungs:", "\xf0\x9f\xab\x81"}, // 🫁 + {":tooth:", "\xf0\x9f\xa6\xb7"}, // 🦷 + {":bone:", "\xf0\x9f\xa6\xb4"}, // 🦴 + {":eyes:", "\xf0\x9f\x91\x80"}, // 👀 + {":eye:", "\xf0\x9f\x91\x81\xef\xb8\x8f"}, // 👁️ + {":tongue:", "\xf0\x9f\x91\x85"}, // 👅 + {":lips:", "\xf0\x9f\x91\x84"}, // 👄 + {":baby:", "\xf0\x9f\x91\xb6"}, // 👶 + {":child:", "\xf0\x9f\xa7\x92"}, // 🧒 + {":boy:", "\xf0\x9f\x91\xa6"}, // 👦 + {":girl:", "\xf0\x9f\x91\xa7"}, // 👧 + {":adult:", "\xf0\x9f\xa7\x91"}, // 🧑 + {":blond_haired_person:", "\xf0\x9f\x91\xb1"}, // 👱 + {":man:", "\xf0\x9f\x91\xa8"}, // 👨 + {":bearded_person:", "\xf0\x9f\xa7\x94"}, // 🧔 + {":red_haired_man:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xb0"}, // 👨‍🦰 + {":curly_haired_man:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xb1"}, // 👨‍🦱 + {":white_haired_man:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xb3"}, // 👨‍🦳 + {":bald_man:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xb2"}, // 👨‍🦲 + {":woman:", "\xf0\x9f\x91\xa9"}, // 👩 + {":red_haired_woman:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xb0"}, // 👩‍🦰 + {":person_red_hair:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xb0"}, // 🧑‍🦰 + {":curly_haired_woman:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xb1"}, // 👩‍🦱 + {":person_curly_hair:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xb1"}, // 🧑‍🦱 + {":white_haired_woman:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xb3"}, // 👩‍🦳 + {":person_white_hair:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xb3"}, // 🧑‍🦳 + {":bald_woman:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xb2"}, // 👩‍🦲 + {":person_bald:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xb2"}, // 🧑‍🦲 + {":blond_haired_woman:", "\xf0\x9f\x91\xb1\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 👱‍♀️ + {":blonde_woman:", "\xf0\x9f\x91\xb1\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 👱‍♀️ + {":blond_haired_man:", "\xf0\x9f\x91\xb1\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 👱‍♂️ + {":older_adult:", "\xf0\x9f\xa7\x93"}, // 🧓 + {":older_man:", "\xf0\x9f\x91\xb4"}, // 👴 + {":older_woman:", "\xf0\x9f\x91\xb5"}, // 👵 + {":frowning_person:", "\xf0\x9f\x99\x8d"}, // 🙍 + {":frowning_man:", "\xf0\x9f\x99\x8d\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🙍‍♂️ + {":frowning_woman:", "\xf0\x9f\x99\x8d\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🙍‍♀️ + {":pouting_face:", "\xf0\x9f\x99\x8e"}, // 🙎 + {":pouting_man:", "\xf0\x9f\x99\x8e\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🙎‍♂️ + {":pouting_woman:", "\xf0\x9f\x99\x8e\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🙎‍♀️ + {":no_good:", "\xf0\x9f\x99\x85"}, // 🙅 + {":no_good_man:", "\xf0\x9f\x99\x85\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🙅‍♂️ + {":ng_man:", "\xf0\x9f\x99\x85\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🙅‍♂️ + {":no_good_woman:", "\xf0\x9f\x99\x85\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🙅‍♀️ + {":ng_woman:", "\xf0\x9f\x99\x85\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🙅‍♀️ + {":ok_person:", "\xf0\x9f\x99\x86"}, // 🙆 + {":ok_man:", "\xf0\x9f\x99\x86\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🙆‍♂️ + {":ok_woman:", "\xf0\x9f\x99\x86\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🙆‍♀️ + {":tipping_hand_person:", "\xf0\x9f\x92\x81"}, // 💁 + {":information_desk_person:", "\xf0\x9f\x92\x81"}, // 💁 + {":tipping_hand_man:", "\xf0\x9f\x92\x81\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 💁‍♂️ + {":sassy_man:", "\xf0\x9f\x92\x81\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 💁‍♂️ + {":tipping_hand_woman:", "\xf0\x9f\x92\x81\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 💁‍♀️ + {":sassy_woman:", "\xf0\x9f\x92\x81\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 💁‍♀️ + {":raising_hand:", "\xf0\x9f\x99\x8b"}, // 🙋 + {":raising_hand_man:", "\xf0\x9f\x99\x8b\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🙋‍♂️ + {":raising_hand_woman:", "\xf0\x9f\x99\x8b\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🙋‍♀️ + {":deaf_person:", "\xf0\x9f\xa7\x8f"}, // 🧏 + {":deaf_man:", "\xf0\x9f\xa7\x8f\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧏‍♂️ + {":deaf_woman:", "\xf0\x9f\xa7\x8f\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧏‍♀️ + {":bow:", "\xf0\x9f\x99\x87"}, // 🙇 + {":bowing_man:", "\xf0\x9f\x99\x87\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🙇‍♂️ + {":bowing_woman:", "\xf0\x9f\x99\x87\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🙇‍♀️ + {":facepalm:", "\xf0\x9f\xa4\xa6"}, // 🤦 + {":man_facepalming:", "\xf0\x9f\xa4\xa6\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🤦‍♂️ + {":woman_facepalming:", "\xf0\x9f\xa4\xa6\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🤦‍♀️ + {":shrug:", "\xf0\x9f\xa4\xb7"}, // 🤷 + {":man_shrugging:", "\xf0\x9f\xa4\xb7\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🤷‍♂️ + {":woman_shrugging:", "\xf0\x9f\xa4\xb7\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🤷‍♀️ + {":health_worker:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xe2\x9a\x95\xef\xb8\x8f"}, // 🧑‍⚕️ + {":man_health_worker:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9a\x95\xef\xb8\x8f"}, // 👨‍⚕️ + {":woman_health_worker:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9a\x95\xef\xb8\x8f"}, // 👩‍⚕️ + {":student:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8e\x93"}, // 🧑‍🎓 + {":man_student:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8e\x93"}, // 👨‍🎓 + {":woman_student:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8e\x93"}, // 👩‍🎓 + {":teacher:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8f\xab"}, // 🧑‍🏫 + {":man_teacher:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8f\xab"}, // 👨‍🏫 + {":woman_teacher:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8f\xab"}, // 👩‍🏫 + {":judge:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xe2\x9a\x96\xef\xb8\x8f"}, // 🧑‍⚖️ + {":man_judge:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9a\x96\xef\xb8\x8f"}, // 👨‍⚖️ + {":woman_judge:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9a\x96\xef\xb8\x8f"}, // 👩‍⚖️ + {":farmer:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8c\xbe"}, // 🧑‍🌾 + {":man_farmer:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8c\xbe"}, // 👨‍🌾 + {":woman_farmer:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8c\xbe"}, // 👩‍🌾 + {":cook:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8d\xb3"}, // 🧑‍🍳 + {":man_cook:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8d\xb3"}, // 👨‍🍳 + {":woman_cook:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8d\xb3"}, // 👩‍🍳 + {":mechanic:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x94\xa7"}, // 🧑‍🔧 + {":man_mechanic:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x94\xa7"}, // 👨‍🔧 + {":woman_mechanic:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x94\xa7"}, // 👩‍🔧 + {":factory_worker:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8f\xad"}, // 🧑‍🏭 + {":man_factory_worker:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8f\xad"}, // 👨‍🏭 + {":woman_factory_worker:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8f\xad"}, // 👩‍🏭 + {":office_worker:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x92\xbc"}, // 🧑‍💼 + {":man_office_worker:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x92\xbc"}, // 👨‍💼 + {":woman_office_worker:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x92\xbc"}, // 👩‍💼 + {":scientist:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x94\xac"}, // 🧑‍🔬 + {":man_scientist:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x94\xac"}, // 👨‍🔬 + {":woman_scientist:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x94\xac"}, // 👩‍🔬 + {":technologist:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x92\xbb"}, // 🧑‍💻 + {":man_technologist:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x92\xbb"}, // 👨‍💻 + {":woman_technologist:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x92\xbb"}, // 👩‍💻 + {":singer:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8e\xa4"}, // 🧑‍🎤 + {":man_singer:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8e\xa4"}, // 👨‍🎤 + {":woman_singer:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8e\xa4"}, // 👩‍🎤 + {":artist:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8e\xa8"}, // 🧑‍🎨 + {":man_artist:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8e\xa8"}, // 👨‍🎨 + {":woman_artist:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8e\xa8"}, // 👩‍🎨 + {":pilot:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xe2\x9c\x88\xef\xb8\x8f"}, // 🧑‍✈️ + {":man_pilot:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9c\x88\xef\xb8\x8f"}, // 👨‍✈️ + {":woman_pilot:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9c\x88\xef\xb8\x8f"}, // 👩‍✈️ + {":astronaut:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x9a\x80"}, // 🧑‍🚀 + {":man_astronaut:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x9a\x80"}, // 👨‍🚀 + {":woman_astronaut:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x9a\x80"}, // 👩‍🚀 + {":firefighter:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x9a\x92"}, // 🧑‍🚒 + {":man_firefighter:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x9a\x92"}, // 👨‍🚒 + {":woman_firefighter:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x9a\x92"}, // 👩‍🚒 + {":police_officer:", "\xf0\x9f\x91\xae"}, // 👮 + {":cop:", "\xf0\x9f\x91\xae"}, // 👮 + {":policeman:", "\xf0\x9f\x91\xae\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 👮‍♂️ + {":policewoman:", "\xf0\x9f\x91\xae\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 👮‍♀️ + {":detective:", "\xf0\x9f\x95\xb5\xef\xb8\x8f"}, // 🕵️ + {":male_detective:", "\xf0\x9f\x95\xb5\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🕵️‍♂️ + {":female_detective:", "\xf0\x9f\x95\xb5\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🕵️‍♀️ + {":guard:", "\xf0\x9f\x92\x82"}, // 💂 + {":guardsman:", "\xf0\x9f\x92\x82\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 💂‍♂️ + {":guardswoman:", "\xf0\x9f\x92\x82\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 💂‍♀️ + {":ninja:", "\xf0\x9f\xa5\xb7"}, // 🥷 + {":construction_worker:", "\xf0\x9f\x91\xb7"}, // 👷 + {":construction_worker_man:", "\xf0\x9f\x91\xb7\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 👷‍♂️ + {":construction_worker_woman:", "\xf0\x9f\x91\xb7\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 👷‍♀️ + {":prince:", "\xf0\x9f\xa4\xb4"}, // 🤴 + {":princess:", "\xf0\x9f\x91\xb8"}, // 👸 + {":person_with_turban:", "\xf0\x9f\x91\xb3"}, // 👳 + {":man_with_turban:", "\xf0\x9f\x91\xb3\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 👳‍♂️ + {":woman_with_turban:", "\xf0\x9f\x91\xb3\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 👳‍♀️ + {":man_with_gua_pi_mao:", "\xf0\x9f\x91\xb2"}, // 👲 + {":woman_with_headscarf:", "\xf0\x9f\xa7\x95"}, // 🧕 + {":person_in_tuxedo:", "\xf0\x9f\xa4\xb5"}, // 🤵 + {":man_in_tuxedo:", "\xf0\x9f\xa4\xb5\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🤵‍♂️ + {":woman_in_tuxedo:", "\xf0\x9f\xa4\xb5\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🤵‍♀️ + {":person_with_veil:", "\xf0\x9f\x91\xb0"}, // 👰 + {":man_with_veil:", "\xf0\x9f\x91\xb0\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 👰‍♂️ + {":woman_with_veil:", "\xf0\x9f\x91\xb0\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 👰‍♀️ + {":bride_with_veil:", "\xf0\x9f\x91\xb0\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 👰‍♀️ + {":pregnant_woman:", "\xf0\x9f\xa4\xb0"}, // 🤰 + {":breast_feeding:", "\xf0\x9f\xa4\xb1"}, // 🤱 + {":woman_feeding_baby:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8d\xbc"}, // 👩‍🍼 + {":man_feeding_baby:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8d\xbc"}, // 👨‍🍼 + {":person_feeding_baby:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8d\xbc"}, // 🧑‍🍼 + {":angel:", "\xf0\x9f\x91\xbc"}, // 👼 + {":santa:", "\xf0\x9f\x8e\x85"}, // 🎅 + {":mrs_claus:", "\xf0\x9f\xa4\xb6"}, // 🤶 + {":mx_claus:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8e\x84"}, // 🧑‍🎄 + {":superhero:", "\xf0\x9f\xa6\xb8"}, // 🦸 + {":superhero_man:", "\xf0\x9f\xa6\xb8\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🦸‍♂️ + {":superhero_woman:", "\xf0\x9f\xa6\xb8\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🦸‍♀️ + {":supervillain:", "\xf0\x9f\xa6\xb9"}, // 🦹 + {":supervillain_man:", "\xf0\x9f\xa6\xb9\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🦹‍♂️ + {":supervillain_woman:", "\xf0\x9f\xa6\xb9\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🦹‍♀️ + {":mage:", "\xf0\x9f\xa7\x99"}, // 🧙 + {":mage_man:", "\xf0\x9f\xa7\x99\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧙‍♂️ + {":mage_woman:", "\xf0\x9f\xa7\x99\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧙‍♀️ + {":fairy:", "\xf0\x9f\xa7\x9a"}, // 🧚 + {":fairy_man:", "\xf0\x9f\xa7\x9a\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧚‍♂️ + {":fairy_woman:", "\xf0\x9f\xa7\x9a\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧚‍♀️ + {":vampire:", "\xf0\x9f\xa7\x9b"}, // 🧛 + {":vampire_man:", "\xf0\x9f\xa7\x9b\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧛‍♂️ + {":vampire_woman:", "\xf0\x9f\xa7\x9b\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧛‍♀️ + {":merperson:", "\xf0\x9f\xa7\x9c"}, // 🧜 + {":merman:", "\xf0\x9f\xa7\x9c\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧜‍♂️ + {":mermaid:", "\xf0\x9f\xa7\x9c\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧜‍♀️ + {":elf:", "\xf0\x9f\xa7\x9d"}, // 🧝 + {":elf_man:", "\xf0\x9f\xa7\x9d\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧝‍♂️ + {":elf_woman:", "\xf0\x9f\xa7\x9d\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧝‍♀️ + {":genie:", "\xf0\x9f\xa7\x9e"}, // 🧞 + {":genie_man:", "\xf0\x9f\xa7\x9e\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧞‍♂️ + {":genie_woman:", "\xf0\x9f\xa7\x9e\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧞‍♀️ + {":zombie:", "\xf0\x9f\xa7\x9f"}, // 🧟 + {":zombie_man:", "\xf0\x9f\xa7\x9f\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧟‍♂️ + {":zombie_woman:", "\xf0\x9f\xa7\x9f\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧟‍♀️ + {":massage:", "\xf0\x9f\x92\x86"}, // 💆 + {":massage_man:", "\xf0\x9f\x92\x86\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 💆‍♂️ + {":massage_woman:", "\xf0\x9f\x92\x86\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 💆‍♀️ + {":haircut:", "\xf0\x9f\x92\x87"}, // 💇 + {":haircut_man:", "\xf0\x9f\x92\x87\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 💇‍♂️ + {":haircut_woman:", "\xf0\x9f\x92\x87\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 💇‍♀️ + {":walking:", "\xf0\x9f\x9a\xb6"}, // 🚶 + {":walking_man:", "\xf0\x9f\x9a\xb6\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🚶‍♂️ + {":walking_woman:", "\xf0\x9f\x9a\xb6\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🚶‍♀️ + {":standing_person:", "\xf0\x9f\xa7\x8d"}, // 🧍 + {":standing_man:", "\xf0\x9f\xa7\x8d\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧍‍♂️ + {":standing_woman:", "\xf0\x9f\xa7\x8d\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧍‍♀️ + {":kneeling_person:", "\xf0\x9f\xa7\x8e"}, // 🧎 + {":kneeling_man:", "\xf0\x9f\xa7\x8e\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧎‍♂️ + {":kneeling_woman:", "\xf0\x9f\xa7\x8e\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧎‍♀️ + {":person_with_probing_cane:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xaf"}, // 🧑‍🦯 + {":man_with_probing_cane:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xaf"}, // 👨‍🦯 + {":woman_with_probing_cane:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xaf"}, // 👩‍🦯 + {":person_in_motorized_wheelchair:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xbc"}, // 🧑‍🦼 + {":man_in_motorized_wheelchair:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xbc"}, // 👨‍🦼 + {":woman_in_motorized_wheelchair:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xbc"}, // 👩‍🦼 + {":person_in_manual_wheelchair:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xbd"}, // 🧑‍🦽 + {":man_in_manual_wheelchair:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xbd"}, // 👨‍🦽 + {":woman_in_manual_wheelchair:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xbd"}, // 👩‍🦽 + {":runner:", "\xf0\x9f\x8f\x83"}, // 🏃 + {":running:", "\xf0\x9f\x8f\x83"}, // 🏃 + {":running_man:", "\xf0\x9f\x8f\x83\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🏃‍♂️ + {":running_woman:", "\xf0\x9f\x8f\x83\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🏃‍♀️ + {":woman_dancing:", "\xf0\x9f\x92\x83"}, // 💃 + {":dancer:", "\xf0\x9f\x92\x83"}, // 💃 + {":man_dancing:", "\xf0\x9f\x95\xba"}, // 🕺 + {":business_suit_levitating:", "\xf0\x9f\x95\xb4\xef\xb8\x8f"}, // 🕴️ + {":dancers:", "\xf0\x9f\x91\xaf"}, // 👯 + {":dancing_men:", "\xf0\x9f\x91\xaf\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 👯‍♂️ + {":dancing_women:", "\xf0\x9f\x91\xaf\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 👯‍♀️ + {":sauna_person:", "\xf0\x9f\xa7\x96"}, // 🧖 + {":sauna_man:", "\xf0\x9f\xa7\x96\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧖‍♂️ + {":sauna_woman:", "\xf0\x9f\xa7\x96\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧖‍♀️ + {":climbing:", "\xf0\x9f\xa7\x97"}, // 🧗 + {":climbing_man:", "\xf0\x9f\xa7\x97\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧗‍♂️ + {":climbing_woman:", "\xf0\x9f\xa7\x97\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧗‍♀️ + {":person_fencing:", "\xf0\x9f\xa4\xba"}, // 🤺 + {":horse_racing:", "\xf0\x9f\x8f\x87"}, // 🏇 + {":skier:", "\xe2\x9b\xb7\xef\xb8\x8f"}, // ⛷️ + {":snowboarder:", "\xf0\x9f\x8f\x82"}, // 🏂 + {":golfing:", "\xf0\x9f\x8f\x8c\xef\xb8\x8f"}, // 🏌️ + {":golfing_man:", "\xf0\x9f\x8f\x8c\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🏌️‍♂️ + {":golfing_woman:", "\xf0\x9f\x8f\x8c\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🏌️‍♀️ + {":surfer:", "\xf0\x9f\x8f\x84"}, // 🏄 + {":surfing_man:", "\xf0\x9f\x8f\x84\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🏄‍♂️ + {":surfing_woman:", "\xf0\x9f\x8f\x84\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🏄‍♀️ + {":rowboat:", "\xf0\x9f\x9a\xa3"}, // 🚣 + {":rowing_man:", "\xf0\x9f\x9a\xa3\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🚣‍♂️ + {":rowing_woman:", "\xf0\x9f\x9a\xa3\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🚣‍♀️ + {":swimmer:", "\xf0\x9f\x8f\x8a"}, // 🏊 + {":swimming_man:", "\xf0\x9f\x8f\x8a\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🏊‍♂️ + {":swimming_woman:", "\xf0\x9f\x8f\x8a\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🏊‍♀️ + {":bouncing_ball_person:", "\xe2\x9b\xb9\xef\xb8\x8f"}, // ⛹️ + {":bouncing_ball_man:", "\xe2\x9b\xb9\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // ⛹️‍♂️ + {":basketball_man:", "\xe2\x9b\xb9\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // ⛹️‍♂️ + {":bouncing_ball_woman:", "\xe2\x9b\xb9\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // ⛹️‍♀️ + {":basketball_woman:", "\xe2\x9b\xb9\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // ⛹️‍♀️ + {":weight_lifting:", "\xf0\x9f\x8f\x8b\xef\xb8\x8f"}, // 🏋️ + {":weight_lifting_man:", "\xf0\x9f\x8f\x8b\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🏋️‍♂️ + {":weight_lifting_woman:", "\xf0\x9f\x8f\x8b\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🏋️‍♀️ + {":bicyclist:", "\xf0\x9f\x9a\xb4"}, // 🚴 + {":biking_man:", "\xf0\x9f\x9a\xb4\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🚴‍♂️ + {":biking_woman:", "\xf0\x9f\x9a\xb4\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🚴‍♀️ + {":mountain_bicyclist:", "\xf0\x9f\x9a\xb5"}, // 🚵 + {":mountain_biking_man:", "\xf0\x9f\x9a\xb5\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🚵‍♂️ + {":mountain_biking_woman:", "\xf0\x9f\x9a\xb5\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🚵‍♀️ + {":cartwheeling:", "\xf0\x9f\xa4\xb8"}, // 🤸 + {":man_cartwheeling:", "\xf0\x9f\xa4\xb8\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🤸‍♂️ + {":woman_cartwheeling:", "\xf0\x9f\xa4\xb8\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🤸‍♀️ + {":wrestling:", "\xf0\x9f\xa4\xbc"}, // 🤼 + {":men_wrestling:", "\xf0\x9f\xa4\xbc\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🤼‍♂️ + {":women_wrestling:", "\xf0\x9f\xa4\xbc\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🤼‍♀️ + {":water_polo:", "\xf0\x9f\xa4\xbd"}, // 🤽 + {":man_playing_water_polo:", "\xf0\x9f\xa4\xbd\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🤽‍♂️ + {":woman_playing_water_polo:", "\xf0\x9f\xa4\xbd\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🤽‍♀️ + {":handball_person:", "\xf0\x9f\xa4\xbe"}, // 🤾 + {":man_playing_handball:", "\xf0\x9f\xa4\xbe\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🤾‍♂️ + {":woman_playing_handball:", "\xf0\x9f\xa4\xbe\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🤾‍♀️ + {":juggling_person:", "\xf0\x9f\xa4\xb9"}, // 🤹 + {":man_juggling:", "\xf0\x9f\xa4\xb9\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🤹‍♂️ + {":woman_juggling:", "\xf0\x9f\xa4\xb9\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🤹‍♀️ + {":lotus_position:", "\xf0\x9f\xa7\x98"}, // 🧘 + {":lotus_position_man:", "\xf0\x9f\xa7\x98\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f"}, // 🧘‍♂️ + {":lotus_position_woman:", "\xf0\x9f\xa7\x98\xe2\x80\x8d\xe2\x99\x80\xef\xb8\x8f"}, // 🧘‍♀️ + {":bath:", "\xf0\x9f\x9b\x80"}, // 🛀 + {":sleeping_bed:", "\xf0\x9f\x9b\x8c"}, // 🛌 + {":people_holding_hands:", "\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d\xf0\x9f\xa7\x91"}, // 🧑‍🤝‍🧑 + {":two_women_holding_hands:", "\xf0\x9f\x91\xad"}, // 👭 + {":couple:", "\xf0\x9f\x91\xab"}, // 👫 + {":two_men_holding_hands:", "\xf0\x9f\x91\xac"}, // 👬 + {":couplekiss:", "\xf0\x9f\x92\x8f"}, // 💏 + {":couplekiss_man_woman:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x92\x8b\xe2\x80\x8d\xf0\x9f\x91\xa8"}, // 👩‍❤️‍💋‍👨 + {":couplekiss_man_man:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x92\x8b\xe2\x80\x8d\xf0\x9f\x91\xa8"}, // 👨‍❤️‍💋‍👨 + {":couplekiss_woman_woman:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x92\x8b\xe2\x80\x8d\xf0\x9f\x91\xa9"}, // 👩‍❤️‍💋‍👩 + {":couple_with_heart:", "\xf0\x9f\x92\x91"}, // 💑 + {":couple_with_heart_woman_man:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x91\xa8"}, // 👩‍❤️‍👨 + {":couple_with_heart_man_man:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x91\xa8"}, // 👨‍❤️‍👨 + {":couple_with_heart_woman_woman:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x91\xa9"}, // 👩‍❤️‍👩 + {":family:", "\xf0\x9f\x91\xaa"}, // 👪 + {":family_man_woman_boy:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👨‍👩‍👦 + {":family_man_woman_girl:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7"}, // 👨‍👩‍👧 + {":family_man_woman_girl_boy:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👨‍👩‍👧‍👦 + {":family_man_woman_boy_boy:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👨‍👩‍👦‍👦 + {":family_man_woman_girl_girl:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa7"}, // 👨‍👩‍👧‍👧 + {":family_man_man_boy:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👨‍👨‍👦 + {":family_man_man_girl:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7"}, // 👨‍👨‍👧 + {":family_man_man_girl_boy:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👨‍👨‍👧‍👦 + {":family_man_man_boy_boy:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa6\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👨‍👨‍👦‍👦 + {":family_man_man_girl_girl:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa7"}, // 👨‍👨‍👧‍👧 + {":family_woman_woman_boy:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👩‍👩‍👦 + {":family_woman_woman_girl:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7"}, // 👩‍👩‍👧 + {":family_woman_woman_girl_boy:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👩‍👩‍👧‍👦 + {":family_woman_woman_boy_boy:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👩‍👩‍👦‍👦 + {":family_woman_woman_girl_girl:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa7"}, // 👩‍👩‍👧‍👧 + {":family_man_boy:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👨‍👦 + {":family_man_boy_boy:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa6\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👨‍👦‍👦 + {":family_man_girl:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7"}, // 👨‍👧 + {":family_man_girl_boy:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👨‍👧‍👦 + {":family_man_girl_girl:", "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa7"}, // 👨‍👧‍👧 + {":family_woman_boy:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👩‍👦 + {":family_woman_boy_boy:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👩‍👦‍👦 + {":family_woman_girl:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7"}, // 👩‍👧 + {":family_woman_girl_boy:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa6"}, // 👩‍👧‍👦 + {":family_woman_girl_girl:", "\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa7"}, // 👩‍👧‍👧 + {":speaking_head:", "\xf0\x9f\x97\xa3\xef\xb8\x8f"}, // 🗣️ + {":bust_in_silhouette:", "\xf0\x9f\x91\xa4"}, // 👤 + {":busts_in_silhouette:", "\xf0\x9f\x91\xa5"}, // 👥 + {":people_hugging:", "\xf0\x9f\xab\x82"}, // 🫂 + {":footprints:", "\xf0\x9f\x91\xa3"}, // 👣 + {":monkey_face:", "\xf0\x9f\x90\xb5"}, // 🐵 + {":monkey:", "\xf0\x9f\x90\x92"}, // 🐒 + {":gorilla:", "\xf0\x9f\xa6\x8d"}, // 🦍 + {":orangutan:", "\xf0\x9f\xa6\xa7"}, // 🦧 + {":dog:", "\xf0\x9f\x90\xb6"}, // 🐶 + {":dog2:", "\xf0\x9f\x90\x95"}, // 🐕 + {":guide_dog:", "\xf0\x9f\xa6\xae"}, // 🦮 + {":service_dog:", "\xf0\x9f\x90\x95\xe2\x80\x8d\xf0\x9f\xa6\xba"}, // 🐕‍🦺 + {":poodle:", "\xf0\x9f\x90\xa9"}, // 🐩 + {":wolf:", "\xf0\x9f\x90\xba"}, // 🐺 + {":fox_face:", "\xf0\x9f\xa6\x8a"}, // 🦊 + {":raccoon:", "\xf0\x9f\xa6\x9d"}, // 🦝 + {":cat:", "\xf0\x9f\x90\xb1"}, // 🐱 + {":cat2:", "\xf0\x9f\x90\x88"}, // 🐈 + {":black_cat:", "\xf0\x9f\x90\x88\xe2\x80\x8d\xe2\xac\x9b"}, // 🐈‍⬛ + {":lion:", "\xf0\x9f\xa6\x81"}, // 🦁 + {":tiger:", "\xf0\x9f\x90\xaf"}, // 🐯 + {":tiger2:", "\xf0\x9f\x90\x85"}, // 🐅 + {":leopard:", "\xf0\x9f\x90\x86"}, // 🐆 + {":horse:", "\xf0\x9f\x90\xb4"}, // 🐴 + {":racehorse:", "\xf0\x9f\x90\x8e"}, // 🐎 + {":unicorn:", "\xf0\x9f\xa6\x84"}, // 🦄 + {":zebra:", "\xf0\x9f\xa6\x93"}, // 🦓 + {":deer:", "\xf0\x9f\xa6\x8c"}, // 🦌 + {":bison:", "\xf0\x9f\xa6\xac"}, // 🦬 + {":cow:", "\xf0\x9f\x90\xae"}, // 🐮 + {":ox:", "\xf0\x9f\x90\x82"}, // 🐂 + {":water_buffalo:", "\xf0\x9f\x90\x83"}, // 🐃 + {":cow2:", "\xf0\x9f\x90\x84"}, // 🐄 + {":pig:", "\xf0\x9f\x90\xb7"}, // 🐷 + {":pig2:", "\xf0\x9f\x90\x96"}, // 🐖 + {":boar:", "\xf0\x9f\x90\x97"}, // 🐗 + {":pig_nose:", "\xf0\x9f\x90\xbd"}, // 🐽 + {":ram:", "\xf0\x9f\x90\x8f"}, // 🐏 + {":sheep:", "\xf0\x9f\x90\x91"}, // 🐑 + {":goat:", "\xf0\x9f\x90\x90"}, // 🐐 + {":dromedary_camel:", "\xf0\x9f\x90\xaa"}, // 🐪 + {":camel:", "\xf0\x9f\x90\xab"}, // 🐫 + {":llama:", "\xf0\x9f\xa6\x99"}, // 🦙 + {":giraffe:", "\xf0\x9f\xa6\x92"}, // 🦒 + {":elephant:", "\xf0\x9f\x90\x98"}, // 🐘 + {":mammoth:", "\xf0\x9f\xa6\xa3"}, // 🦣 + {":rhinoceros:", "\xf0\x9f\xa6\x8f"}, // 🦏 + {":hippopotamus:", "\xf0\x9f\xa6\x9b"}, // 🦛 + {":mouse:", "\xf0\x9f\x90\xad"}, // 🐭 + {":mouse2:", "\xf0\x9f\x90\x81"}, // 🐁 + {":rat:", "\xf0\x9f\x90\x80"}, // 🐀 + {":hamster:", "\xf0\x9f\x90\xb9"}, // 🐹 + {":rabbit:", "\xf0\x9f\x90\xb0"}, // 🐰 + {":rabbit2:", "\xf0\x9f\x90\x87"}, // 🐇 + {":chipmunk:", "\xf0\x9f\x90\xbf\xef\xb8\x8f"}, // 🐿️ + {":beaver:", "\xf0\x9f\xa6\xab"}, // 🦫 + {":hedgehog:", "\xf0\x9f\xa6\x94"}, // 🦔 + {":bat:", "\xf0\x9f\xa6\x87"}, // 🦇 + {":bear:", "\xf0\x9f\x90\xbb"}, // 🐻 + {":polar_bear:", "\xf0\x9f\x90\xbb\xe2\x80\x8d\xe2\x9d\x84\xef\xb8\x8f"}, // 🐻‍❄️ + {":koala:", "\xf0\x9f\x90\xa8"}, // 🐨 + {":panda_face:", "\xf0\x9f\x90\xbc"}, // 🐼 + {":sloth:", "\xf0\x9f\xa6\xa5"}, // 🦥 + {":otter:", "\xf0\x9f\xa6\xa6"}, // 🦦 + {":skunk:", "\xf0\x9f\xa6\xa8"}, // 🦨 + {":kangaroo:", "\xf0\x9f\xa6\x98"}, // 🦘 + {":badger:", "\xf0\x9f\xa6\xa1"}, // 🦡 + {":feet:", "\xf0\x9f\x90\xbe"}, // 🐾 + {":paw_prints:", "\xf0\x9f\x90\xbe"}, // 🐾 + {":turkey:", "\xf0\x9f\xa6\x83"}, // 🦃 + {":chicken:", "\xf0\x9f\x90\x94"}, // 🐔 + {":rooster:", "\xf0\x9f\x90\x93"}, // 🐓 + {":hatching_chick:", "\xf0\x9f\x90\xa3"}, // 🐣 + {":baby_chick:", "\xf0\x9f\x90\xa4"}, // 🐤 + {":hatched_chick:", "\xf0\x9f\x90\xa5"}, // 🐥 + {":bird:", "\xf0\x9f\x90\xa6"}, // 🐦 + {":penguin:", "\xf0\x9f\x90\xa7"}, // 🐧 + {":dove:", "\xf0\x9f\x95\x8a\xef\xb8\x8f"}, // 🕊️ + {":eagle:", "\xf0\x9f\xa6\x85"}, // 🦅 + {":duck:", "\xf0\x9f\xa6\x86"}, // 🦆 + {":swan:", "\xf0\x9f\xa6\xa2"}, // 🦢 + {":owl:", "\xf0\x9f\xa6\x89"}, // 🦉 + {":dodo:", "\xf0\x9f\xa6\xa4"}, // 🦤 + {":feather:", "\xf0\x9f\xaa\xb6"}, // 🪶 + {":flamingo:", "\xf0\x9f\xa6\xa9"}, // 🦩 + {":peacock:", "\xf0\x9f\xa6\x9a"}, // 🦚 + {":parrot:", "\xf0\x9f\xa6\x9c"}, // 🦜 + {":frog:", "\xf0\x9f\x90\xb8"}, // 🐸 + {":crocodile:", "\xf0\x9f\x90\x8a"}, // 🐊 + {":turtle:", "\xf0\x9f\x90\xa2"}, // 🐢 + {":lizard:", "\xf0\x9f\xa6\x8e"}, // 🦎 + {":snake:", "\xf0\x9f\x90\x8d"}, // 🐍 + {":dragon_face:", "\xf0\x9f\x90\xb2"}, // 🐲 + {":dragon:", "\xf0\x9f\x90\x89"}, // 🐉 + {":sauropod:", "\xf0\x9f\xa6\x95"}, // 🦕 + {":t-rex:", "\xf0\x9f\xa6\x96"}, // 🦖 + {":whale:", "\xf0\x9f\x90\xb3"}, // 🐳 + {":whale2:", "\xf0\x9f\x90\x8b"}, // 🐋 + {":dolphin:", "\xf0\x9f\x90\xac"}, // 🐬 + {":flipper:", "\xf0\x9f\x90\xac"}, // 🐬 + {":seal:", "\xf0\x9f\xa6\xad"}, // 🦭 + {":fish:", "\xf0\x9f\x90\x9f"}, // 🐟 + {":tropical_fish:", "\xf0\x9f\x90\xa0"}, // 🐠 + {":blowfish:", "\xf0\x9f\x90\xa1"}, // 🐡 + {":shark:", "\xf0\x9f\xa6\x88"}, // 🦈 + {":octopus:", "\xf0\x9f\x90\x99"}, // 🐙 + {":shell:", "\xf0\x9f\x90\x9a"}, // 🐚 + {":snail:", "\xf0\x9f\x90\x8c"}, // 🐌 + {":butterfly:", "\xf0\x9f\xa6\x8b"}, // 🦋 + {":bug:", "\xf0\x9f\x90\x9b"}, // 🐛 + {":ant:", "\xf0\x9f\x90\x9c"}, // 🐜 + {":bee:", "\xf0\x9f\x90\x9d"}, // 🐝 + {":honeybee:", "\xf0\x9f\x90\x9d"}, // 🐝 + {":beetle:", "\xf0\x9f\xaa\xb2"}, // 🪲 + {":lady_beetle:", "\xf0\x9f\x90\x9e"}, // 🐞 + {":cricket:", "\xf0\x9f\xa6\x97"}, // 🦗 + {":cockroach:", "\xf0\x9f\xaa\xb3"}, // 🪳 + {":spider:", "\xf0\x9f\x95\xb7\xef\xb8\x8f"}, // 🕷️ + {":spider_web:", "\xf0\x9f\x95\xb8\xef\xb8\x8f"}, // 🕸️ + {":scorpion:", "\xf0\x9f\xa6\x82"}, // 🦂 + {":mosquito:", "\xf0\x9f\xa6\x9f"}, // 🦟 + {":fly:", "\xf0\x9f\xaa\xb0"}, // 🪰 + {":worm:", "\xf0\x9f\xaa\xb1"}, // 🪱 + {":microbe:", "\xf0\x9f\xa6\xa0"}, // 🦠 + {":bouquet:", "\xf0\x9f\x92\x90"}, // 💐 + {":cherry_blossom:", "\xf0\x9f\x8c\xb8"}, // 🌸 + {":white_flower:", "\xf0\x9f\x92\xae"}, // 💮 + {":rosette:", "\xf0\x9f\x8f\xb5\xef\xb8\x8f"}, // 🏵️ + {":rose:", "\xf0\x9f\x8c\xb9"}, // 🌹 + {":wilted_flower:", "\xf0\x9f\xa5\x80"}, // 🥀 + {":hibiscus:", "\xf0\x9f\x8c\xba"}, // 🌺 + {":sunflower:", "\xf0\x9f\x8c\xbb"}, // 🌻 + {":blossom:", "\xf0\x9f\x8c\xbc"}, // 🌼 + {":tulip:", "\xf0\x9f\x8c\xb7"}, // 🌷 + {":seedling:", "\xf0\x9f\x8c\xb1"}, // 🌱 + {":potted_plant:", "\xf0\x9f\xaa\xb4"}, // 🪴 + {":evergreen_tree:", "\xf0\x9f\x8c\xb2"}, // 🌲 + {":deciduous_tree:", "\xf0\x9f\x8c\xb3"}, // 🌳 + {":palm_tree:", "\xf0\x9f\x8c\xb4"}, // 🌴 + {":cactus:", "\xf0\x9f\x8c\xb5"}, // 🌵 + {":ear_of_rice:", "\xf0\x9f\x8c\xbe"}, // 🌾 + {":herb:", "\xf0\x9f\x8c\xbf"}, // 🌿 + {":shamrock:", "\xe2\x98\x98\xef\xb8\x8f"}, // ☘️ + {":four_leaf_clover:", "\xf0\x9f\x8d\x80"}, // 🍀 + {":maple_leaf:", "\xf0\x9f\x8d\x81"}, // 🍁 + {":fallen_leaf:", "\xf0\x9f\x8d\x82"}, // 🍂 + {":leaves:", "\xf0\x9f\x8d\x83"}, // 🍃 + {":grapes:", "\xf0\x9f\x8d\x87"}, // 🍇 + {":melon:", "\xf0\x9f\x8d\x88"}, // 🍈 + {":watermelon:", "\xf0\x9f\x8d\x89"}, // 🍉 + {":tangerine:", "\xf0\x9f\x8d\x8a"}, // 🍊 + {":orange:", "\xf0\x9f\x8d\x8a"}, // 🍊 + {":mandarin:", "\xf0\x9f\x8d\x8a"}, // 🍊 + {":lemon:", "\xf0\x9f\x8d\x8b"}, // 🍋 + {":banana:", "\xf0\x9f\x8d\x8c"}, // 🍌 + {":pineapple:", "\xf0\x9f\x8d\x8d"}, // 🍍 + {":mango:", "\xf0\x9f\xa5\xad"}, // 🥭 + {":apple:", "\xf0\x9f\x8d\x8e"}, // 🍎 + {":green_apple:", "\xf0\x9f\x8d\x8f"}, // 🍏 + {":pear:", "\xf0\x9f\x8d\x90"}, // 🍐 + {":peach:", "\xf0\x9f\x8d\x91"}, // 🍑 + {":cherries:", "\xf0\x9f\x8d\x92"}, // 🍒 + {":strawberry:", "\xf0\x9f\x8d\x93"}, // 🍓 + {":blueberries:", "\xf0\x9f\xab\x90"}, // 🫐 + {":kiwi_fruit:", "\xf0\x9f\xa5\x9d"}, // 🥝 + {":tomato:", "\xf0\x9f\x8d\x85"}, // 🍅 + {":olive:", "\xf0\x9f\xab\x92"}, // 🫒 + {":coconut:", "\xf0\x9f\xa5\xa5"}, // 🥥 + {":avocado:", "\xf0\x9f\xa5\x91"}, // 🥑 + {":eggplant:", "\xf0\x9f\x8d\x86"}, // 🍆 + {":potato:", "\xf0\x9f\xa5\x94"}, // 🥔 + {":carrot:", "\xf0\x9f\xa5\x95"}, // 🥕 + {":corn:", "\xf0\x9f\x8c\xbd"}, // 🌽 + {":hot_pepper:", "\xf0\x9f\x8c\xb6\xef\xb8\x8f"}, // 🌶️ + {":bell_pepper:", "\xf0\x9f\xab\x91"}, // 🫑 + {":cucumber:", "\xf0\x9f\xa5\x92"}, // 🥒 + {":leafy_green:", "\xf0\x9f\xa5\xac"}, // 🥬 + {":broccoli:", "\xf0\x9f\xa5\xa6"}, // 🥦 + {":garlic:", "\xf0\x9f\xa7\x84"}, // 🧄 + {":onion:", "\xf0\x9f\xa7\x85"}, // 🧅 + {":mushroom:", "\xf0\x9f\x8d\x84"}, // 🍄 + {":peanuts:", "\xf0\x9f\xa5\x9c"}, // 🥜 + {":chestnut:", "\xf0\x9f\x8c\xb0"}, // 🌰 + {":bread:", "\xf0\x9f\x8d\x9e"}, // 🍞 + {":croissant:", "\xf0\x9f\xa5\x90"}, // 🥐 + {":baguette_bread:", "\xf0\x9f\xa5\x96"}, // 🥖 + {":flatbread:", "\xf0\x9f\xab\x93"}, // 🫓 + {":pretzel:", "\xf0\x9f\xa5\xa8"}, // 🥨 + {":bagel:", "\xf0\x9f\xa5\xaf"}, // 🥯 + {":pancakes:", "\xf0\x9f\xa5\x9e"}, // 🥞 + {":waffle:", "\xf0\x9f\xa7\x87"}, // 🧇 + {":cheese:", "\xf0\x9f\xa7\x80"}, // 🧀 + {":meat_on_bone:", "\xf0\x9f\x8d\x96"}, // 🍖 + {":poultry_leg:", "\xf0\x9f\x8d\x97"}, // 🍗 + {":cut_of_meat:", "\xf0\x9f\xa5\xa9"}, // 🥩 + {":bacon:", "\xf0\x9f\xa5\x93"}, // 🥓 + {":hamburger:", "\xf0\x9f\x8d\x94"}, // 🍔 + {":fries:", "\xf0\x9f\x8d\x9f"}, // 🍟 + {":pizza:", "\xf0\x9f\x8d\x95"}, // 🍕 + {":hotdog:", "\xf0\x9f\x8c\xad"}, // 🌭 + {":sandwich:", "\xf0\x9f\xa5\xaa"}, // 🥪 + {":taco:", "\xf0\x9f\x8c\xae"}, // 🌮 + {":burrito:", "\xf0\x9f\x8c\xaf"}, // 🌯 + {":tamale:", "\xf0\x9f\xab\x94"}, // 🫔 + {":stuffed_flatbread:", "\xf0\x9f\xa5\x99"}, // 🥙 + {":falafel:", "\xf0\x9f\xa7\x86"}, // 🧆 + {":egg:", "\xf0\x9f\xa5\x9a"}, // 🥚 + {":fried_egg:", "\xf0\x9f\x8d\xb3"}, // 🍳 + {":shallow_pan_of_food:", "\xf0\x9f\xa5\x98"}, // 🥘 + {":stew:", "\xf0\x9f\x8d\xb2"}, // 🍲 + {":fondue:", "\xf0\x9f\xab\x95"}, // 🫕 + {":bowl_with_spoon:", "\xf0\x9f\xa5\xa3"}, // 🥣 + {":green_salad:", "\xf0\x9f\xa5\x97"}, // 🥗 + {":popcorn:", "\xf0\x9f\x8d\xbf"}, // 🍿 + {":butter:", "\xf0\x9f\xa7\x88"}, // 🧈 + {":salt:", "\xf0\x9f\xa7\x82"}, // 🧂 + {":canned_food:", "\xf0\x9f\xa5\xab"}, // 🥫 + {":bento:", "\xf0\x9f\x8d\xb1"}, // 🍱 + {":rice_cracker:", "\xf0\x9f\x8d\x98"}, // 🍘 + {":rice_ball:", "\xf0\x9f\x8d\x99"}, // 🍙 + {":rice:", "\xf0\x9f\x8d\x9a"}, // 🍚 + {":curry:", "\xf0\x9f\x8d\x9b"}, // 🍛 + {":ramen:", "\xf0\x9f\x8d\x9c"}, // 🍜 + {":spaghetti:", "\xf0\x9f\x8d\x9d"}, // 🍝 + {":sweet_potato:", "\xf0\x9f\x8d\xa0"}, // 🍠 + {":oden:", "\xf0\x9f\x8d\xa2"}, // 🍢 + {":sushi:", "\xf0\x9f\x8d\xa3"}, // 🍣 + {":fried_shrimp:", "\xf0\x9f\x8d\xa4"}, // 🍤 + {":fish_cake:", "\xf0\x9f\x8d\xa5"}, // 🍥 + {":moon_cake:", "\xf0\x9f\xa5\xae"}, // 🥮 + {":dango:", "\xf0\x9f\x8d\xa1"}, // 🍡 + {":dumpling:", "\xf0\x9f\xa5\x9f"}, // 🥟 + {":fortune_cookie:", "\xf0\x9f\xa5\xa0"}, // 🥠 + {":takeout_box:", "\xf0\x9f\xa5\xa1"}, // 🥡 + {":crab:", "\xf0\x9f\xa6\x80"}, // 🦀 + {":lobster:", "\xf0\x9f\xa6\x9e"}, // 🦞 + {":shrimp:", "\xf0\x9f\xa6\x90"}, // 🦐 + {":squid:", "\xf0\x9f\xa6\x91"}, // 🦑 + {":oyster:", "\xf0\x9f\xa6\xaa"}, // 🦪 + {":icecream:", "\xf0\x9f\x8d\xa6"}, // 🍦 + {":shaved_ice:", "\xf0\x9f\x8d\xa7"}, // 🍧 + {":ice_cream:", "\xf0\x9f\x8d\xa8"}, // 🍨 + {":doughnut:", "\xf0\x9f\x8d\xa9"}, // 🍩 + {":cookie:", "\xf0\x9f\x8d\xaa"}, // 🍪 + {":birthday:", "\xf0\x9f\x8e\x82"}, // 🎂 + {":cake:", "\xf0\x9f\x8d\xb0"}, // 🍰 + {":cupcake:", "\xf0\x9f\xa7\x81"}, // 🧁 + {":pie:", "\xf0\x9f\xa5\xa7"}, // 🥧 + {":chocolate_bar:", "\xf0\x9f\x8d\xab"}, // 🍫 + {":candy:", "\xf0\x9f\x8d\xac"}, // 🍬 + {":lollipop:", "\xf0\x9f\x8d\xad"}, // 🍭 + {":custard:", "\xf0\x9f\x8d\xae"}, // 🍮 + {":honey_pot:", "\xf0\x9f\x8d\xaf"}, // 🍯 + {":baby_bottle:", "\xf0\x9f\x8d\xbc"}, // 🍼 + {":milk_glass:", "\xf0\x9f\xa5\x9b"}, // 🥛 + {":coffee:", "\xe2\x98\x95"}, // ☕ + {":teapot:", "\xf0\x9f\xab\x96"}, // 🫖 + {":tea:", "\xf0\x9f\x8d\xb5"}, // 🍵 + {":sake:", "\xf0\x9f\x8d\xb6"}, // 🍶 + {":champagne:", "\xf0\x9f\x8d\xbe"}, // 🍾 + {":wine_glass:", "\xf0\x9f\x8d\xb7"}, // 🍷 + {":cocktail:", "\xf0\x9f\x8d\xb8"}, // 🍸 + {":tropical_drink:", "\xf0\x9f\x8d\xb9"}, // 🍹 + {":beer:", "\xf0\x9f\x8d\xba"}, // 🍺 + {":beers:", "\xf0\x9f\x8d\xbb"}, // 🍻 + {":clinking_glasses:", "\xf0\x9f\xa5\x82"}, // 🥂 + {":tumbler_glass:", "\xf0\x9f\xa5\x83"}, // 🥃 + {":cup_with_straw:", "\xf0\x9f\xa5\xa4"}, // 🥤 + {":bubble_tea:", "\xf0\x9f\xa7\x8b"}, // 🧋 + {":beverage_box:", "\xf0\x9f\xa7\x83"}, // 🧃 + {":mate:", "\xf0\x9f\xa7\x89"}, // 🧉 + {":ice_cube:", "\xf0\x9f\xa7\x8a"}, // 🧊 + {":chopsticks:", "\xf0\x9f\xa5\xa2"}, // 🥢 + {":plate_with_cutlery:", "\xf0\x9f\x8d\xbd\xef\xb8\x8f"}, // 🍽️ + {":fork_and_knife:", "\xf0\x9f\x8d\xb4"}, // 🍴 + {":spoon:", "\xf0\x9f\xa5\x84"}, // 🥄 + {":hocho:", "\xf0\x9f\x94\xaa"}, // 🔪 + {":knife:", "\xf0\x9f\x94\xaa"}, // 🔪 + {":amphora:", "\xf0\x9f\x8f\xba"}, // 🏺 + {":earth_africa:", "\xf0\x9f\x8c\x8d"}, // 🌍 + {":earth_americas:", "\xf0\x9f\x8c\x8e"}, // 🌎 + {":earth_asia:", "\xf0\x9f\x8c\x8f"}, // 🌏 + {":globe_with_meridians:", "\xf0\x9f\x8c\x90"}, // 🌐 + {":world_map:", "\xf0\x9f\x97\xba\xef\xb8\x8f"}, // 🗺️ + {":japan:", "\xf0\x9f\x97\xbe"}, // 🗾 + {":compass:", "\xf0\x9f\xa7\xad"}, // 🧭 + {":mountain_snow:", "\xf0\x9f\x8f\x94\xef\xb8\x8f"}, // 🏔️ + {":mountain:", "\xe2\x9b\xb0\xef\xb8\x8f"}, // ⛰️ + {":volcano:", "\xf0\x9f\x8c\x8b"}, // 🌋 + {":mount_fuji:", "\xf0\x9f\x97\xbb"}, // 🗻 + {":camping:", "\xf0\x9f\x8f\x95\xef\xb8\x8f"}, // 🏕️ + {":beach_umbrella:", "\xf0\x9f\x8f\x96\xef\xb8\x8f"}, // 🏖️ + {":desert:", "\xf0\x9f\x8f\x9c\xef\xb8\x8f"}, // 🏜️ + {":desert_island:", "\xf0\x9f\x8f\x9d\xef\xb8\x8f"}, // 🏝️ + {":national_park:", "\xf0\x9f\x8f\x9e\xef\xb8\x8f"}, // 🏞️ + {":stadium:", "\xf0\x9f\x8f\x9f\xef\xb8\x8f"}, // 🏟️ + {":classical_building:", "\xf0\x9f\x8f\x9b\xef\xb8\x8f"}, // 🏛️ + {":building_construction:", "\xf0\x9f\x8f\x97\xef\xb8\x8f"}, // 🏗️ + {":bricks:", "\xf0\x9f\xa7\xb1"}, // 🧱 + {":rock:", "\xf0\x9f\xaa\xa8"}, // 🪨 + {":wood:", "\xf0\x9f\xaa\xb5"}, // 🪵 + {":hut:", "\xf0\x9f\x9b\x96"}, // 🛖 + {":houses:", "\xf0\x9f\x8f\x98\xef\xb8\x8f"}, // 🏘️ + {":derelict_house:", "\xf0\x9f\x8f\x9a\xef\xb8\x8f"}, // 🏚️ + {":house:", "\xf0\x9f\x8f\xa0"}, // 🏠 + {":house_with_garden:", "\xf0\x9f\x8f\xa1"}, // 🏡 + {":office:", "\xf0\x9f\x8f\xa2"}, // 🏢 + {":post_office:", "\xf0\x9f\x8f\xa3"}, // 🏣 + {":european_post_office:", "\xf0\x9f\x8f\xa4"}, // 🏤 + {":hospital:", "\xf0\x9f\x8f\xa5"}, // 🏥 + {":bank:", "\xf0\x9f\x8f\xa6"}, // 🏦 + {":hotel:", "\xf0\x9f\x8f\xa8"}, // 🏨 + {":love_hotel:", "\xf0\x9f\x8f\xa9"}, // 🏩 + {":convenience_store:", "\xf0\x9f\x8f\xaa"}, // 🏪 + {":school:", "\xf0\x9f\x8f\xab"}, // 🏫 + {":department_store:", "\xf0\x9f\x8f\xac"}, // 🏬 + {":factory:", "\xf0\x9f\x8f\xad"}, // 🏭 + {":japanese_castle:", "\xf0\x9f\x8f\xaf"}, // 🏯 + {":european_castle:", "\xf0\x9f\x8f\xb0"}, // 🏰 + {":wedding:", "\xf0\x9f\x92\x92"}, // 💒 + {":tokyo_tower:", "\xf0\x9f\x97\xbc"}, // 🗼 + {":statue_of_liberty:", "\xf0\x9f\x97\xbd"}, // 🗽 + {":church:", "\xe2\x9b\xaa"}, // ⛪ + {":mosque:", "\xf0\x9f\x95\x8c"}, // 🕌 + {":hindu_temple:", "\xf0\x9f\x9b\x95"}, // 🛕 + {":synagogue:", "\xf0\x9f\x95\x8d"}, // 🕍 + {":shinto_shrine:", "\xe2\x9b\xa9\xef\xb8\x8f"}, // ⛩️ + {":kaaba:", "\xf0\x9f\x95\x8b"}, // 🕋 + {":fountain:", "\xe2\x9b\xb2"}, // ⛲ + {":tent:", "\xe2\x9b\xba"}, // ⛺ + {":foggy:", "\xf0\x9f\x8c\x81"}, // 🌁 + {":night_with_stars:", "\xf0\x9f\x8c\x83"}, // 🌃 + {":cityscape:", "\xf0\x9f\x8f\x99\xef\xb8\x8f"}, // 🏙️ + {":sunrise_over_mountains:", "\xf0\x9f\x8c\x84"}, // 🌄 + {":sunrise:", "\xf0\x9f\x8c\x85"}, // 🌅 + {":city_sunset:", "\xf0\x9f\x8c\x86"}, // 🌆 + {":city_sunrise:", "\xf0\x9f\x8c\x87"}, // 🌇 + {":bridge_at_night:", "\xf0\x9f\x8c\x89"}, // 🌉 + {":hotsprings:", "\xe2\x99\xa8\xef\xb8\x8f"}, // ♨️ + {":carousel_horse:", "\xf0\x9f\x8e\xa0"}, // 🎠 + {":ferris_wheel:", "\xf0\x9f\x8e\xa1"}, // 🎡 + {":roller_coaster:", "\xf0\x9f\x8e\xa2"}, // 🎢 + {":barber:", "\xf0\x9f\x92\x88"}, // 💈 + {":circus_tent:", "\xf0\x9f\x8e\xaa"}, // 🎪 + {":steam_locomotive:", "\xf0\x9f\x9a\x82"}, // 🚂 + {":railway_car:", "\xf0\x9f\x9a\x83"}, // 🚃 + {":bullettrain_side:", "\xf0\x9f\x9a\x84"}, // 🚄 + {":bullettrain_front:", "\xf0\x9f\x9a\x85"}, // 🚅 + {":train2:", "\xf0\x9f\x9a\x86"}, // 🚆 + {":metro:", "\xf0\x9f\x9a\x87"}, // 🚇 + {":light_rail:", "\xf0\x9f\x9a\x88"}, // 🚈 + {":station:", "\xf0\x9f\x9a\x89"}, // 🚉 + {":tram:", "\xf0\x9f\x9a\x8a"}, // 🚊 + {":monorail:", "\xf0\x9f\x9a\x9d"}, // 🚝 + {":mountain_railway:", "\xf0\x9f\x9a\x9e"}, // 🚞 + {":train:", "\xf0\x9f\x9a\x8b"}, // 🚋 + {":bus:", "\xf0\x9f\x9a\x8c"}, // 🚌 + {":oncoming_bus:", "\xf0\x9f\x9a\x8d"}, // 🚍 + {":trolleybus:", "\xf0\x9f\x9a\x8e"}, // 🚎 + {":minibus:", "\xf0\x9f\x9a\x90"}, // 🚐 + {":ambulance:", "\xf0\x9f\x9a\x91"}, // 🚑 + {":fire_engine:", "\xf0\x9f\x9a\x92"}, // 🚒 + {":police_car:", "\xf0\x9f\x9a\x93"}, // 🚓 + {":oncoming_police_car:", "\xf0\x9f\x9a\x94"}, // 🚔 + {":taxi:", "\xf0\x9f\x9a\x95"}, // 🚕 + {":oncoming_taxi:", "\xf0\x9f\x9a\x96"}, // 🚖 + {":car:", "\xf0\x9f\x9a\x97"}, // 🚗 + {":red_car:", "\xf0\x9f\x9a\x97"}, // 🚗 + {":oncoming_automobile:", "\xf0\x9f\x9a\x98"}, // 🚘 + {":blue_car:", "\xf0\x9f\x9a\x99"}, // 🚙 + {":pickup_truck:", "\xf0\x9f\x9b\xbb"}, // 🛻 + {":truck:", "\xf0\x9f\x9a\x9a"}, // 🚚 + {":articulated_lorry:", "\xf0\x9f\x9a\x9b"}, // 🚛 + {":tractor:", "\xf0\x9f\x9a\x9c"}, // 🚜 + {":racing_car:", "\xf0\x9f\x8f\x8e\xef\xb8\x8f"}, // 🏎️ + {":motorcycle:", "\xf0\x9f\x8f\x8d\xef\xb8\x8f"}, // 🏍️ + {":motor_scooter:", "\xf0\x9f\x9b\xb5"}, // 🛵 + {":manual_wheelchair:", "\xf0\x9f\xa6\xbd"}, // 🦽 + {":motorized_wheelchair:", "\xf0\x9f\xa6\xbc"}, // 🦼 + {":auto_rickshaw:", "\xf0\x9f\x9b\xba"}, // 🛺 + {":bike:", "\xf0\x9f\x9a\xb2"}, // 🚲 + {":kick_scooter:", "\xf0\x9f\x9b\xb4"}, // 🛴 + {":skateboard:", "\xf0\x9f\x9b\xb9"}, // 🛹 + {":roller_skate:", "\xf0\x9f\x9b\xbc"}, // 🛼 + {":busstop:", "\xf0\x9f\x9a\x8f"}, // 🚏 + {":motorway:", "\xf0\x9f\x9b\xa3\xef\xb8\x8f"}, // 🛣️ + {":railway_track:", "\xf0\x9f\x9b\xa4\xef\xb8\x8f"}, // 🛤️ + {":oil_drum:", "\xf0\x9f\x9b\xa2\xef\xb8\x8f"}, // 🛢️ + {":fuelpump:", "\xe2\x9b\xbd"}, // ⛽ + {":rotating_light:", "\xf0\x9f\x9a\xa8"}, // 🚨 + {":traffic_light:", "\xf0\x9f\x9a\xa5"}, // 🚥 + {":vertical_traffic_light:", "\xf0\x9f\x9a\xa6"}, // 🚦 + {":stop_sign:", "\xf0\x9f\x9b\x91"}, // 🛑 + {":construction:", "\xf0\x9f\x9a\xa7"}, // 🚧 + {":anchor:", "\xe2\x9a\x93"}, // ⚓ + {":boat:", "\xe2\x9b\xb5"}, // ⛵ + {":sailboat:", "\xe2\x9b\xb5"}, // ⛵ + {":canoe:", "\xf0\x9f\x9b\xb6"}, // 🛶 + {":speedboat:", "\xf0\x9f\x9a\xa4"}, // 🚤 + {":passenger_ship:", "\xf0\x9f\x9b\xb3\xef\xb8\x8f"}, // 🛳️ + {":ferry:", "\xe2\x9b\xb4\xef\xb8\x8f"}, // ⛴️ + {":motor_boat:", "\xf0\x9f\x9b\xa5\xef\xb8\x8f"}, // 🛥️ + {":ship:", "\xf0\x9f\x9a\xa2"}, // 🚢 + {":airplane:", "\xe2\x9c\x88\xef\xb8\x8f"}, // ✈️ + {":small_airplane:", "\xf0\x9f\x9b\xa9\xef\xb8\x8f"}, // 🛩️ + {":flight_departure:", "\xf0\x9f\x9b\xab"}, // 🛫 + {":flight_arrival:", "\xf0\x9f\x9b\xac"}, // 🛬 + {":parachute:", "\xf0\x9f\xaa\x82"}, // 🪂 + {":seat:", "\xf0\x9f\x92\xba"}, // 💺 + {":helicopter:", "\xf0\x9f\x9a\x81"}, // 🚁 + {":suspension_railway:", "\xf0\x9f\x9a\x9f"}, // 🚟 + {":mountain_cableway:", "\xf0\x9f\x9a\xa0"}, // 🚠 + {":aerial_tramway:", "\xf0\x9f\x9a\xa1"}, // 🚡 + {":artificial_satellite:", "\xf0\x9f\x9b\xb0\xef\xb8\x8f"}, // 🛰️ + {":rocket:", "\xf0\x9f\x9a\x80"}, // 🚀 + {":flying_saucer:", "\xf0\x9f\x9b\xb8"}, // 🛸 + {":bellhop_bell:", "\xf0\x9f\x9b\x8e\xef\xb8\x8f"}, // 🛎️ + {":luggage:", "\xf0\x9f\xa7\xb3"}, // 🧳 + {":hourglass:", "\xe2\x8c\x9b"}, // ⌛ + {":hourglass_flowing_sand:", "\xe2\x8f\xb3"}, // ⏳ + {":watch:", "\xe2\x8c\x9a"}, // ⌚ + {":alarm_clock:", "\xe2\x8f\xb0"}, // ⏰ + {":stopwatch:", "\xe2\x8f\xb1\xef\xb8\x8f"}, // ⏱️ + {":timer_clock:", "\xe2\x8f\xb2\xef\xb8\x8f"}, // ⏲️ + {":mantelpiece_clock:", "\xf0\x9f\x95\xb0\xef\xb8\x8f"}, // 🕰️ + {":clock12:", "\xf0\x9f\x95\x9b"}, // 🕛 + {":clock1230:", "\xf0\x9f\x95\xa7"}, // 🕧 + {":clock1:", "\xf0\x9f\x95\x90"}, // 🕐 + {":clock130:", "\xf0\x9f\x95\x9c"}, // 🕜 + {":clock2:", "\xf0\x9f\x95\x91"}, // 🕑 + {":clock230:", "\xf0\x9f\x95\x9d"}, // 🕝 + {":clock3:", "\xf0\x9f\x95\x92"}, // 🕒 + {":clock330:", "\xf0\x9f\x95\x9e"}, // 🕞 + {":clock4:", "\xf0\x9f\x95\x93"}, // 🕓 + {":clock430:", "\xf0\x9f\x95\x9f"}, // 🕟 + {":clock5:", "\xf0\x9f\x95\x94"}, // 🕔 + {":clock530:", "\xf0\x9f\x95\xa0"}, // 🕠 + {":clock6:", "\xf0\x9f\x95\x95"}, // 🕕 + {":clock630:", "\xf0\x9f\x95\xa1"}, // 🕡 + {":clock7:", "\xf0\x9f\x95\x96"}, // 🕖 + {":clock730:", "\xf0\x9f\x95\xa2"}, // 🕢 + {":clock8:", "\xf0\x9f\x95\x97"}, // 🕗 + {":clock830:", "\xf0\x9f\x95\xa3"}, // 🕣 + {":clock9:", "\xf0\x9f\x95\x98"}, // 🕘 + {":clock930:", "\xf0\x9f\x95\xa4"}, // 🕤 + {":clock10:", "\xf0\x9f\x95\x99"}, // 🕙 + {":clock1030:", "\xf0\x9f\x95\xa5"}, // 🕥 + {":clock11:", "\xf0\x9f\x95\x9a"}, // 🕚 + {":clock1130:", "\xf0\x9f\x95\xa6"}, // 🕦 + {":new_moon:", "\xf0\x9f\x8c\x91"}, // 🌑 + {":waxing_crescent_moon:", "\xf0\x9f\x8c\x92"}, // 🌒 + {":first_quarter_moon:", "\xf0\x9f\x8c\x93"}, // 🌓 + {":moon:", "\xf0\x9f\x8c\x94"}, // 🌔 + {":waxing_gibbous_moon:", "\xf0\x9f\x8c\x94"}, // 🌔 + {":full_moon:", "\xf0\x9f\x8c\x95"}, // 🌕 + {":waning_gibbous_moon:", "\xf0\x9f\x8c\x96"}, // 🌖 + {":last_quarter_moon:", "\xf0\x9f\x8c\x97"}, // 🌗 + {":waning_crescent_moon:", "\xf0\x9f\x8c\x98"}, // 🌘 + {":crescent_moon:", "\xf0\x9f\x8c\x99"}, // 🌙 + {":new_moon_with_face:", "\xf0\x9f\x8c\x9a"}, // 🌚 + {":first_quarter_moon_with_face:", "\xf0\x9f\x8c\x9b"}, // 🌛 + {":last_quarter_moon_with_face:", "\xf0\x9f\x8c\x9c"}, // 🌜 + {":thermometer:", "\xf0\x9f\x8c\xa1\xef\xb8\x8f"}, // 🌡️ + {":sunny:", "\xe2\x98\x80\xef\xb8\x8f"}, // ☀️ + {":full_moon_with_face:", "\xf0\x9f\x8c\x9d"}, // 🌝 + {":sun_with_face:", "\xf0\x9f\x8c\x9e"}, // 🌞 + {":ringed_planet:", "\xf0\x9f\xaa\x90"}, // 🪐 + {":star:", "\xe2\xad\x90"}, // ⭐ + {":star2:", "\xf0\x9f\x8c\x9f"}, // 🌟 + {":stars:", "\xf0\x9f\x8c\xa0"}, // 🌠 + {":milky_way:", "\xf0\x9f\x8c\x8c"}, // 🌌 + {":cloud:", "\xe2\x98\x81\xef\xb8\x8f"}, // ☁️ + {":partly_sunny:", "\xe2\x9b\x85"}, // ⛅ + {":cloud_with_lightning_and_rain:", "\xe2\x9b\x88\xef\xb8\x8f"}, // ⛈️ + {":sun_behind_small_cloud:", "\xf0\x9f\x8c\xa4\xef\xb8\x8f"}, // 🌤️ + {":sun_behind_large_cloud:", "\xf0\x9f\x8c\xa5\xef\xb8\x8f"}, // 🌥️ + {":sun_behind_rain_cloud:", "\xf0\x9f\x8c\xa6\xef\xb8\x8f"}, // 🌦️ + {":cloud_with_rain:", "\xf0\x9f\x8c\xa7\xef\xb8\x8f"}, // 🌧️ + {":cloud_with_snow:", "\xf0\x9f\x8c\xa8\xef\xb8\x8f"}, // 🌨️ + {":cloud_with_lightning:", "\xf0\x9f\x8c\xa9\xef\xb8\x8f"}, // 🌩️ + {":tornado:", "\xf0\x9f\x8c\xaa\xef\xb8\x8f"}, // 🌪️ + {":fog:", "\xf0\x9f\x8c\xab\xef\xb8\x8f"}, // 🌫️ + {":wind_face:", "\xf0\x9f\x8c\xac\xef\xb8\x8f"}, // 🌬️ + {":cyclone:", "\xf0\x9f\x8c\x80"}, // 🌀 + {":rainbow:", "\xf0\x9f\x8c\x88"}, // 🌈 + {":closed_umbrella:", "\xf0\x9f\x8c\x82"}, // 🌂 + {":open_umbrella:", "\xe2\x98\x82\xef\xb8\x8f"}, // ☂️ + {":umbrella:", "\xe2\x98\x94"}, // ☔ + {":parasol_on_ground:", "\xe2\x9b\xb1\xef\xb8\x8f"}, // ⛱️ + {":zap:", "\xe2\x9a\xa1"}, // ⚡ + {":snowflake:", "\xe2\x9d\x84\xef\xb8\x8f"}, // ❄️ + {":snowman_with_snow:", "\xe2\x98\x83\xef\xb8\x8f"}, // ☃️ + {":snowman:", "\xe2\x9b\x84"}, // ⛄ + {":comet:", "\xe2\x98\x84\xef\xb8\x8f"}, // ☄️ + {":fire:", "\xf0\x9f\x94\xa5"}, // 🔥 + {":droplet:", "\xf0\x9f\x92\xa7"}, // 💧 + {":ocean:", "\xf0\x9f\x8c\x8a"}, // 🌊 + {":jack_o_lantern:", "\xf0\x9f\x8e\x83"}, // 🎃 + {":christmas_tree:", "\xf0\x9f\x8e\x84"}, // 🎄 + {":fireworks:", "\xf0\x9f\x8e\x86"}, // 🎆 + {":sparkler:", "\xf0\x9f\x8e\x87"}, // 🎇 + {":firecracker:", "\xf0\x9f\xa7\xa8"}, // 🧨 + {":sparkles:", "\xe2\x9c\xa8"}, // ✨ + {":balloon:", "\xf0\x9f\x8e\x88"}, // 🎈 + {":tada:", "\xf0\x9f\x8e\x89"}, // 🎉 + {":confetti_ball:", "\xf0\x9f\x8e\x8a"}, // 🎊 + {":tanabata_tree:", "\xf0\x9f\x8e\x8b"}, // 🎋 + {":bamboo:", "\xf0\x9f\x8e\x8d"}, // 🎍 + {":dolls:", "\xf0\x9f\x8e\x8e"}, // 🎎 + {":flags:", "\xf0\x9f\x8e\x8f"}, // 🎏 + {":wind_chime:", "\xf0\x9f\x8e\x90"}, // 🎐 + {":rice_scene:", "\xf0\x9f\x8e\x91"}, // 🎑 + {":red_envelope:", "\xf0\x9f\xa7\xa7"}, // 🧧 + {":ribbon:", "\xf0\x9f\x8e\x80"}, // 🎀 + {":gift:", "\xf0\x9f\x8e\x81"}, // 🎁 + {":reminder_ribbon:", "\xf0\x9f\x8e\x97\xef\xb8\x8f"}, // 🎗️ + {":tickets:", "\xf0\x9f\x8e\x9f\xef\xb8\x8f"}, // 🎟️ + {":ticket:", "\xf0\x9f\x8e\xab"}, // 🎫 + {":medal_military:", "\xf0\x9f\x8e\x96\xef\xb8\x8f"}, // 🎖️ + {":trophy:", "\xf0\x9f\x8f\x86"}, // 🏆 + {":medal_sports:", "\xf0\x9f\x8f\x85"}, // 🏅 + {":1st_place_medal:", "\xf0\x9f\xa5\x87"}, // 🥇 + {":2nd_place_medal:", "\xf0\x9f\xa5\x88"}, // 🥈 + {":3rd_place_medal:", "\xf0\x9f\xa5\x89"}, // 🥉 + {":soccer:", "\xe2\x9a\xbd"}, // ⚽ + {":baseball:", "\xe2\x9a\xbe"}, // ⚾ + {":softball:", "\xf0\x9f\xa5\x8e"}, // 🥎 + {":basketball:", "\xf0\x9f\x8f\x80"}, // 🏀 + {":volleyball:", "\xf0\x9f\x8f\x90"}, // 🏐 + {":football:", "\xf0\x9f\x8f\x88"}, // 🏈 + {":rugby_football:", "\xf0\x9f\x8f\x89"}, // 🏉 + {":tennis:", "\xf0\x9f\x8e\xbe"}, // 🎾 + {":flying_disc:", "\xf0\x9f\xa5\x8f"}, // 🥏 + {":bowling:", "\xf0\x9f\x8e\xb3"}, // 🎳 + {":cricket_game:", "\xf0\x9f\x8f\x8f"}, // 🏏 + {":field_hockey:", "\xf0\x9f\x8f\x91"}, // 🏑 + {":ice_hockey:", "\xf0\x9f\x8f\x92"}, // 🏒 + {":lacrosse:", "\xf0\x9f\xa5\x8d"}, // 🥍 + {":ping_pong:", "\xf0\x9f\x8f\x93"}, // 🏓 + {":badminton:", "\xf0\x9f\x8f\xb8"}, // 🏸 + {":boxing_glove:", "\xf0\x9f\xa5\x8a"}, // 🥊 + {":martial_arts_uniform:", "\xf0\x9f\xa5\x8b"}, // 🥋 + {":goal_net:", "\xf0\x9f\xa5\x85"}, // 🥅 + {":golf:", "\xe2\x9b\xb3"}, // ⛳ + {":ice_skate:", "\xe2\x9b\xb8\xef\xb8\x8f"}, // ⛸️ + {":fishing_pole_and_fish:", "\xf0\x9f\x8e\xa3"}, // 🎣 + {":diving_mask:", "\xf0\x9f\xa4\xbf"}, // 🤿 + {":running_shirt_with_sash:", "\xf0\x9f\x8e\xbd"}, // 🎽 + {":ski:", "\xf0\x9f\x8e\xbf"}, // 🎿 + {":sled:", "\xf0\x9f\x9b\xb7"}, // 🛷 + {":curling_stone:", "\xf0\x9f\xa5\x8c"}, // 🥌 + {":dart:", "\xf0\x9f\x8e\xaf"}, // 🎯 + {":yo_yo:", "\xf0\x9f\xaa\x80"}, // 🪀 + {":kite:", "\xf0\x9f\xaa\x81"}, // 🪁 + {":8ball:", "\xf0\x9f\x8e\xb1"}, // 🎱 + {":crystal_ball:", "\xf0\x9f\x94\xae"}, // 🔮 + {":magic_wand:", "\xf0\x9f\xaa\x84"}, // 🪄 + {":nazar_amulet:", "\xf0\x9f\xa7\xbf"}, // 🧿 + {":video_game:", "\xf0\x9f\x8e\xae"}, // 🎮 + {":joystick:", "\xf0\x9f\x95\xb9\xef\xb8\x8f"}, // 🕹️ + {":slot_machine:", "\xf0\x9f\x8e\xb0"}, // 🎰 + {":game_die:", "\xf0\x9f\x8e\xb2"}, // 🎲 + {":jigsaw:", "\xf0\x9f\xa7\xa9"}, // 🧩 + {":teddy_bear:", "\xf0\x9f\xa7\xb8"}, // 🧸 + {":pi_ata:", "\xf0\x9f\xaa\x85"}, // 🪅 + {":nesting_dolls:", "\xf0\x9f\xaa\x86"}, // 🪆 + {":spades:", "\xe2\x99\xa0\xef\xb8\x8f"}, // ♠️ + {":hearts:", "\xe2\x99\xa5\xef\xb8\x8f"}, // ♥️ + {":diamonds:", "\xe2\x99\xa6\xef\xb8\x8f"}, // ♦️ + {":clubs:", "\xe2\x99\xa3\xef\xb8\x8f"}, // ♣️ + {":chess_pawn:", "\xe2\x99\x9f\xef\xb8\x8f"}, // ♟️ + {":black_joker:", "\xf0\x9f\x83\x8f"}, // 🃏 + {":mahjong:", "\xf0\x9f\x80\x84"}, // 🀄 + {":flower_playing_cards:", "\xf0\x9f\x8e\xb4"}, // 🎴 + {":performing_arts:", "\xf0\x9f\x8e\xad"}, // 🎭 + {":framed_picture:", "\xf0\x9f\x96\xbc\xef\xb8\x8f"}, // 🖼️ + {":art:", "\xf0\x9f\x8e\xa8"}, // 🎨 + {":thread:", "\xf0\x9f\xa7\xb5"}, // 🧵 + {":sewing_needle:", "\xf0\x9f\xaa\xa1"}, // 🪡 + {":yarn:", "\xf0\x9f\xa7\xb6"}, // 🧶 + {":knot:", "\xf0\x9f\xaa\xa2"}, // 🪢 + {":eyeglasses:", "\xf0\x9f\x91\x93"}, // 👓 + {":dark_sunglasses:", "\xf0\x9f\x95\xb6\xef\xb8\x8f"}, // 🕶️ + {":goggles:", "\xf0\x9f\xa5\xbd"}, // 🥽 + {":lab_coat:", "\xf0\x9f\xa5\xbc"}, // 🥼 + {":safety_vest:", "\xf0\x9f\xa6\xba"}, // 🦺 + {":necktie:", "\xf0\x9f\x91\x94"}, // 👔 + {":shirt:", "\xf0\x9f\x91\x95"}, // 👕 + {":tshirt:", "\xf0\x9f\x91\x95"}, // 👕 + {":jeans:", "\xf0\x9f\x91\x96"}, // 👖 + {":scarf:", "\xf0\x9f\xa7\xa3"}, // 🧣 + {":gloves:", "\xf0\x9f\xa7\xa4"}, // 🧤 + {":coat:", "\xf0\x9f\xa7\xa5"}, // 🧥 + {":socks:", "\xf0\x9f\xa7\xa6"}, // 🧦 + {":dress:", "\xf0\x9f\x91\x97"}, // 👗 + {":kimono:", "\xf0\x9f\x91\x98"}, // 👘 + {":sari:", "\xf0\x9f\xa5\xbb"}, // 🥻 + {":one_piece_swimsuit:", "\xf0\x9f\xa9\xb1"}, // 🩱 + {":swim_brief:", "\xf0\x9f\xa9\xb2"}, // 🩲 + {":shorts:", "\xf0\x9f\xa9\xb3"}, // 🩳 + {":bikini:", "\xf0\x9f\x91\x99"}, // 👙 + {":womans_clothes:", "\xf0\x9f\x91\x9a"}, // 👚 + {":purse:", "\xf0\x9f\x91\x9b"}, // 👛 + {":handbag:", "\xf0\x9f\x91\x9c"}, // 👜 + {":pouch:", "\xf0\x9f\x91\x9d"}, // 👝 + {":shopping:", "\xf0\x9f\x9b\x8d\xef\xb8\x8f"}, // 🛍️ + {":school_satchel:", "\xf0\x9f\x8e\x92"}, // 🎒 + {":thong_sandal:", "\xf0\x9f\xa9\xb4"}, // 🩴 + {":mans_shoe:", "\xf0\x9f\x91\x9e"}, // 👞 + {":shoe:", "\xf0\x9f\x91\x9e"}, // 👞 + {":athletic_shoe:", "\xf0\x9f\x91\x9f"}, // 👟 + {":hiking_boot:", "\xf0\x9f\xa5\xbe"}, // 🥾 + {":flat_shoe:", "\xf0\x9f\xa5\xbf"}, // 🥿 + {":high_heel:", "\xf0\x9f\x91\xa0"}, // 👠 + {":sandal:", "\xf0\x9f\x91\xa1"}, // 👡 + {":ballet_shoes:", "\xf0\x9f\xa9\xb0"}, // 🩰 + {":boot:", "\xf0\x9f\x91\xa2"}, // 👢 + {":crown:", "\xf0\x9f\x91\x91"}, // 👑 + {":womans_hat:", "\xf0\x9f\x91\x92"}, // 👒 + {":tophat:", "\xf0\x9f\x8e\xa9"}, // 🎩 + {":mortar_board:", "\xf0\x9f\x8e\x93"}, // 🎓 + {":billed_cap:", "\xf0\x9f\xa7\xa2"}, // 🧢 + {":military_helmet:", "\xf0\x9f\xaa\x96"}, // 🪖 + {":rescue_worker_helmet:", "\xe2\x9b\x91\xef\xb8\x8f"}, // ⛑️ + {":prayer_beads:", "\xf0\x9f\x93\xbf"}, // 📿 + {":lipstick:", "\xf0\x9f\x92\x84"}, // 💄 + {":ring:", "\xf0\x9f\x92\x8d"}, // 💍 + {":gem:", "\xf0\x9f\x92\x8e"}, // 💎 + {":mute:", "\xf0\x9f\x94\x87"}, // 🔇 + {":speaker:", "\xf0\x9f\x94\x88"}, // 🔈 + {":sound:", "\xf0\x9f\x94\x89"}, // 🔉 + {":loud_sound:", "\xf0\x9f\x94\x8a"}, // 🔊 + {":loudspeaker:", "\xf0\x9f\x93\xa2"}, // 📢 + {":mega:", "\xf0\x9f\x93\xa3"}, // 📣 + {":postal_horn:", "\xf0\x9f\x93\xaf"}, // 📯 + {":bell:", "\xf0\x9f\x94\x94"}, // 🔔 + {":no_bell:", "\xf0\x9f\x94\x95"}, // 🔕 + {":musical_score:", "\xf0\x9f\x8e\xbc"}, // 🎼 + {":musical_note:", "\xf0\x9f\x8e\xb5"}, // 🎵 + {":notes:", "\xf0\x9f\x8e\xb6"}, // 🎶 + {":studio_microphone:", "\xf0\x9f\x8e\x99\xef\xb8\x8f"}, // 🎙️ + {":level_slider:", "\xf0\x9f\x8e\x9a\xef\xb8\x8f"}, // 🎚️ + {":control_knobs:", "\xf0\x9f\x8e\x9b\xef\xb8\x8f"}, // 🎛️ + {":microphone:", "\xf0\x9f\x8e\xa4"}, // 🎤 + {":headphones:", "\xf0\x9f\x8e\xa7"}, // 🎧 + {":radio:", "\xf0\x9f\x93\xbb"}, // 📻 + {":saxophone:", "\xf0\x9f\x8e\xb7"}, // 🎷 + {":accordion:", "\xf0\x9f\xaa\x97"}, // 🪗 + {":guitar:", "\xf0\x9f\x8e\xb8"}, // 🎸 + {":musical_keyboard:", "\xf0\x9f\x8e\xb9"}, // 🎹 + {":trumpet:", "\xf0\x9f\x8e\xba"}, // 🎺 + {":violin:", "\xf0\x9f\x8e\xbb"}, // 🎻 + {":banjo:", "\xf0\x9f\xaa\x95"}, // 🪕 + {":drum:", "\xf0\x9f\xa5\x81"}, // 🥁 + {":long_drum:", "\xf0\x9f\xaa\x98"}, // 🪘 + {":iphone:", "\xf0\x9f\x93\xb1"}, // 📱 + {":calling:", "\xf0\x9f\x93\xb2"}, // 📲 + {":phone:", "\xe2\x98\x8e\xef\xb8\x8f"}, // ☎️ + {":telephone:", "\xe2\x98\x8e\xef\xb8\x8f"}, // ☎️ + {":telephone_receiver:", "\xf0\x9f\x93\x9e"}, // 📞 + {":pager:", "\xf0\x9f\x93\x9f"}, // 📟 + {":fax:", "\xf0\x9f\x93\xa0"}, // 📠 + {":battery:", "\xf0\x9f\x94\x8b"}, // 🔋 + {":electric_plug:", "\xf0\x9f\x94\x8c"}, // 🔌 + {":computer:", "\xf0\x9f\x92\xbb"}, // 💻 + {":desktop_computer:", "\xf0\x9f\x96\xa5\xef\xb8\x8f"}, // 🖥️ + {":printer:", "\xf0\x9f\x96\xa8\xef\xb8\x8f"}, // 🖨️ + {":keyboard:", "\xe2\x8c\xa8\xef\xb8\x8f"}, // ⌨️ + {":computer_mouse:", "\xf0\x9f\x96\xb1\xef\xb8\x8f"}, // 🖱️ + {":trackball:", "\xf0\x9f\x96\xb2\xef\xb8\x8f"}, // 🖲️ + {":minidisc:", "\xf0\x9f\x92\xbd"}, // 💽 + {":floppy_disk:", "\xf0\x9f\x92\xbe"}, // 💾 + {":cd:", "\xf0\x9f\x92\xbf"}, // 💿 + {":dvd:", "\xf0\x9f\x93\x80"}, // 📀 + {":abacus:", "\xf0\x9f\xa7\xae"}, // 🧮 + {":movie_camera:", "\xf0\x9f\x8e\xa5"}, // 🎥 + {":film_strip:", "\xf0\x9f\x8e\x9e\xef\xb8\x8f"}, // 🎞️ + {":film_projector:", "\xf0\x9f\x93\xbd\xef\xb8\x8f"}, // 📽️ + {":clapper:", "\xf0\x9f\x8e\xac"}, // 🎬 + {":tv:", "\xf0\x9f\x93\xba"}, // 📺 + {":camera:", "\xf0\x9f\x93\xb7"}, // 📷 + {":camera_flash:", "\xf0\x9f\x93\xb8"}, // 📸 + {":video_camera:", "\xf0\x9f\x93\xb9"}, // 📹 + {":vhs:", "\xf0\x9f\x93\xbc"}, // 📼 + {":mag:", "\xf0\x9f\x94\x8d"}, // 🔍 + {":mag_right:", "\xf0\x9f\x94\x8e"}, // 🔎 + {":candle:", "\xf0\x9f\x95\xaf\xef\xb8\x8f"}, // 🕯️ + {":bulb:", "\xf0\x9f\x92\xa1"}, // 💡 + {":flashlight:", "\xf0\x9f\x94\xa6"}, // 🔦 + {":izakaya_lantern:", "\xf0\x9f\x8f\xae"}, // 🏮 + {":lantern:", "\xf0\x9f\x8f\xae"}, // 🏮 + {":diya_lamp:", "\xf0\x9f\xaa\x94"}, // 🪔 + {":notebook_with_decorative_cover:", "\xf0\x9f\x93\x94"}, // 📔 + {":closed_book:", "\xf0\x9f\x93\x95"}, // 📕 + {":book:", "\xf0\x9f\x93\x96"}, // 📖 + {":open_book:", "\xf0\x9f\x93\x96"}, // 📖 + {":green_book:", "\xf0\x9f\x93\x97"}, // 📗 + {":blue_book:", "\xf0\x9f\x93\x98"}, // 📘 + {":orange_book:", "\xf0\x9f\x93\x99"}, // 📙 + {":books:", "\xf0\x9f\x93\x9a"}, // 📚 + {":notebook:", "\xf0\x9f\x93\x93"}, // 📓 + {":ledger:", "\xf0\x9f\x93\x92"}, // 📒 + {":page_with_curl:", "\xf0\x9f\x93\x83"}, // 📃 + {":scroll:", "\xf0\x9f\x93\x9c"}, // 📜 + {":page_facing_up:", "\xf0\x9f\x93\x84"}, // 📄 + {":newspaper:", "\xf0\x9f\x93\xb0"}, // 📰 + {":newspaper_roll:", "\xf0\x9f\x97\x9e\xef\xb8\x8f"}, // 🗞️ + {":bookmark_tabs:", "\xf0\x9f\x93\x91"}, // 📑 + {":bookmark:", "\xf0\x9f\x94\x96"}, // 🔖 + {":label:", "\xf0\x9f\x8f\xb7\xef\xb8\x8f"}, // 🏷️ + {":moneybag:", "\xf0\x9f\x92\xb0"}, // 💰 + {":coin:", "\xf0\x9f\xaa\x99"}, // 🪙 + {":yen:", "\xf0\x9f\x92\xb4"}, // 💴 + {":dollar:", "\xf0\x9f\x92\xb5"}, // 💵 + {":euro:", "\xf0\x9f\x92\xb6"}, // 💶 + {":pound:", "\xf0\x9f\x92\xb7"}, // 💷 + {":money_with_wings:", "\xf0\x9f\x92\xb8"}, // 💸 + {":credit_card:", "\xf0\x9f\x92\xb3"}, // 💳 + {":receipt:", "\xf0\x9f\xa7\xbe"}, // 🧾 + {":chart:", "\xf0\x9f\x92\xb9"}, // 💹 + {":email:", "\xe2\x9c\x89\xef\xb8\x8f"}, // ✉️ + {":envelope:", "\xe2\x9c\x89\xef\xb8\x8f"}, // ✉️ + {":e-mail:", "\xf0\x9f\x93\xa7"}, // 📧 + {":incoming_envelope:", "\xf0\x9f\x93\xa8"}, // 📨 + {":envelope_with_arrow:", "\xf0\x9f\x93\xa9"}, // 📩 + {":outbox_tray:", "\xf0\x9f\x93\xa4"}, // 📤 + {":inbox_tray:", "\xf0\x9f\x93\xa5"}, // 📥 + {":package:", "\xf0\x9f\x93\xa6"}, // 📦 + {":mailbox:", "\xf0\x9f\x93\xab"}, // 📫 + {":mailbox_closed:", "\xf0\x9f\x93\xaa"}, // 📪 + {":mailbox_with_mail:", "\xf0\x9f\x93\xac"}, // 📬 + {":mailbox_with_no_mail:", "\xf0\x9f\x93\xad"}, // 📭 + {":postbox:", "\xf0\x9f\x93\xae"}, // 📮 + {":ballot_box:", "\xf0\x9f\x97\xb3\xef\xb8\x8f"}, // 🗳️ + {":pencil2:", "\xe2\x9c\x8f\xef\xb8\x8f"}, // ✏️ + {":black_nib:", "\xe2\x9c\x92\xef\xb8\x8f"}, // ✒️ + {":fountain_pen:", "\xf0\x9f\x96\x8b\xef\xb8\x8f"}, // 🖋️ + {":pen:", "\xf0\x9f\x96\x8a\xef\xb8\x8f"}, // 🖊️ + {":paintbrush:", "\xf0\x9f\x96\x8c\xef\xb8\x8f"}, // 🖌️ + {":crayon:", "\xf0\x9f\x96\x8d\xef\xb8\x8f"}, // 🖍️ + {":memo:", "\xf0\x9f\x93\x9d"}, // 📝 + {":pencil:", "\xf0\x9f\x93\x9d"}, // 📝 + {":briefcase:", "\xf0\x9f\x92\xbc"}, // 💼 + {":file_folder:", "\xf0\x9f\x93\x81"}, // 📁 + {":open_file_folder:", "\xf0\x9f\x93\x82"}, // 📂 + {":card_index_dividers:", "\xf0\x9f\x97\x82\xef\xb8\x8f"}, // 🗂️ + {":date:", "\xf0\x9f\x93\x85"}, // 📅 + {":calendar:", "\xf0\x9f\x93\x86"}, // 📆 + {":spiral_notepad:", "\xf0\x9f\x97\x92\xef\xb8\x8f"}, // 🗒️ + {":spiral_calendar:", "\xf0\x9f\x97\x93\xef\xb8\x8f"}, // 🗓️ + {":card_index:", "\xf0\x9f\x93\x87"}, // 📇 + {":chart_with_upwards_trend:", "\xf0\x9f\x93\x88"}, // 📈 + {":chart_with_downwards_trend:", "\xf0\x9f\x93\x89"}, // 📉 + {":bar_chart:", "\xf0\x9f\x93\x8a"}, // 📊 + {":clipboard:", "\xf0\x9f\x93\x8b"}, // 📋 + {":pushpin:", "\xf0\x9f\x93\x8c"}, // 📌 + {":round_pushpin:", "\xf0\x9f\x93\x8d"}, // 📍 + {":paperclip:", "\xf0\x9f\x93\x8e"}, // 📎 + {":paperclips:", "\xf0\x9f\x96\x87\xef\xb8\x8f"}, // 🖇️ + {":straight_ruler:", "\xf0\x9f\x93\x8f"}, // 📏 + {":triangular_ruler:", "\xf0\x9f\x93\x90"}, // 📐 + {":scissors:", "\xe2\x9c\x82\xef\xb8\x8f"}, // ✂️ + {":card_file_box:", "\xf0\x9f\x97\x83\xef\xb8\x8f"}, // 🗃️ + {":file_cabinet:", "\xf0\x9f\x97\x84\xef\xb8\x8f"}, // 🗄️ + {":wastebasket:", "\xf0\x9f\x97\x91\xef\xb8\x8f"}, // 🗑️ + {":lock:", "\xf0\x9f\x94\x92"}, // 🔒 + {":unlock:", "\xf0\x9f\x94\x93"}, // 🔓 + {":lock_with_ink_pen:", "\xf0\x9f\x94\x8f"}, // 🔏 + {":closed_lock_with_key:", "\xf0\x9f\x94\x90"}, // 🔐 + {":key:", "\xf0\x9f\x94\x91"}, // 🔑 + {":old_key:", "\xf0\x9f\x97\x9d\xef\xb8\x8f"}, // 🗝️ + {":hammer:", "\xf0\x9f\x94\xa8"}, // 🔨 + {":axe:", "\xf0\x9f\xaa\x93"}, // 🪓 + {":pick:", "\xe2\x9b\x8f\xef\xb8\x8f"}, // ⛏️ + {":hammer_and_pick:", "\xe2\x9a\x92\xef\xb8\x8f"}, // ⚒️ + {":hammer_and_wrench:", "\xf0\x9f\x9b\xa0\xef\xb8\x8f"}, // 🛠️ + {":dagger:", "\xf0\x9f\x97\xa1\xef\xb8\x8f"}, // 🗡️ + {":crossed_swords:", "\xe2\x9a\x94\xef\xb8\x8f"}, // ⚔️ + {":gun:", "\xf0\x9f\x94\xab"}, // 🔫 + {":boomerang:", "\xf0\x9f\xaa\x83"}, // 🪃 + {":bow_and_arrow:", "\xf0\x9f\x8f\xb9"}, // 🏹 + {":shield:", "\xf0\x9f\x9b\xa1\xef\xb8\x8f"}, // 🛡️ + {":carpentry_saw:", "\xf0\x9f\xaa\x9a"}, // 🪚 + {":wrench:", "\xf0\x9f\x94\xa7"}, // 🔧 + {":screwdriver:", "\xf0\x9f\xaa\x9b"}, // 🪛 + {":nut_and_bolt:", "\xf0\x9f\x94\xa9"}, // 🔩 + {":gear:", "\xe2\x9a\x99\xef\xb8\x8f"}, // ⚙️ + {":clamp:", "\xf0\x9f\x97\x9c\xef\xb8\x8f"}, // 🗜️ + {":balance_scale:", "\xe2\x9a\x96\xef\xb8\x8f"}, // ⚖️ + {":probing_cane:", "\xf0\x9f\xa6\xaf"}, // 🦯 + {":link:", "\xf0\x9f\x94\x97"}, // 🔗 + {":chains:", "\xe2\x9b\x93\xef\xb8\x8f"}, // ⛓️ + {":hook:", "\xf0\x9f\xaa\x9d"}, // 🪝 + {":toolbox:", "\xf0\x9f\xa7\xb0"}, // 🧰 + {":magnet:", "\xf0\x9f\xa7\xb2"}, // 🧲 + {":ladder:", "\xf0\x9f\xaa\x9c"}, // 🪜 + {":alembic:", "\xe2\x9a\x97\xef\xb8\x8f"}, // ⚗️ + {":test_tube:", "\xf0\x9f\xa7\xaa"}, // 🧪 + {":petri_dish:", "\xf0\x9f\xa7\xab"}, // 🧫 + {":dna:", "\xf0\x9f\xa7\xac"}, // 🧬 + {":microscope:", "\xf0\x9f\x94\xac"}, // 🔬 + {":telescope:", "\xf0\x9f\x94\xad"}, // 🔭 + {":satellite:", "\xf0\x9f\x93\xa1"}, // 📡 + {":syringe:", "\xf0\x9f\x92\x89"}, // 💉 + {":drop_of_blood:", "\xf0\x9f\xa9\xb8"}, // 🩸 + {":pill:", "\xf0\x9f\x92\x8a"}, // 💊 + {":adhesive_bandage:", "\xf0\x9f\xa9\xb9"}, // 🩹 + {":stethoscope:", "\xf0\x9f\xa9\xba"}, // 🩺 + {":door:", "\xf0\x9f\x9a\xaa"}, // 🚪 + {":elevator:", "\xf0\x9f\x9b\x97"}, // 🛗 + {":mirror:", "\xf0\x9f\xaa\x9e"}, // 🪞 + {":window:", "\xf0\x9f\xaa\x9f"}, // 🪟 + {":bed:", "\xf0\x9f\x9b\x8f\xef\xb8\x8f"}, // 🛏️ + {":couch_and_lamp:", "\xf0\x9f\x9b\x8b\xef\xb8\x8f"}, // 🛋️ + {":chair:", "\xf0\x9f\xaa\x91"}, // 🪑 + {":toilet:", "\xf0\x9f\x9a\xbd"}, // 🚽 + {":plunger:", "\xf0\x9f\xaa\xa0"}, // 🪠 + {":shower:", "\xf0\x9f\x9a\xbf"}, // 🚿 + {":bathtub:", "\xf0\x9f\x9b\x81"}, // 🛁 + {":mouse_trap:", "\xf0\x9f\xaa\xa4"}, // 🪤 + {":razor:", "\xf0\x9f\xaa\x92"}, // 🪒 + {":lotion_bottle:", "\xf0\x9f\xa7\xb4"}, // 🧴 + {":safety_pin:", "\xf0\x9f\xa7\xb7"}, // 🧷 + {":broom:", "\xf0\x9f\xa7\xb9"}, // 🧹 + {":basket:", "\xf0\x9f\xa7\xba"}, // 🧺 + {":roll_of_paper:", "\xf0\x9f\xa7\xbb"}, // 🧻 + {":bucket:", "\xf0\x9f\xaa\xa3"}, // 🪣 + {":soap:", "\xf0\x9f\xa7\xbc"}, // 🧼 + {":toothbrush:", "\xf0\x9f\xaa\xa5"}, // 🪥 + {":sponge:", "\xf0\x9f\xa7\xbd"}, // 🧽 + {":fire_extinguisher:", "\xf0\x9f\xa7\xaf"}, // 🧯 + {":shopping_cart:", "\xf0\x9f\x9b\x92"}, // 🛒 + {":smoking:", "\xf0\x9f\x9a\xac"}, // 🚬 + {":coffin:", "\xe2\x9a\xb0\xef\xb8\x8f"}, // ⚰️ + {":headstone:", "\xf0\x9f\xaa\xa6"}, // 🪦 + {":funeral_urn:", "\xe2\x9a\xb1\xef\xb8\x8f"}, // ⚱️ + {":moyai:", "\xf0\x9f\x97\xbf"}, // 🗿 + {":placard:", "\xf0\x9f\xaa\xa7"}, // 🪧 + {":atm:", "\xf0\x9f\x8f\xa7"}, // 🏧 + {":put_litter_in_its_place:", "\xf0\x9f\x9a\xae"}, // 🚮 + {":potable_water:", "\xf0\x9f\x9a\xb0"}, // 🚰 + {":wheelchair:", "\xe2\x99\xbf"}, // ♿ + {":mens:", "\xf0\x9f\x9a\xb9"}, // 🚹 + {":womens:", "\xf0\x9f\x9a\xba"}, // 🚺 + {":restroom:", "\xf0\x9f\x9a\xbb"}, // 🚻 + {":baby_symbol:", "\xf0\x9f\x9a\xbc"}, // 🚼 + {":wc:", "\xf0\x9f\x9a\xbe"}, // 🚾 + {":passport_control:", "\xf0\x9f\x9b\x82"}, // 🛂 + {":customs:", "\xf0\x9f\x9b\x83"}, // 🛃 + {":baggage_claim:", "\xf0\x9f\x9b\x84"}, // 🛄 + {":left_luggage:", "\xf0\x9f\x9b\x85"}, // 🛅 + {":warning:", "\xe2\x9a\xa0\xef\xb8\x8f"}, // ⚠️ + {":children_crossing:", "\xf0\x9f\x9a\xb8"}, // 🚸 + {":no_entry:", "\xe2\x9b\x94"}, // ⛔ + {":no_entry_sign:", "\xf0\x9f\x9a\xab"}, // 🚫 + {":no_bicycles:", "\xf0\x9f\x9a\xb3"}, // 🚳 + {":no_smoking:", "\xf0\x9f\x9a\xad"}, // 🚭 + {":do_not_litter:", "\xf0\x9f\x9a\xaf"}, // 🚯 + {":non-potable_water:", "\xf0\x9f\x9a\xb1"}, // 🚱 + {":no_pedestrians:", "\xf0\x9f\x9a\xb7"}, // 🚷 + {":no_mobile_phones:", "\xf0\x9f\x93\xb5"}, // 📵 + {":underage:", "\xf0\x9f\x94\x9e"}, // 🔞 + {":radioactive:", "\xe2\x98\xa2\xef\xb8\x8f"}, // ☢️ + {":biohazard:", "\xe2\x98\xa3\xef\xb8\x8f"}, // ☣️ + {":arrow_up:", "\xe2\xac\x86\xef\xb8\x8f"}, // ⬆️ + {":arrow_upper_right:", "\xe2\x86\x97\xef\xb8\x8f"}, // ↗️ + {":arrow_right:", "\xe2\x9e\xa1\xef\xb8\x8f"}, // ➡️ + {":arrow_lower_right:", "\xe2\x86\x98\xef\xb8\x8f"}, // ↘️ + {":arrow_down:", "\xe2\xac\x87\xef\xb8\x8f"}, // ⬇️ + {":arrow_lower_left:", "\xe2\x86\x99\xef\xb8\x8f"}, // ↙️ + {":arrow_left:", "\xe2\xac\x85\xef\xb8\x8f"}, // ⬅️ + {":arrow_upper_left:", "\xe2\x86\x96\xef\xb8\x8f"}, // ↖️ + {":arrow_up_down:", "\xe2\x86\x95\xef\xb8\x8f"}, // ↕️ + {":left_right_arrow:", "\xe2\x86\x94\xef\xb8\x8f"}, // ↔️ + {":leftwards_arrow_with_hook:", "\xe2\x86\xa9\xef\xb8\x8f"}, // ↩️ + {":arrow_right_hook:", "\xe2\x86\xaa\xef\xb8\x8f"}, // ↪️ + {":arrow_heading_up:", "\xe2\xa4\xb4\xef\xb8\x8f"}, // ⤴️ + {":arrow_heading_down:", "\xe2\xa4\xb5\xef\xb8\x8f"}, // ⤵️ + {":arrows_clockwise:", "\xf0\x9f\x94\x83"}, // 🔃 + {":arrows_counterclockwise:", "\xf0\x9f\x94\x84"}, // 🔄 + {":back:", "\xf0\x9f\x94\x99"}, // 🔙 + {":end:", "\xf0\x9f\x94\x9a"}, // 🔚 + {":on:", "\xf0\x9f\x94\x9b"}, // 🔛 + {":soon:", "\xf0\x9f\x94\x9c"}, // 🔜 + {":top:", "\xf0\x9f\x94\x9d"}, // 🔝 + {":place_of_worship:", "\xf0\x9f\x9b\x90"}, // 🛐 + {":atom_symbol:", "\xe2\x9a\x9b\xef\xb8\x8f"}, // ⚛️ + {":om:", "\xf0\x9f\x95\x89\xef\xb8\x8f"}, // 🕉️ + {":star_of_david:", "\xe2\x9c\xa1\xef\xb8\x8f"}, // ✡️ + {":wheel_of_dharma:", "\xe2\x98\xb8\xef\xb8\x8f"}, // ☸️ + {":yin_yang:", "\xe2\x98\xaf\xef\xb8\x8f"}, // ☯️ + {":latin_cross:", "\xe2\x9c\x9d\xef\xb8\x8f"}, // ✝️ + {":orthodox_cross:", "\xe2\x98\xa6\xef\xb8\x8f"}, // ☦️ + {":star_and_crescent:", "\xe2\x98\xaa\xef\xb8\x8f"}, // ☪️ + {":peace_symbol:", "\xe2\x98\xae\xef\xb8\x8f"}, // ☮️ + {":menorah:", "\xf0\x9f\x95\x8e"}, // 🕎 + {":six_pointed_star:", "\xf0\x9f\x94\xaf"}, // 🔯 + {":aries:", "\xe2\x99\x88"}, // ♈ + {":taurus:", "\xe2\x99\x89"}, // ♉ + {":gemini:", "\xe2\x99\x8a"}, // ♊ + {":cancer:", "\xe2\x99\x8b"}, // ♋ + {":leo:", "\xe2\x99\x8c"}, // ♌ + {":virgo:", "\xe2\x99\x8d"}, // ♍ + {":libra:", "\xe2\x99\x8e"}, // ♎ + {":scorpius:", "\xe2\x99\x8f"}, // ♏ + {":sagittarius:", "\xe2\x99\x90"}, // ♐ + {":capricorn:", "\xe2\x99\x91"}, // ♑ + {":aquarius:", "\xe2\x99\x92"}, // ♒ + {":pisces:", "\xe2\x99\x93"}, // ♓ + {":ophiuchus:", "\xe2\x9b\x8e"}, // ⛎ + {":twisted_rightwards_arrows:", "\xf0\x9f\x94\x80"}, // 🔀 + {":repeat:", "\xf0\x9f\x94\x81"}, // 🔁 + {":repeat_one:", "\xf0\x9f\x94\x82"}, // 🔂 + {":arrow_forward:", "\xe2\x96\xb6\xef\xb8\x8f"}, // ▶️ + {":fast_forward:", "\xe2\x8f\xa9"}, // ⏩ + {":next_track_button:", "\xe2\x8f\xad\xef\xb8\x8f"}, // ⏭️ + {":play_or_pause_button:", "\xe2\x8f\xaf\xef\xb8\x8f"}, // ⏯️ + {":arrow_backward:", "\xe2\x97\x80\xef\xb8\x8f"}, // ◀️ + {":rewind:", "\xe2\x8f\xaa"}, // ⏪ + {":previous_track_button:", "\xe2\x8f\xae\xef\xb8\x8f"}, // ⏮️ + {":arrow_up_small:", "\xf0\x9f\x94\xbc"}, // 🔼 + {":arrow_double_up:", "\xe2\x8f\xab"}, // ⏫ + {":arrow_down_small:", "\xf0\x9f\x94\xbd"}, // 🔽 + {":arrow_double_down:", "\xe2\x8f\xac"}, // ⏬ + {":pause_button:", "\xe2\x8f\xb8\xef\xb8\x8f"}, // ⏸️ + {":stop_button:", "\xe2\x8f\xb9\xef\xb8\x8f"}, // ⏹️ + {":record_button:", "\xe2\x8f\xba\xef\xb8\x8f"}, // ⏺️ + {":eject_button:", "\xe2\x8f\x8f\xef\xb8\x8f"}, // ⏏️ + {":cinema:", "\xf0\x9f\x8e\xa6"}, // 🎦 + {":low_brightness:", "\xf0\x9f\x94\x85"}, // 🔅 + {":high_brightness:", "\xf0\x9f\x94\x86"}, // 🔆 + {":signal_strength:", "\xf0\x9f\x93\xb6"}, // 📶 + {":vibration_mode:", "\xf0\x9f\x93\xb3"}, // 📳 + {":mobile_phone_off:", "\xf0\x9f\x93\xb4"}, // 📴 + {":female_sign:", "\xe2\x99\x80\xef\xb8\x8f"}, // ♀️ + {":male_sign:", "\xe2\x99\x82\xef\xb8\x8f"}, // ♂️ + {":transgender_symbol:", "\xe2\x9a\xa7\xef\xb8\x8f"}, // ⚧️ + {":heavy_multiplication_x:", "\xe2\x9c\x96\xef\xb8\x8f"}, // ✖️ + {":heavy_plus_sign:", "\xe2\x9e\x95"}, // ➕ + {":heavy_minus_sign:", "\xe2\x9e\x96"}, // ➖ + {":heavy_division_sign:", "\xe2\x9e\x97"}, // ➗ + {":infinity:", "\xe2\x99\xbe\xef\xb8\x8f"}, // ♾️ + {":bangbang:", "\xe2\x80\xbc\xef\xb8\x8f"}, // ‼️ + {":interrobang:", "\xe2\x81\x89\xef\xb8\x8f"}, // ⁉️ + {":question:", "\xe2\x9d\x93"}, // ❓ + {":grey_question:", "\xe2\x9d\x94"}, // ❔ + {":grey_exclamation:", "\xe2\x9d\x95"}, // ❕ + {":exclamation:", "\xe2\x9d\x97"}, // ❗ + {":heavy_exclamation_mark:", "\xe2\x9d\x97"}, // ❗ + {":wavy_dash:", "\xe3\x80\xb0\xef\xb8\x8f"}, // 〰️ + {":currency_exchange:", "\xf0\x9f\x92\xb1"}, // 💱 + {":heavy_dollar_sign:", "\xf0\x9f\x92\xb2"}, // 💲 + {":medical_symbol:", "\xe2\x9a\x95\xef\xb8\x8f"}, // ⚕️ + {":recycle:", "\xe2\x99\xbb\xef\xb8\x8f"}, // ♻️ + {":fleur_de_lis:", "\xe2\x9a\x9c\xef\xb8\x8f"}, // ⚜️ + {":trident:", "\xf0\x9f\x94\xb1"}, // 🔱 + {":name_badge:", "\xf0\x9f\x93\x9b"}, // 📛 + {":beginner:", "\xf0\x9f\x94\xb0"}, // 🔰 + {":o:", "\xe2\xad\x95"}, // ⭕ + {":white_check_mark:", "\xe2\x9c\x85"}, // ✅ + {":ballot_box_with_check:", "\xe2\x98\x91\xef\xb8\x8f"}, // ☑️ + {":heavy_check_mark:", "\xe2\x9c\x94\xef\xb8\x8f"}, // ✔️ + {":x:", "\xe2\x9d\x8c"}, // ❌ + {":negative_squared_cross_mark:", "\xe2\x9d\x8e"}, // ❎ + {":curly_loop:", "\xe2\x9e\xb0"}, // ➰ + {":loop:", "\xe2\x9e\xbf"}, // ➿ + {":part_alternation_mark:", "\xe3\x80\xbd\xef\xb8\x8f"}, // 〽️ + {":eight_spoked_asterisk:", "\xe2\x9c\xb3\xef\xb8\x8f"}, // ✳️ + {":eight_pointed_black_star:", "\xe2\x9c\xb4\xef\xb8\x8f"}, // ✴️ + {":sparkle:", "\xe2\x9d\x87\xef\xb8\x8f"}, // ❇️ + {":copyright:", "\xc2\xa9\xef\xb8\x8f"}, // ©️ + {":registered:", "\xc2\xae\xef\xb8\x8f"}, // ®️ + {":tm:", "\xe2\x84\xa2\xef\xb8\x8f"}, // ™️ + {":hash:", "\x23\xef\xb8\x8f\xe2\x83\xa3"}, // #️⃣ + {":asterisk:", "\x2a\xef\xb8\x8f\xe2\x83\xa3"}, // *️⃣ + {":zero:", "\x30\xef\xb8\x8f\xe2\x83\xa3"}, // 0️⃣ + {":one:", "\x31\xef\xb8\x8f\xe2\x83\xa3"}, // 1️⃣ + {":two:", "\x32\xef\xb8\x8f\xe2\x83\xa3"}, // 2️⃣ + {":three:", "\x33\xef\xb8\x8f\xe2\x83\xa3"}, // 3️⃣ + {":four:", "\x34\xef\xb8\x8f\xe2\x83\xa3"}, // 4️⃣ + {":five:", "\x35\xef\xb8\x8f\xe2\x83\xa3"}, // 5️⃣ + {":six:", "\x36\xef\xb8\x8f\xe2\x83\xa3"}, // 6️⃣ + {":seven:", "\x37\xef\xb8\x8f\xe2\x83\xa3"}, // 7️⃣ + {":eight:", "\x38\xef\xb8\x8f\xe2\x83\xa3"}, // 8️⃣ + {":nine:", "\x39\xef\xb8\x8f\xe2\x83\xa3"}, // 9️⃣ + {":keycap_ten:", "\xf0\x9f\x94\x9f"}, // 🔟 + {":capital_abcd:", "\xf0\x9f\x94\xa0"}, // 🔠 + {":abcd:", "\xf0\x9f\x94\xa1"}, // 🔡 + {":1234:", "\xf0\x9f\x94\xa2"}, // 🔢 + {":symbols:", "\xf0\x9f\x94\xa3"}, // 🔣 + {":abc:", "\xf0\x9f\x94\xa4"}, // 🔤 + {":a:", "\xf0\x9f\x85\xb0\xef\xb8\x8f"}, // 🅰️ + {":ab:", "\xf0\x9f\x86\x8e"}, // 🆎 + {":b:", "\xf0\x9f\x85\xb1\xef\xb8\x8f"}, // 🅱️ + {":cl:", "\xf0\x9f\x86\x91"}, // 🆑 + {":cool:", "\xf0\x9f\x86\x92"}, // 🆒 + {":free:", "\xf0\x9f\x86\x93"}, // 🆓 + {":information_source:", "\xe2\x84\xb9\xef\xb8\x8f"}, // ℹ️ + {":id:", "\xf0\x9f\x86\x94"}, // 🆔 + {":m:", "\xe2\x93\x82\xef\xb8\x8f"}, // Ⓜ️ + {":new:", "\xf0\x9f\x86\x95"}, // 🆕 + {":ng:", "\xf0\x9f\x86\x96"}, // 🆖 + {":o2:", "\xf0\x9f\x85\xbe\xef\xb8\x8f"}, // 🅾️ + {":ok:", "\xf0\x9f\x86\x97"}, // 🆗 + {":parking:", "\xf0\x9f\x85\xbf\xef\xb8\x8f"}, // 🅿️ + {":sos:", "\xf0\x9f\x86\x98"}, // 🆘 + {":up:", "\xf0\x9f\x86\x99"}, // 🆙 + {":vs:", "\xf0\x9f\x86\x9a"}, // 🆚 + {":koko:", "\xf0\x9f\x88\x81"}, // 🈁 + {":sa:", "\xf0\x9f\x88\x82\xef\xb8\x8f"}, // 🈂️ + {":u6708:", "\xf0\x9f\x88\xb7\xef\xb8\x8f"}, // 🈷️ + {":u6709:", "\xf0\x9f\x88\xb6"}, // 🈶 + {":u6307:", "\xf0\x9f\x88\xaf"}, // 🈯 + {":ideograph_advantage:", "\xf0\x9f\x89\x90"}, // 🉐 + {":u5272:", "\xf0\x9f\x88\xb9"}, // 🈹 + {":u7121:", "\xf0\x9f\x88\x9a"}, // 🈚 + {":u7981:", "\xf0\x9f\x88\xb2"}, // 🈲 + {":accept:", "\xf0\x9f\x89\x91"}, // 🉑 + {":u7533:", "\xf0\x9f\x88\xb8"}, // 🈸 + {":u5408:", "\xf0\x9f\x88\xb4"}, // 🈴 + {":u7a7a:", "\xf0\x9f\x88\xb3"}, // 🈳 + {":congratulations:", "\xe3\x8a\x97\xef\xb8\x8f"}, // ㊗️ + {":secret:", "\xe3\x8a\x99\xef\xb8\x8f"}, // ㊙️ + {":u55b6:", "\xf0\x9f\x88\xba"}, // 🈺 + {":u6e80:", "\xf0\x9f\x88\xb5"}, // 🈵 + {":red_circle:", "\xf0\x9f\x94\xb4"}, // 🔴 + {":orange_circle:", "\xf0\x9f\x9f\xa0"}, // 🟠 + {":yellow_circle:", "\xf0\x9f\x9f\xa1"}, // 🟡 + {":green_circle:", "\xf0\x9f\x9f\xa2"}, // 🟢 + {":large_blue_circle:", "\xf0\x9f\x94\xb5"}, // 🔵 + {":purple_circle:", "\xf0\x9f\x9f\xa3"}, // 🟣 + {":brown_circle:", "\xf0\x9f\x9f\xa4"}, // 🟤 + {":black_circle:", "\xe2\x9a\xab"}, // ⚫ + {":white_circle:", "\xe2\x9a\xaa"}, // ⚪ + {":red_square:", "\xf0\x9f\x9f\xa5"}, // 🟥 + {":orange_square:", "\xf0\x9f\x9f\xa7"}, // 🟧 + {":yellow_square:", "\xf0\x9f\x9f\xa8"}, // 🟨 + {":green_square:", "\xf0\x9f\x9f\xa9"}, // 🟩 + {":blue_square:", "\xf0\x9f\x9f\xa6"}, // 🟦 + {":purple_square:", "\xf0\x9f\x9f\xaa"}, // 🟪 + {":brown_square:", "\xf0\x9f\x9f\xab"}, // 🟫 + {":black_large_square:", "\xe2\xac\x9b"}, // ⬛ + {":white_large_square:", "\xe2\xac\x9c"}, // ⬜ + {":black_medium_square:", "\xe2\x97\xbc\xef\xb8\x8f"}, // ◼️ + {":white_medium_square:", "\xe2\x97\xbb\xef\xb8\x8f"}, // ◻️ + {":black_medium_small_square:", "\xe2\x97\xbe"}, // ◾ + {":white_medium_small_square:", "\xe2\x97\xbd"}, // ◽ + {":black_small_square:", "\xe2\x96\xaa\xef\xb8\x8f"}, // ▪️ + {":white_small_square:", "\xe2\x96\xab\xef\xb8\x8f"}, // ▫️ + {":large_orange_diamond:", "\xf0\x9f\x94\xb6"}, // 🔶 + {":large_blue_diamond:", "\xf0\x9f\x94\xb7"}, // 🔷 + {":small_orange_diamond:", "\xf0\x9f\x94\xb8"}, // 🔸 + {":small_blue_diamond:", "\xf0\x9f\x94\xb9"}, // 🔹 + {":small_red_triangle:", "\xf0\x9f\x94\xba"}, // 🔺 + {":small_red_triangle_down:", "\xf0\x9f\x94\xbb"}, // 🔻 + {":diamond_shape_with_a_dot_inside:", "\xf0\x9f\x92\xa0"}, // 💠 + {":radio_button:", "\xf0\x9f\x94\x98"}, // 🔘 + {":white_square_button:", "\xf0\x9f\x94\xb3"}, // 🔳 + {":black_square_button:", "\xf0\x9f\x94\xb2"}, // 🔲 + {":checkered_flag:", "\xf0\x9f\x8f\x81"}, // 🏁 + {":triangular_flag_on_post:", "\xf0\x9f\x9a\xa9"}, // 🚩 + {":crossed_flags:", "\xf0\x9f\x8e\x8c"}, // 🎌 + {":black_flag:", "\xf0\x9f\x8f\xb4"}, // 🏴 + {":white_flag:", "\xf0\x9f\x8f\xb3\xef\xb8\x8f"}, // 🏳️ + {":rainbow_flag:", "\xf0\x9f\x8f\xb3\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x8c\x88"}, // 🏳️‍🌈 + {":transgender_flag:", "\xf0\x9f\x8f\xb3\xef\xb8\x8f\xe2\x80\x8d\xe2\x9a\xa7\xef\xb8\x8f"}, // 🏳️‍⚧️ + {":pirate_flag:", "\xf0\x9f\x8f\xb4\xe2\x80\x8d\xe2\x98\xa0\xef\xb8\x8f"}, // 🏴‍☠️ + {":ascension_island:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xa8"}, // 🇦🇨 + {":andorra:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xa9"}, // 🇦🇩 + {":united_arab_emirates:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xaa"}, // 🇦🇪 + {":afghanistan:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xab"}, // 🇦🇫 + {":antigua_barbuda:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xac"}, // 🇦🇬 + {":anguilla:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xae"}, // 🇦🇮 + {":albania:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xb1"}, // 🇦🇱 + {":armenia:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xb2"}, // 🇦🇲 + {":angola:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xb4"}, // 🇦🇴 + {":antarctica:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xb6"}, // 🇦🇶 + {":argentina:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xb7"}, // 🇦🇷 + {":american_samoa:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xb8"}, // 🇦🇸 + {":austria:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xb9"}, // 🇦🇹 + {":australia:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xba"}, // 🇦🇺 + {":aruba:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xbc"}, // 🇦🇼 + {":aland_islands:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xbd"}, // 🇦🇽 + {":azerbaijan:", "\xf0\x9f\x87\xa6\xf0\x9f\x87\xbf"}, // 🇦🇿 + {":bosnia_herzegovina:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xa6"}, // 🇧🇦 + {":barbados:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xa7"}, // 🇧🇧 + {":bangladesh:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xa9"}, // 🇧🇩 + {":belgium:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xaa"}, // 🇧🇪 + {":burkina_faso:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xab"}, // 🇧🇫 + {":bulgaria:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xac"}, // 🇧🇬 + {":bahrain:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xad"}, // 🇧🇭 + {":burundi:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xae"}, // 🇧🇮 + {":benin:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xaf"}, // 🇧🇯 + {":st_barthelemy:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xb1"}, // 🇧🇱 + {":bermuda:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xb2"}, // 🇧🇲 + {":brunei:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xb3"}, // 🇧🇳 + {":bolivia:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xb4"}, // 🇧🇴 + {":caribbean_netherlands:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xb6"}, // 🇧🇶 + {":brazil:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xb7"}, // 🇧🇷 + {":bahamas:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xb8"}, // 🇧🇸 + {":bhutan:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xb9"}, // 🇧🇹 + {":bouvet_island:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xbb"}, // 🇧🇻 + {":botswana:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xbc"}, // 🇧🇼 + {":belarus:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xbe"}, // 🇧🇾 + {":belize:", "\xf0\x9f\x87\xa7\xf0\x9f\x87\xbf"}, // 🇧🇿 + {":canada:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xa6"}, // 🇨🇦 + {":cocos_islands:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xa8"}, // 🇨🇨 + {":congo_kinshasa:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xa9"}, // 🇨🇩 + {":central_african_republic:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xab"}, // 🇨🇫 + {":congo_brazzaville:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xac"}, // 🇨🇬 + {":switzerland:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xad"}, // 🇨🇭 + {":cote_divoire:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xae"}, // 🇨🇮 + {":cook_islands:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xb0"}, // 🇨🇰 + {":chile:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xb1"}, // 🇨🇱 + {":cameroon:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xb2"}, // 🇨🇲 + {":cn:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xb3"}, // 🇨🇳 + {":colombia:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xb4"}, // 🇨🇴 + {":clipperton_island:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xb5"}, // 🇨🇵 + {":costa_rica:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xb7"}, // 🇨🇷 + {":cuba:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xba"}, // 🇨🇺 + {":cape_verde:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xbb"}, // 🇨🇻 + {":curacao:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xbc"}, // 🇨🇼 + {":christmas_island:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xbd"}, // 🇨🇽 + {":cyprus:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xbe"}, // 🇨🇾 + {":czech_republic:", "\xf0\x9f\x87\xa8\xf0\x9f\x87\xbf"}, // 🇨🇿 + {":de:", "\xf0\x9f\x87\xa9\xf0\x9f\x87\xaa"}, // 🇩🇪 + {":diego_garcia:", "\xf0\x9f\x87\xa9\xf0\x9f\x87\xac"}, // 🇩🇬 + {":djibouti:", "\xf0\x9f\x87\xa9\xf0\x9f\x87\xaf"}, // 🇩🇯 + {":denmark:", "\xf0\x9f\x87\xa9\xf0\x9f\x87\xb0"}, // 🇩🇰 + {":dominica:", "\xf0\x9f\x87\xa9\xf0\x9f\x87\xb2"}, // 🇩🇲 + {":dominican_republic:", "\xf0\x9f\x87\xa9\xf0\x9f\x87\xb4"}, // 🇩🇴 + {":algeria:", "\xf0\x9f\x87\xa9\xf0\x9f\x87\xbf"}, // 🇩🇿 + {":ceuta_melilla:", "\xf0\x9f\x87\xaa\xf0\x9f\x87\xa6"}, // 🇪🇦 + {":ecuador:", "\xf0\x9f\x87\xaa\xf0\x9f\x87\xa8"}, // 🇪🇨 + {":estonia:", "\xf0\x9f\x87\xaa\xf0\x9f\x87\xaa"}, // 🇪🇪 + {":egypt:", "\xf0\x9f\x87\xaa\xf0\x9f\x87\xac"}, // 🇪🇬 + {":western_sahara:", "\xf0\x9f\x87\xaa\xf0\x9f\x87\xad"}, // 🇪🇭 + {":eritrea:", "\xf0\x9f\x87\xaa\xf0\x9f\x87\xb7"}, // 🇪🇷 + {":es:", "\xf0\x9f\x87\xaa\xf0\x9f\x87\xb8"}, // 🇪🇸 + {":ethiopia:", "\xf0\x9f\x87\xaa\xf0\x9f\x87\xb9"}, // 🇪🇹 + {":eu:", "\xf0\x9f\x87\xaa\xf0\x9f\x87\xba"}, // 🇪🇺 + {":european_union:", "\xf0\x9f\x87\xaa\xf0\x9f\x87\xba"}, // 🇪🇺 + {":finland:", "\xf0\x9f\x87\xab\xf0\x9f\x87\xae"}, // 🇫🇮 + {":fiji:", "\xf0\x9f\x87\xab\xf0\x9f\x87\xaf"}, // 🇫🇯 + {":falkland_islands:", "\xf0\x9f\x87\xab\xf0\x9f\x87\xb0"}, // 🇫🇰 + {":micronesia:", "\xf0\x9f\x87\xab\xf0\x9f\x87\xb2"}, // 🇫🇲 + {":faroe_islands:", "\xf0\x9f\x87\xab\xf0\x9f\x87\xb4"}, // 🇫🇴 + {":fr:", "\xf0\x9f\x87\xab\xf0\x9f\x87\xb7"}, // 🇫🇷 + {":gabon:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xa6"}, // 🇬🇦 + {":gb:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xa7"}, // 🇬🇧 + {":uk:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xa7"}, // 🇬🇧 + {":grenada:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xa9"}, // 🇬🇩 + {":georgia:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xaa"}, // 🇬🇪 + {":french_guiana:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xab"}, // 🇬🇫 + {":guernsey:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xac"}, // 🇬🇬 + {":ghana:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xad"}, // 🇬🇭 + {":gibraltar:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xae"}, // 🇬🇮 + {":greenland:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xb1"}, // 🇬🇱 + {":gambia:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xb2"}, // 🇬🇲 + {":guinea:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xb3"}, // 🇬🇳 + {":guadeloupe:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xb5"}, // 🇬🇵 + {":equatorial_guinea:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xb6"}, // 🇬🇶 + {":greece:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xb7"}, // 🇬🇷 + {":south_georgia_south_sandwich_islands:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xb8"}, // 🇬🇸 + {":guatemala:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xb9"}, // 🇬🇹 + {":guam:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xba"}, // 🇬🇺 + {":guinea_bissau:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xbc"}, // 🇬🇼 + {":guyana:", "\xf0\x9f\x87\xac\xf0\x9f\x87\xbe"}, // 🇬🇾 + {":hong_kong:", "\xf0\x9f\x87\xad\xf0\x9f\x87\xb0"}, // 🇭🇰 + {":heard_mcdonald_islands:", "\xf0\x9f\x87\xad\xf0\x9f\x87\xb2"}, // 🇭🇲 + {":honduras:", "\xf0\x9f\x87\xad\xf0\x9f\x87\xb3"}, // 🇭🇳 + {":croatia:", "\xf0\x9f\x87\xad\xf0\x9f\x87\xb7"}, // 🇭🇷 + {":haiti:", "\xf0\x9f\x87\xad\xf0\x9f\x87\xb9"}, // 🇭🇹 + {":hungary:", "\xf0\x9f\x87\xad\xf0\x9f\x87\xba"}, // 🇭🇺 + {":canary_islands:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xa8"}, // 🇮🇨 + {":indonesia:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xa9"}, // 🇮🇩 + {":ireland:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xaa"}, // 🇮🇪 + {":israel:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xb1"}, // 🇮🇱 + {":isle_of_man:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xb2"}, // 🇮🇲 + {":india:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xb3"}, // 🇮🇳 + {":british_indian_ocean_territory:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xb4"}, // 🇮🇴 + {":iraq:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xb6"}, // 🇮🇶 + {":iran:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xb7"}, // 🇮🇷 + {":iceland:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xb8"}, // 🇮🇸 + {":it:", "\xf0\x9f\x87\xae\xf0\x9f\x87\xb9"}, // 🇮🇹 + {":jersey:", "\xf0\x9f\x87\xaf\xf0\x9f\x87\xaa"}, // 🇯🇪 + {":jamaica:", "\xf0\x9f\x87\xaf\xf0\x9f\x87\xb2"}, // 🇯🇲 + {":jordan:", "\xf0\x9f\x87\xaf\xf0\x9f\x87\xb4"}, // 🇯🇴 + {":jp:", "\xf0\x9f\x87\xaf\xf0\x9f\x87\xb5"}, // 🇯🇵 + {":kenya:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xaa"}, // 🇰🇪 + {":kyrgyzstan:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xac"}, // 🇰🇬 + {":cambodia:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xad"}, // 🇰🇭 + {":kiribati:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xae"}, // 🇰🇮 + {":comoros:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xb2"}, // 🇰🇲 + {":st_kitts_nevis:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xb3"}, // 🇰🇳 + {":north_korea:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xb5"}, // 🇰🇵 + {":kr:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xb7"}, // 🇰🇷 + {":kuwait:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xbc"}, // 🇰🇼 + {":cayman_islands:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xbe"}, // 🇰🇾 + {":kazakhstan:", "\xf0\x9f\x87\xb0\xf0\x9f\x87\xbf"}, // 🇰🇿 + {":laos:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xa6"}, // 🇱🇦 + {":lebanon:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xa7"}, // 🇱🇧 + {":st_lucia:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xa8"}, // 🇱🇨 + {":liechtenstein:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xae"}, // 🇱🇮 + {":sri_lanka:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xb0"}, // 🇱🇰 + {":liberia:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xb7"}, // 🇱🇷 + {":lesotho:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xb8"}, // 🇱🇸 + {":lithuania:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xb9"}, // 🇱🇹 + {":luxembourg:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xba"}, // 🇱🇺 + {":latvia:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xbb"}, // 🇱🇻 + {":libya:", "\xf0\x9f\x87\xb1\xf0\x9f\x87\xbe"}, // 🇱🇾 + {":morocco:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xa6"}, // 🇲🇦 + {":monaco:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xa8"}, // 🇲🇨 + {":moldova:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xa9"}, // 🇲🇩 + {":montenegro:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xaa"}, // 🇲🇪 + {":st_martin:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xab"}, // 🇲🇫 + {":madagascar:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xac"}, // 🇲🇬 + {":marshall_islands:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xad"}, // 🇲🇭 + {":macedonia:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xb0"}, // 🇲🇰 + {":mali:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xb1"}, // 🇲🇱 + {":myanmar:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xb2"}, // 🇲🇲 + {":mongolia:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xb3"}, // 🇲🇳 + {":macau:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xb4"}, // 🇲🇴 + {":northern_mariana_islands:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xb5"}, // 🇲🇵 + {":martinique:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xb6"}, // 🇲🇶 + {":mauritania:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xb7"}, // 🇲🇷 + {":montserrat:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xb8"}, // 🇲🇸 + {":malta:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xb9"}, // 🇲🇹 + {":mauritius:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xba"}, // 🇲🇺 + {":maldives:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xbb"}, // 🇲🇻 + {":malawi:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xbc"}, // 🇲🇼 + {":mexico:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xbd"}, // 🇲🇽 + {":malaysia:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xbe"}, // 🇲🇾 + {":mozambique:", "\xf0\x9f\x87\xb2\xf0\x9f\x87\xbf"}, // 🇲🇿 + {":namibia:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xa6"}, // 🇳🇦 + {":new_caledonia:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xa8"}, // 🇳🇨 + {":niger:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xaa"}, // 🇳🇪 + {":norfolk_island:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xab"}, // 🇳🇫 + {":nigeria:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xac"}, // 🇳🇬 + {":nicaragua:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xae"}, // 🇳🇮 + {":netherlands:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xb1"}, // 🇳🇱 + {":norway:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xb4"}, // 🇳🇴 + {":nepal:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xb5"}, // 🇳🇵 + {":nauru:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xb7"}, // 🇳🇷 + {":niue:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xba"}, // 🇳🇺 + {":new_zealand:", "\xf0\x9f\x87\xb3\xf0\x9f\x87\xbf"}, // 🇳🇿 + {":oman:", "\xf0\x9f\x87\xb4\xf0\x9f\x87\xb2"}, // 🇴🇲 + {":panama:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xa6"}, // 🇵🇦 + {":peru:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xaa"}, // 🇵🇪 + {":french_polynesia:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xab"}, // 🇵🇫 + {":papua_new_guinea:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xac"}, // 🇵🇬 + {":philippines:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xad"}, // 🇵🇭 + {":pakistan:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xb0"}, // 🇵🇰 + {":poland:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xb1"}, // 🇵🇱 + {":st_pierre_miquelon:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xb2"}, // 🇵🇲 + {":pitcairn_islands:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xb3"}, // 🇵🇳 + {":puerto_rico:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xb7"}, // 🇵🇷 + {":palestinian_territories:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xb8"}, // 🇵🇸 + {":portugal:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xb9"}, // 🇵🇹 + {":palau:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xbc"}, // 🇵🇼 + {":paraguay:", "\xf0\x9f\x87\xb5\xf0\x9f\x87\xbe"}, // 🇵🇾 + {":qatar:", "\xf0\x9f\x87\xb6\xf0\x9f\x87\xa6"}, // 🇶🇦 + {":reunion:", "\xf0\x9f\x87\xb7\xf0\x9f\x87\xaa"}, // 🇷🇪 + {":romania:", "\xf0\x9f\x87\xb7\xf0\x9f\x87\xb4"}, // 🇷🇴 + {":serbia:", "\xf0\x9f\x87\xb7\xf0\x9f\x87\xb8"}, // 🇷🇸 + {":ru:", "\xf0\x9f\x87\xb7\xf0\x9f\x87\xba"}, // 🇷🇺 + {":rwanda:", "\xf0\x9f\x87\xb7\xf0\x9f\x87\xbc"}, // 🇷🇼 + {":saudi_arabia:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xa6"}, // 🇸🇦 + {":solomon_islands:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xa7"}, // 🇸🇧 + {":seychelles:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xa8"}, // 🇸🇨 + {":sudan:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xa9"}, // 🇸🇩 + {":sweden:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xaa"}, // 🇸🇪 + {":singapore:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xac"}, // 🇸🇬 + {":st_helena:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xad"}, // 🇸🇭 + {":slovenia:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xae"}, // 🇸🇮 + {":svalbard_jan_mayen:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xaf"}, // 🇸🇯 + {":slovakia:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xb0"}, // 🇸🇰 + {":sierra_leone:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xb1"}, // 🇸🇱 + {":san_marino:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xb2"}, // 🇸🇲 + {":senegal:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xb3"}, // 🇸🇳 + {":somalia:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xb4"}, // 🇸🇴 + {":suriname:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xb7"}, // 🇸🇷 + {":south_sudan:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xb8"}, // 🇸🇸 + {":sao_tome_principe:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xb9"}, // 🇸🇹 + {":el_salvador:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xbb"}, // 🇸🇻 + {":sint_maarten:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xbd"}, // 🇸🇽 + {":syria:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xbe"}, // 🇸🇾 + {":swaziland:", "\xf0\x9f\x87\xb8\xf0\x9f\x87\xbf"}, // 🇸🇿 + {":tristan_da_cunha:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xa6"}, // 🇹🇦 + {":turks_caicos_islands:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xa8"}, // 🇹🇨 + {":chad:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xa9"}, // 🇹🇩 + {":french_southern_territories:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xab"}, // 🇹🇫 + {":togo:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xac"}, // 🇹🇬 + {":thailand:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xad"}, // 🇹🇭 + {":tajikistan:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xaf"}, // 🇹🇯 + {":tokelau:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xb0"}, // 🇹🇰 + {":timor_leste:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xb1"}, // 🇹🇱 + {":turkmenistan:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xb2"}, // 🇹🇲 + {":tunisia:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xb3"}, // 🇹🇳 + {":tonga:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xb4"}, // 🇹🇴 + {":tr:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xb7"}, // 🇹🇷 + {":trinidad_tobago:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xb9"}, // 🇹🇹 + {":tuvalu:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xbb"}, // 🇹🇻 + {":taiwan:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xbc"}, // 🇹🇼 + {":tanzania:", "\xf0\x9f\x87\xb9\xf0\x9f\x87\xbf"}, // 🇹🇿 + {":ukraine:", "\xf0\x9f\x87\xba\xf0\x9f\x87\xa6"}, // 🇺🇦 + {":uganda:", "\xf0\x9f\x87\xba\xf0\x9f\x87\xac"}, // 🇺🇬 + {":us_outlying_islands:", "\xf0\x9f\x87\xba\xf0\x9f\x87\xb2"}, // 🇺🇲 + {":united_nations:", "\xf0\x9f\x87\xba\xf0\x9f\x87\xb3"}, // 🇺🇳 + {":us:", "\xf0\x9f\x87\xba\xf0\x9f\x87\xb8"}, // 🇺🇸 + {":uruguay:", "\xf0\x9f\x87\xba\xf0\x9f\x87\xbe"}, // 🇺🇾 + {":uzbekistan:", "\xf0\x9f\x87\xba\xf0\x9f\x87\xbf"}, // 🇺🇿 + {":vatican_city:", "\xf0\x9f\x87\xbb\xf0\x9f\x87\xa6"}, // 🇻🇦 + {":st_vincent_grenadines:", "\xf0\x9f\x87\xbb\xf0\x9f\x87\xa8"}, // 🇻🇨 + {":venezuela:", "\xf0\x9f\x87\xbb\xf0\x9f\x87\xaa"}, // 🇻🇪 + {":british_virgin_islands:", "\xf0\x9f\x87\xbb\xf0\x9f\x87\xac"}, // 🇻🇬 + {":us_virgin_islands:", "\xf0\x9f\x87\xbb\xf0\x9f\x87\xae"}, // 🇻🇮 + {":vietnam:", "\xf0\x9f\x87\xbb\xf0\x9f\x87\xb3"}, // 🇻🇳 + {":vanuatu:", "\xf0\x9f\x87\xbb\xf0\x9f\x87\xba"}, // 🇻🇺 + {":wallis_futuna:", "\xf0\x9f\x87\xbc\xf0\x9f\x87\xab"}, // 🇼🇫 + {":samoa:", "\xf0\x9f\x87\xbc\xf0\x9f\x87\xb8"}, // 🇼🇸 + {":kosovo:", "\xf0\x9f\x87\xbd\xf0\x9f\x87\xb0"}, // 🇽🇰 + {":yemen:", "\xf0\x9f\x87\xbe\xf0\x9f\x87\xaa"}, // 🇾🇪 + {":mayotte:", "\xf0\x9f\x87\xbe\xf0\x9f\x87\xb9"}, // 🇾🇹 + {":south_africa:", "\xf0\x9f\x87\xbf\xf0\x9f\x87\xa6"}, // 🇿🇦 + {":zambia:", "\xf0\x9f\x87\xbf\xf0\x9f\x87\xb2"}, // 🇿🇲 + {":zimbabwe:", "\xf0\x9f\x87\xbf\xf0\x9f\x87\xbc"}, // 🇿🇼 + {":england:", "\xf0\x9f\x8f\xb4\xf3\xa0\x81\xa7\xf3\xa0\x81\xa2\xf3\xa0\x81\xa5\xf3\xa0\x81\xae\xf3\xa0\x81\xa7\xf3\xa0\x81\xbf"}, // 🏴󠁧󠁢󠁥󠁮󠁧󠁿 + {":scotland:", "\xf0\x9f\x8f\xb4\xf3\xa0\x81\xa7\xf3\xa0\x81\xa2\xf3\xa0\x81\xb3\xf3\xa0\x81\xa3\xf3\xa0\x81\xb4\xf3\xa0\x81\xbf"}, // 🏴󠁧󠁢󠁳󠁣󠁴󠁿 + {":wales:", "\xf0\x9f\x8f\xb4\xf3\xa0\x81\xa7\xf3\xa0\x81\xa2\xf3\xa0\x81\xb7\xf3\xa0\x81\xac\xf3\xa0\x81\xb3\xf3\xa0\x81\xbf"}, // 🏴󠁧󠁢󠁷󠁬󠁳󠁿 {NULL, NULL} }; - #endif diff --git a/client/emojis_scrap_github.py b/client/emojis_scrap_github.py index 777bf8aa5..4c102e644 100755 --- a/client/emojis_scrap_github.py +++ b/client/emojis_scrap_github.py @@ -10,7 +10,11 @@ EMOJI_JSON_URL = 'https://raw.githubusercontent.com/github/gemoji/master/db/emoj def print_emoji(emoji_json): for alias in emoji_json['aliases']: - print(' {{":{0}:", "{1}"}},'.format(alias, emoji_json['emoji'])) + print(' {{":{0}:", "{1}"}}, // {2}'.format(alias, + +''.join('\\x{:02x}'.format(b) for b in emoji_json['emoji'].encode('utf8')), + +emoji_json['emoji'])) print( """#ifndef EMOJIS_H__ @@ -23,13 +27,12 @@ typedef struct emoji_s { // emoji_t array are expected to be NULL terminated static emoji_t EmojiTable[] = {""") + with urlopen(EMOJI_JSON_URL) as conn: emojis_json = json.loads(conn.read().decode('utf-8')) for emoji_json in emojis_json: print_emoji(emoji_json) -print( -""" {NULL, NULL} +print(""" {NULL, NULL} }; - #endif""") diff --git a/client/ui.c b/client/ui.c index 1c04def6c..e4343fec3 100644 --- a/client/ui.c +++ b/client/ui.c @@ -391,7 +391,7 @@ void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter) { static bool emojify_token(const char *token, uint8_t token_length, const char **emojified_token, uint8_t *emojified_token_length, emojiMode_t mode) { int i = 0; - while (EmojiTable[i].alias) { + while (EmojiTable[i].alias && EmojiTable[i].emoji) { if ((strlen(EmojiTable[i].alias) == token_length) && (0 == memcmp(EmojiTable[i].alias, token, token_length))) { switch (mode) { case EMOJI: { @@ -402,7 +402,7 @@ static bool emojify_token(const char *token, uint8_t token_length, const char ** case ALTTEXT: { int j = 0; *emojified_token_length = 0; - while (EmojiAltTable[j].alias) { + while (EmojiAltTable[j].alias && EmojiAltTable[i].alttext) { if ((strlen(EmojiAltTable[j].alias) == token_length) && (0 == memcmp(EmojiAltTable[j].alias, token, token_length))) { *emojified_token = EmojiAltTable[j].alttext; *emojified_token_length = strlen(EmojiAltTable[j].alttext); From 82077b2f1ce159cf225d58721086a2d724562a8c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 16 Mar 2020 18:42:34 +0100 Subject: [PATCH 152/298] hint now uses session struct, in preperation for a preference file. --- client/cmdmain.c | 17 ++++++----------- client/proxgui.h | 1 - client/ui.c | 2 +- client/ui.h | 1 + 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/client/cmdmain.c b/client/cmdmain.c index 57cd4d10a..8d4b1c8b7 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -196,30 +196,25 @@ static int CmdHints(const char *Cmd) { char ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 'h') return usage_hints(); - if (strlen(Cmd) < 1) { - PrintAndLogEx(INFO, "Hints are %s", (g_showhints) ? "ON" : "OFF"); - return PM3_SUCCESS; - } - if (strlen(Cmd) > 1){ str_lower((char *)Cmd); if (str_startswith(Cmd, "of")) { - g_showhints = false; + session.show_hints = false; } else { - g_showhints = true; + session.show_hints = true; } - } else { + } else if (strlen(Cmd) == 1) { if (param_getchar(Cmd, 0) != 0x00) { ms = param_get32ex(Cmd, 0, 0, 10); if (ms == 0) { - g_showhints = false; + session.show_hints = false; } else { - g_showhints = true; + session.show_hints = true; } } } - PrintAndLogEx(INFO, "Hints are %s", (g_showhints) ? "ON" : "OFF"); + PrintAndLogEx(INFO, "Hints are %s", (session.show_hints) ? "ON" : "OFF"); return PM3_SUCCESS; } diff --git a/client/proxgui.h b/client/proxgui.h index fea28d62b..c9cd0096d 100644 --- a/client/proxgui.h +++ b/client/proxgui.h @@ -55,7 +55,6 @@ extern size_t DemodBufferLen; extern size_t g_DemodStartIdx; extern bool showDemod; extern uint8_t g_debugMode; -extern uint8_t g_showhints; #ifndef FILE_PATH_SIZE #define FILE_PATH_SIZE 1000 diff --git a/client/ui.c b/client/ui.c index e4343fec3..d470647b7 100644 --- a/client/ui.c +++ b/client/ui.c @@ -131,7 +131,7 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) { return; // skip HINT messages if client has hints turned off i.e. 'HINT 0' - if (g_showhints == 0 && level == HINT) + if (session.show_hints == false && level == HINT) return; char prefix[40] = {0}; diff --git a/client/ui.h b/client/ui.h index 3b07caf46..5bb814b81 100644 --- a/client/ui.h +++ b/client/ui.h @@ -27,6 +27,7 @@ typedef struct { emojiMode_t emoji_mode; bool pm3_present; bool help_dump_mode; + bool show_hints; } session_arg_t; extern session_arg_t session; From 9f787faea647e013b838dd72b47115ed2a4ba92c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 16 Mar 2020 18:43:24 +0100 Subject: [PATCH 153/298] remove var --- client/util.h | 1 - 1 file changed, 1 deletion(-) diff --git a/client/util.h b/client/util.h index e010175a6..fb31e6013 100644 --- a/client/util.h +++ b/client/util.h @@ -23,7 +23,6 @@ uint8_t g_debugMode; uint8_t g_printAndLog; -uint8_t g_showhints; #define PRINTANDLOG_PRINT 1 #define PRINTANDLOG_LOG 2 From c769d661f135ad1002da63fd226dfee4996d940d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 16 Mar 2020 21:34:27 +0100 Subject: [PATCH 154/298] emoji -> alttext in logfiles --- client/ui.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/ui.c b/client/ui.c index d470647b7..177e495aa 100644 --- a/client/ui.c +++ b/client/ui.c @@ -331,10 +331,11 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { #endif if ((g_printAndLog & PRINTANDLOG_LOG) && logging && logfile) { + memcpy_filter_emoji(buffer3, buffer2, sizeof(buffer2), ALTTEXT); if (filter_ansi) { // already done - fprintf(logfile, "%s\n", buffer2); + fprintf(logfile, "%s\n", buffer3); } else { - memcpy_filter_ansi(buffer, buffer2, sizeof(buffer2), true); + memcpy_filter_ansi(buffer, buffer3, sizeof(buffer3), true); fprintf(logfile, "%s\n", buffer); } fflush(logfile); From 0a616d61f713781d95696c0e96f1562b9d7a3ca8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 16 Mar 2020 21:45:08 +0100 Subject: [PATCH 155/298] less emoji --- client/ui.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/client/ui.c b/client/ui.c index 177e495aa..df62b9bff 100644 --- a/client/ui.c +++ b/client/ui.c @@ -146,41 +146,31 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) { switch (level) { case ERR: if (session.emoji_mode == EMOJI) - strncpy(prefix, " :rotating_light: ", sizeof(prefix) - 1); + strncpy(prefix, _RED_("[!!]") " :rotating_light: ", sizeof(prefix) - 1); else strncpy(prefix, _RED_("[!!]"), sizeof(prefix) - 1); stream = stderr; break; case FAILED: if (session.emoji_mode == EMOJI) - strncpy(prefix, " :no_entry: ", sizeof(prefix) - 1); + strncpy(prefix, _RED_("[-]") " :no_entry: ", sizeof(prefix) - 1); else strncpy(prefix, _RED_("[-]"), sizeof(prefix) - 1); break; case DEBUG: - if (session.emoji_mode == EMOJI) - strncpy(prefix, " :speech_balloon: ", sizeof(prefix) - 1); - else - strncpy(prefix, _BLUE_("[#]"), sizeof(prefix) - 1); - break; + strncpy(prefix, _BLUE_("[#]"), sizeof(prefix) - 1); case HINT: case SUCCESS: - if (session.emoji_mode == EMOJI) - strncpy(prefix, " :star: ", sizeof(prefix) - 1); - else - strncpy(prefix, _GREEN_("[+]"), sizeof(prefix) - 1); + strncpy(prefix, _GREEN_("[+]"), sizeof(prefix) - 1); break; case WARNING: if (session.emoji_mode == EMOJI) - strncpy(prefix, " :warning: ", sizeof(prefix) - 1); + strncpy(prefix, _CYAN_("[!]") " :warning: ", sizeof(prefix) - 1); else strncpy(prefix, _CYAN_("[!]"), sizeof(prefix) - 1); break; case INFO: - if (session.emoji_mode == EMOJI) - strncpy(prefix, " :information_source: ", sizeof(prefix) - 1); - else - strncpy(prefix, _YELLOW_("[=]"), sizeof(prefix) - 1); + strncpy(prefix, _YELLOW_("[=]"), sizeof(prefix) - 1); break; case INPLACE: if (session.emoji_mode == EMOJI) { From 3fa86bf80b3cd978acc0964b9e0f5558cf6ddec4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 16 Mar 2020 21:45:17 +0100 Subject: [PATCH 156/298] iceman needs his coffee --- client/proxmark3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index c21852852..3217d0583 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -36,14 +36,14 @@ static void showBanner(void) { PrintAndLogEx(NORMAL, " " _BLUE_("██████╗ ███╗ ███╗ ████╗ ")); PrintAndLogEx(NORMAL, " " _BLUE_("██╔══██╗████╗ ████║ ══█║")); PrintAndLogEx(NORMAL, " " _BLUE_("██████╔╝██╔████╔██║ ████╔╝")); - PrintAndLogEx(NORMAL, " " _BLUE_("██╔═══╝ ██║╚██╔╝██║ ══█║") " :snowflake: iceman@icesql.net"); + PrintAndLogEx(NORMAL, " " _BLUE_("██╔═══╝ ██║╚██╔╝██║ ══█║") " :snowflake: iceman@icesql.net :coffee:"); PrintAndLogEx(NORMAL, " " _BLUE_("██║ ██║ ╚═╝ ██║ ████╔╝") " https://github.com/rfidresearchgroup/proxmark3/"); PrintAndLogEx(NORMAL, " " _BLUE_("╚═╝ ╚═╝ ╚═╝ ╚═══╝ ") "pre-release v4.0"); #else PrintAndLogEx(NORMAL, " ======. ===. ===. ====."); PrintAndLogEx(NORMAL, " ==...==.====. ====. ..=."); PrintAndLogEx(NORMAL, " ======..==.====.==. ====.."); - PrintAndLogEx(NORMAL, " ==..... ==..==..==. ..=. iceman@icesql.net"); + PrintAndLogEx(NORMAL, " ==..... ==..==..==. ..=. iceman@icesql.net :coffee:"); PrintAndLogEx(NORMAL, " ==. ==. ... ==. ====.. https://github.com/rfidresearchgroup/proxmark3/"); PrintAndLogEx(NORMAL, " ... ... ... ..... pre-release v4.0"); #endif From 7a7a3d014e8800f5644664962bf7d9089b819b53 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 16 Mar 2020 21:51:45 +0100 Subject: [PATCH 157/298] hf mfdes info - remake to work with Desfire Light. Switch to apdu framing. WIP --- armsrc/mifaredesfire.c | 77 +++++++++++------- client/cmdhfmfdes.c | 175 ++++++++++++++++++++++++++--------------- 2 files changed, 160 insertions(+), 92 deletions(-) diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index c13311051..cd47b5ca9 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -14,6 +14,7 @@ #include "crc16.h" #include "mbedtls/aes.h" #include "commonutil.h" +#include "util.h" #define MAX_APPLICATION_COUNT 28 #define MAX_FILE_COUNT 16 @@ -83,7 +84,7 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) { int len = DesfireAPDU(datain, datalen, resp); if (DBGLEVEL >= 4) - print_result("ERR <--: ", resp, len); + print_result("RESP <--: ", resp, len); if (!len) { OnError(2); @@ -96,16 +97,25 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) { if (flags & DISCONNECT) OnSuccess(); - reply_old(CMD_ACK, 1, len, 0, resp, len); + reply_mix(CMD_ACK, 1, len, 0, resp, len); } void MifareDesfireGetInformation() { + LEDsoff(); + int len = 0; iso14a_card_select_t card; uint8_t resp[PM3_CMD_DATA_SIZE] = {0x00}; - uint8_t dataout[PM3_CMD_DATA_SIZE] = {0x00}; + struct p { + uint8_t isOK; + uint8_t uid[7]; + uint8_t versionHW[7]; + uint8_t versionSW[7]; + uint8_t details[14]; + } PACKED payload; + /* 1 = PCB 1 2 = cid 2 @@ -122,61 +132,65 @@ void MifareDesfireGetInformation() { // card select - information if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) { if (DBGLEVEL >= DBG_ERROR) DbpString("Can't select card"); - OnError(1); + payload.isOK = 1; // 2 == can not select + reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload)); + switch_off(); return; } if (card.uidlen != 7) { if (DBGLEVEL >= DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen); - OnError(2); + payload.isOK = 2; // 2 == WRONG UID + reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload)); + switch_off(); return; } - - memcpy(dataout, card.uid, 7); + // add uid. + memcpy(payload.uid, card.uid, sizeof(card.uid)); LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - - uint8_t cmd[] = {GET_VERSION}; + uint8_t cmd[] = {GET_VERSION, 0x00, 0x00, 0x00}; size_t cmd_len = sizeof(cmd); len = DesfireAPDU(cmd, cmd_len, resp); if (!len) { print_result("ERROR <--: ", resp, len); - OnError(3); + payload.isOK = 3; // 3 == DOESNT ANSWER TO GET_VERSION + reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload)); + switch_off(); return; } - LED_A_OFF(); - LED_B_ON(); - memcpy(dataout + 7, resp + 3, 7); + memcpy(payload.versionHW, resp + 1, sizeof(payload.versionHW)); // ADDITION_FRAME 1 cmd[0] = ADDITIONAL_FRAME; len = DesfireAPDU(cmd, cmd_len, resp); if (!len) { print_result("ERROR <--: ", resp, len); - OnError(3); + payload.isOK = 3; // 3 == DOESNT ANSWER TO GET_VERSION + reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload)); + switch_off(); return; } - - LED_B_OFF(); - LED_C_ON(); - memcpy(dataout + 7 + 7, resp + 3, 7); + memcpy(payload.versionSW, resp + 1, sizeof(payload.versionSW)); // ADDITION_FRAME 2 len = DesfireAPDU(cmd, cmd_len, resp); if (!len) { print_result("ERROR <--: ", resp, len); - OnError(3); + payload.isOK = 3; // 3 == DOESNT ANSWER TO GET_VERSION + reply_ng(CMD_HF_DESFIRE_INFO, PM3_ESOFT, (uint8_t *)&payload, sizeof(payload)); + switch_off(); return; } - memcpy(dataout + 7 + 7 + 7, resp + 3, 14); - - reply_old(CMD_ACK, 1, 0, 0, dataout, sizeof(dataout)); + memcpy(payload.details, resp + 1, sizeof(payload.details)); + LED_B_ON(); + reply_ng(CMD_HF_DESFIRE_INFO, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload)); + LED_B_OFF(); + // reset the pcb_blocknum, pcb_blocknum = 0; OnSuccess(); @@ -517,7 +531,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) } OnSuccess(); - reply_old(CMD_ACK, 1, len, 0, resp, len); + reply_mix(CMD_ACK, 1, len, 0, resp, len); } // 3 different ISO ways to send data to a DESFIRE (direct, capsuled, capsuled ISO) @@ -565,15 +579,20 @@ size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) { uint8_t cmd[cmdlen]; memset(cmd, 0, cmdlen); - cmd[0] = 0x0A; // 0x0A = send cid, 0x02 = no cid. + cmd[0] = 0x02; // 0x0A = send cid, 0x02 = no cid. cmd[0] |= pcb_blocknum; // OR the block number into the PCB - cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards + + cmd[1] = 0x90; // CID: 0x00 //TODO: allow multiple selected cards memcpy(cmd + 2, datain, len); AddCrc14A(cmd, len + 2); - + +/* +hf 14a apdu -sk 90 60 00 00 00 +hf 14a apdu -k 90 AF 00 00 00 +hf 14a apdu 90AF000000 +*/ memcpy(dataout, cmd, cmdlen); - return cmdlen; } diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 698af4a2d..d9790726d 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -31,13 +31,24 @@ static int CmdHF14ADesInfo(const char *Cmd) { SendCommandNG(CMD_HF_DESFIRE_INFO, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + if (!WaitForResponseTimeout(CMD_HF_DESFIRE_INFO, &resp, 1500)) { PrintAndLogEx(WARNING, "Command execute timeout"); return PM3_ETIMEOUT; } - uint8_t isOK = resp.oldarg[0] & 0xff; - if (!isOK) { - switch (resp.oldarg[1]) { + + struct p { + uint8_t isOK; + uint8_t uid[7]; + uint8_t versionHW[7]; + uint8_t versionSW[7]; + uint8_t details[14]; + } PACKED; + + struct p *package = (struct p *) resp.data.asBytes; + + if (resp.status != PM3_SUCCESS) { + + switch (package->isOK) { case 1: PrintAndLogEx(WARNING, "Can't select card"); break; @@ -51,45 +62,49 @@ static int CmdHF14ADesInfo(const char *Cmd) { } return PM3_ESOFT; } + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-- Desfire Information --------------------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); - PrintAndLogEx(SUCCESS, " UID : " _GREEN_("%s"), sprint_hex(resp.data.asBytes, 7)); - PrintAndLogEx(SUCCESS, " Batch number : " _GREEN_("%s"), sprint_hex(resp.data.asBytes + 28, 5)); - PrintAndLogEx(SUCCESS, " Production date : week %02x, 20%02x", resp.data.asBytes[33], resp.data.asBytes[34]); + PrintAndLogEx(SUCCESS, " UID : " _GREEN_("%s"), sprint_hex(package->uid, sizeof(package->uid))); + PrintAndLogEx(SUCCESS, " Batch number : " _GREEN_("%s"), sprint_hex(package->details + 7, 5)); + PrintAndLogEx(SUCCESS, " Production date : week " _GREEN_("%02x") "/ " _GREEN_("20%02x"), package->details[12], package->details[13]); PrintAndLogEx(INFO, " -----------------------------------------------------------"); PrintAndLogEx(INFO, " Hardware Information"); - PrintAndLogEx(SUCCESS, " Vendor Id : " _YELLOW_("%s"), getTagInfo(resp.data.asBytes[7])); - PrintAndLogEx(SUCCESS, " Type : " _YELLOW_("0x%02X"), resp.data.asBytes[8]); - PrintAndLogEx(SUCCESS, " Subtype : " _YELLOW_("0x%02X"), resp.data.asBytes[9]); - PrintAndLogEx(SUCCESS, " Version : " _YELLOW_("%s"), getVersionStr(resp.data.asBytes[10], resp.data.asBytes[11])); - PrintAndLogEx(SUCCESS, " Storage size : " _YELLOW_("%s"), getCardSizeStr(resp.data.asBytes[12])); - PrintAndLogEx(SUCCESS, " Protocol : " _YELLOW_("%s"), getProtocolStr(resp.data.asBytes[13])); + PrintAndLogEx(SUCCESS, " Vendor Id : " _YELLOW_("%s"), getTagInfo(package->versionHW[0])); + PrintAndLogEx(SUCCESS, " Type : " _YELLOW_("0x%02X"), package->versionHW[1]); + PrintAndLogEx(SUCCESS, " Subtype : " _YELLOW_("0x%02X"), package->versionHW[2]); + PrintAndLogEx(SUCCESS, " Version : %s", getVersionStr(package->versionHW[3], package->versionHW[4])); + PrintAndLogEx(SUCCESS, " Storage size : %s", getCardSizeStr(package->versionHW[5])); + PrintAndLogEx(SUCCESS, " Protocol : %s", getProtocolStr(package->versionHW[6])); PrintAndLogEx(INFO, " -----------------------------------------------------------"); PrintAndLogEx(INFO, " Software Information"); - PrintAndLogEx(SUCCESS, " Vendor Id : " _YELLOW_("%s"), getTagInfo(resp.data.asBytes[14])); - PrintAndLogEx(SUCCESS, " Type : " _YELLOW_("0x%02X"), resp.data.asBytes[15]); - PrintAndLogEx(SUCCESS, " Subtype : " _YELLOW_("0x%02X"), resp.data.asBytes[16]); - PrintAndLogEx(SUCCESS, " Version : " _YELLOW_("%d.%d"), resp.data.asBytes[17], resp.data.asBytes[18]); - PrintAndLogEx(SUCCESS, " storage size : " _YELLOW_("%s"), getCardSizeStr(resp.data.asBytes[19])); - PrintAndLogEx(SUCCESS, " Protocol : " _YELLOW_("%s"), getProtocolStr(resp.data.asBytes[20])); + PrintAndLogEx(SUCCESS, " Vendor Id : " _YELLOW_("%s"), getTagInfo(package->versionSW[0])); + PrintAndLogEx(SUCCESS, " Type : " _YELLOW_("0x%02X"), package->versionSW[1]); + PrintAndLogEx(SUCCESS, " Subtype : " _YELLOW_("0x%02X"), package->versionSW[2]); + PrintAndLogEx(SUCCESS, " Version : " _YELLOW_("%d.%d"), package->versionSW[3], package->versionSW[4]); + PrintAndLogEx(SUCCESS, " storage size : %s", getCardSizeStr(package->versionSW[5])); + PrintAndLogEx(SUCCESS, " Protocol : %s", getProtocolStr(package->versionSW[6])); PrintAndLogEx(INFO, "-------------------------------------------------------------"); // Master Key settings getKeySettings(NULL); // Free memory on card - uint8_t data[1] = {GET_FREE_MEMORY}; - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, (INIT | DISCONNECT), 0x01, 0, data, sizeof(data)); + uint8_t c[] = {GET_FREE_MEMORY, 0x00, 0x00, 0x00}; // 0x6E + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, (INIT | DISCONNECT), sizeof(c), 0, c, sizeof(c)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return PM3_ETIMEOUT; - uint8_t tmp[3]; - memcpy(tmp, resp.data.asBytes + 3, 3); - - PrintAndLogEx(SUCCESS, " Available free memory on card : " _GREEN_("%d bytes"), le24toh(tmp)); + // Desfire Light doesn't support FREEMEM (len = 5) + if (resp.length == 8) { + uint8_t tmp[3]; + memcpy(tmp, resp.data.asBytes + 1, 3); + PrintAndLogEx(SUCCESS, " Available free memory on card : " _GREEN_("%d bytes"), le24toh(tmp)); + } else { + PrintAndLogEx(SUCCESS, " Card doesn't support 'free mem' cmd"); + } PrintAndLogEx(INFO, "-------------------------------------------------------------"); - /* Card Master key (CMK) 0x00 AID = 00 00 00 (card level) Application Master Key (AMK) 0x00 AID != 00 00 00 @@ -116,7 +131,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { */ char *getCardSizeStr(uint8_t fsize) { - static char buf[30] = {0x00}; + static char buf[40] = {0x00}; char *retStr = buf; uint16_t usize = 1 << ((fsize >> 1) + 1); @@ -124,37 +139,39 @@ char *getCardSizeStr(uint8_t fsize) { // is LSB set? if (fsize & 1) - sprintf(retStr, "0x%02X (%d - %d bytes)", fsize, usize, lsize); + sprintf(retStr, "0x%02X ( " _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize); else - sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize); + sprintf(retStr, "0x%02X ( " _YELLOW_("%d bytes") ")", fsize, lsize); return buf; } char *getProtocolStr(uint8_t id) { - static char buf[30] = {0x00}; + static char buf[40] = {0x00}; char *retStr = buf; if (id == 0x05) - sprintf(retStr, "0x%02X (ISO 14443-3, 14443-4)", id); + sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3, 14443-4") ")", id); else - sprintf(retStr, "0x%02X (Unknown)", id); + sprintf(retStr, "0x%02X ( " _YELLOW_("Unknown") ")", id); return buf; } char *getVersionStr(uint8_t major, uint8_t minor) { - static char buf[30] = {0x00}; + static char buf[40] = {0x00}; char *retStr = buf; if (major == 0x00) - sprintf(retStr, "%d.%d (Desfire MF3ICD40)", major, minor); + sprintf(retStr, "%x.%x ( " _YELLOW_("Desfire MF3ICD40") ")", major, minor); else if (major == 0x01 && minor == 0x00) - sprintf(retStr, "%d.%d (Desfire EV1)", major, minor); + sprintf(retStr, "%x.%x ( " _YELLOW_("Desfire EV1") ")", major, minor); else if (major == 0x12 && minor == 0x00) - sprintf(retStr, "%d.%d (Desfire EV2)", major, minor); + sprintf(retStr, "%x.%x ( " _YELLOW_("Desfire EV2") ")", major, minor); + else if (major == 0x30 && minor == 0x00) + sprintf(retStr, "%x.%x ( " _YELLOW_("Desfire Light") ")", major, minor); else - sprintf(retStr, "%d.%d (Unknown)", major, minor); + sprintf(retStr, "%x.%x ( " _YELLOW_("Unknown") ")", major, minor); return buf; } @@ -165,14 +182,15 @@ void getKeySettings(uint8_t *aid) { uint8_t isOK = 0; PacketResponseNG resp; - //memset(messStr, 0x00, 512); - if (aid == NULL) { + + // CARD MASTER KEY + PrintAndLogEx(SUCCESS, " CMK - PICC, Card Master Key settings"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); { - uint8_t data[1] = {GET_KEY_SETTINGS}; // 0x45 - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + uint8_t data[] = {GET_KEY_SETTINGS, 0x00, 0x00, 0x00}; // 0x45 + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.oldarg[0] & 0xff; @@ -180,18 +198,41 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(WARNING, _RED_(" Can't select master application")); return; } + // Not supported 02 91 1c c4 ca + // OK - 02 0f 01 91 00 7e fe + if (resp.length == 7 ) { + + // number of Master keys (0x01) + PrintAndLogEx(SUCCESS, " [0x08] Number of Masterkeys : %u", resp.data.asBytes[2]); + uint8_t setting = (resp.data.asBytes[2] >> 6); + switch(setting) { + case 0: + PrintAndLogEx(SUCCESS, " [00] (3)DES operation of PICC master key"); + break; + case 1: + PrintAndLogEx(SUCCESS, " [01] 3K3DES operation of PICC master key"); + break; + case 2: + PrintAndLogEx(SUCCESS, " [02] AES operation of PICC master key"); + break; + default: + break; + } + + str = (resp.data.asBytes[2] & (1 << 3)) ? _GREEN_("YES") : "NO"; + PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", str); + str = (resp.data.asBytes[2] & (1 << 2)) ? "NO" : _GREEN_("YES"); + PrintAndLogEx(SUCCESS, " [0x04] CMK required for create/delete : %s", str); + str = (resp.data.asBytes[2] & (1 << 1)) ? "NO" : _GREEN_("YES"); + PrintAndLogEx(SUCCESS, " [0x02] Directory list access with CMK : %s", str); + str = (resp.data.asBytes[2] & (1 << 0)) ? _GREEN_("YES") : "NO"; + PrintAndLogEx(SUCCESS, " [0x01] CMK is changeable : %s", str); + } - str = (resp.data.asBytes[3] & (1 << 3)) ? _GREEN_("YES") : "NO"; - PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", str); - str = (resp.data.asBytes[3] & (1 << 2)) ? "NO" : _GREEN_("YES"); - PrintAndLogEx(SUCCESS, " [0x04] CMK required for create/delete : %s", str); - str = (resp.data.asBytes[3] & (1 << 1)) ? "NO" : _GREEN_("YES"); - PrintAndLogEx(SUCCESS, " [0x02] Directory list access with CMK : %s", str); - str = (resp.data.asBytes[3] & (1 << 0)) ? _GREEN_("YES") : "NO"; - PrintAndLogEx(SUCCESS, " [0x01] CMK is changeable : %s", str); - - { - uint8_t data[2] = {GET_KEY_VERSION, 0}; // 0x64 + // dd == key version + // cla ins p1 p2 lc dd le + { // 90, 64, + uint8_t data[] = {GET_KEY_VERSION, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x64 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } @@ -201,13 +242,17 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(WARNING, _RED_(" Can't read key-version")); return; } - PrintAndLogEx(SUCCESS, ""); - PrintAndLogEx(SUCCESS, " Max number of keys : " _YELLOW_("%d"), resp.data.asBytes[4]); - PrintAndLogEx(SUCCESS, " Master key Version : " _YELLOW_("%d (0x%02x)"), resp.data.asBytes[3], resp.data.asBytes[3]); - PrintAndLogEx(INFO, " ----------------------------------------------------------"); + if (resp.length == 6) { + PrintAndLogEx(SUCCESS, ""); + PrintAndLogEx(SUCCESS, " Max number of keys : " _YELLOW_("%d"), resp.data.asBytes[1]); + PrintAndLogEx(SUCCESS, " Master key Version : " _YELLOW_("%d (0x%02x)"), resp.data.asBytes[3], resp.data.asBytes[3]); + PrintAndLogEx(INFO, " ----------------------------------------------------------"); + } + { - uint8_t data[2] = {AUTHENTICATE, 0}; // 0x0A, KEY 0 + // cla ins p1 p2 lc dd le + uint8_t data[] = {AUTHENTICATE, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x0A, KEY 0 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } @@ -216,7 +261,7 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); { - uint8_t data[2] = {AUTHENTICATE_ISO, 0}; // 0x1A, KEY 0 + uint8_t data[] = {AUTHENTICATE_ISO, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x1A, KEY 0 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } @@ -225,7 +270,7 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); { - uint8_t data[2] = {AUTHENTICATE_AES, 0}; // 0xAA, KEY 0 + uint8_t data[] = {AUTHENTICATE_AES, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0xAA, KEY 0 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } @@ -235,15 +280,20 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(INFO, "-------------------------------------------------------------"); } else { + + // AID - APPLICATIO MASTER KEYS + PrintAndLogEx(SUCCESS, " AMK - Application Master Key settings"); PrintAndLogEx(INFO, " ----------------------------------------------------------"); + PrintAndLogEx(INFO, "Selecting AID: %s", sprint_hex(aid, 3) ); // SELECT AID { - uint8_t data[4] = {SELECT_APPLICATION}; // 0x5a + uint8_t data[] = {SELECT_APPLICATION, 0x00, 0x00, 0x00}; // 0x5a memcpy(data + 1, aid, 3); SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | CLEARTRACE, sizeof(data), 0, data, sizeof(data)); } + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, _RED_(" Timed-out")); return; @@ -256,7 +306,7 @@ void getKeySettings(uint8_t *aid) { // KEY SETTINGS { - uint8_t data[1] = {GET_KEY_SETTINGS}; // 0x45 + uint8_t data[] = {GET_KEY_SETTINGS, 0x00, 0x00, 0x00}; // 0x45 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } @@ -299,7 +349,7 @@ void getKeySettings(uint8_t *aid) { // KEY VERSION - AMK { - uint8_t data[2] = {GET_KEY_VERSION, 0}; // 0x64 + uint8_t data[] = {GET_KEY_VERSION, 0x00, 0x00, 0x00}; // 0x64 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } @@ -541,7 +591,6 @@ static int CmdHF14ADesAuth(const char *Cmd) { return PM3_SUCCESS; } - static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"info", CmdHF14ADesInfo, IfPm3Iso14443a, "Tag information"}, From 1cb495e40b479ed88d5bec4d7a3ff7f3f9fa5c2a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 17 Mar 2020 01:50:27 +0100 Subject: [PATCH 158/298] add desfire light signature verification check --- armsrc/mifaredesfire.c | 1 + client/cmdhfmfdes.c | 70 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index cd47b5ca9..3a3d0007c 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -32,6 +32,7 @@ static uint8_t deselect_cmd[] = {0xc2, 0xe0, 0xb4}; /* PCB CID CMD PAYLOAD */ //static uint8_t __res[MAX_FRAME_SIZE]; + bool InitDesfireCard() { iso14a_card_select_t card; diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index d9790726d..7d6a6162c 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -17,6 +17,8 @@ #include "ui.h" #include "cmdhf14a.h" #include "mbedtls/des.h" +#include "crypto/libpcrypto.h" +#include "protocols.h" uint8_t key_zero_data[16] = { 0x00 }; uint8_t key_ones_data[16] = { 0x01 }; @@ -25,6 +27,63 @@ uint8_t key_picc_data[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x static int CmdHelp(const char *Cmd); +static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len) { + #define PUBLIC_DESFIRE_ECDA_KEYLEN 57 + + // ref: MIFARE Desfire Originality Signature Validation + uint8_t nxp_desfire_keys[1][PUBLIC_DESFIRE_ECDA_KEYLEN] = { + // DESFire Light + { + 0x04, 0x0E, 0x98, 0xE1, 0x17, 0xAA, 0xA3, 0x64, + 0x57, 0xF4, 0x31, 0x73, 0xDC, 0x92, 0x0A, 0x87, + 0x57, 0x26, 0x7F, 0x44, 0xCE, 0x4E, 0xC5, 0xAD, + 0xD3, 0xC5, 0x40, 0x75, 0x57, 0x1A, 0xEB, 0xBF, + 0x7B, 0x94, 0x2A, 0x97, 0x74, 0xA1, 0xD9, 0x4A, + 0xD0, 0x25, 0x72, 0x42, 0x7E, 0x5A, 0xE0, 0xA2, + 0xDD, 0x36, 0x59, 0x1B, 0x1F, 0xB3, 0x4F, 0xCF, 0x3D + } + // DESFire Ev2 + + }; + + uint8_t public_key = 0; + int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, nxp_desfire_keys[public_key], uid, 7, signature, signature_len, false); + bool is_valid = (res == 0); + + PrintAndLogEx(INFO, " Tag Signature"); + PrintAndLogEx(INFO, " IC signature public key name : NXP ???"); + PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_desfire_keys[public_key], 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 16, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 32, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 48, PUBLIC_DESFIRE_ECDA_KEYLEN - 48)); + PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp224r1"); + PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 16, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 32, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 48, signature_len - 48)); + PrintAndLogEx( (is_valid) ? SUCCESS : WARNING, " Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + return PM3_SUCCESS; +} +static int get_desfire_signature(uint8_t *signature, size_t *signature_len) { + + PacketResponseNG resp; + + uint8_t c[] = {MFDES_READSIG, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x3C + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, (INIT | DISCONNECT), sizeof(c), 0, c, sizeof(c)); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) + return PM3_ETIMEOUT; + + if (resp.length == 61) { + memcpy(signature, resp.data.asBytes + 1, 56); + *signature_len = 56; + return PM3_SUCCESS; + } else { + *signature_len = 0; + return PM3_ESOFT; + } +} + static int CmdHF14ADesInfo(const char *Cmd) { (void)Cmd; // Cmd is not used so far @@ -87,6 +146,13 @@ static int CmdHF14ADesInfo(const char *Cmd) { PrintAndLogEx(SUCCESS, " Protocol : %s", getProtocolStr(package->versionSW[6])); PrintAndLogEx(INFO, "-------------------------------------------------------------"); + // Signature originality check + uint8_t signature[56] = {0}; + size_t signature_len = 0; + + if (get_desfire_signature(signature, &signature_len) == PM3_SUCCESS) + desfire_print_signature(package->uid, signature, signature_len); + // Master Key settings getKeySettings(NULL); @@ -96,6 +162,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return PM3_ETIMEOUT; + PrintAndLogEx(INFO, " Free memory"); // Desfire Light doesn't support FREEMEM (len = 5) if (resp.length == 8) { uint8_t tmp[3]; @@ -119,7 +186,6 @@ static int CmdHF14ADesInfo(const char *Cmd) { keys 12,13,14,15 R */ - return PM3_SUCCESS; } @@ -186,7 +252,7 @@ void getKeySettings(uint8_t *aid) { // CARD MASTER KEY - PrintAndLogEx(SUCCESS, " CMK - PICC, Card Master Key settings"); + PrintAndLogEx(INFO, " CMK - PICC, Card Master Key settings"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); { uint8_t data[] = {GET_KEY_SETTINGS, 0x00, 0x00, 0x00}; // 0x45 From 5f29601947d6f4869c1dcac2f82788ab7182c705 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 17 Mar 2020 01:50:45 +0100 Subject: [PATCH 159/298] add desfire light signature verification check --- include/protocols.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/protocols.h b/include/protocols.h index de38e1aea..519172af6 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -385,6 +385,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MFDES_CHANGE_KEY 0xc4 #define MFDES_GET_KEY_VERSION 0x64 #define MFDES_AUTHENTICATION_FRAME 0xAF +#define MFDES_READSIG 0x3C // LEGIC Commands #define LEGIC_MIM_22 0x0D From 6d7682fdb3e3adb2011d0d3407e16546607fb623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marlin=20S=C3=B6=C3=B6se?= <30473690+msoose@users.noreply.github.com> Date: Mon, 16 Mar 2020 21:04:46 -0400 Subject: [PATCH 160/298] Update mfc_default_keys.dic --- client/dictionaries/mfc_default_keys.dic | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 1e26f948b..405f0d6f0 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1101,4 +1101,7 @@ c554ef6a6015 b8937130b6ba d7744a1a0c44 82908b57ef4f -fe04ecfe5577 \ No newline at end of file +fe04ecfe5577 +# comfort inn hotel +4d57414c5648 +4d48414c5648 From 8cf88c5cd51ddf3cd25ade6b7dfebd6a6af989b3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 17 Mar 2020 02:30:25 +0100 Subject: [PATCH 161/298] hf mfdes info - textual --- client/cmdhfmfdes.c | 52 +++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 7d6a6162c..2479270fa 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -269,39 +269,25 @@ void getKeySettings(uint8_t *aid) { if (resp.length == 7 ) { // number of Master keys (0x01) - PrintAndLogEx(SUCCESS, " [0x08] Number of Masterkeys : %u", resp.data.asBytes[2]); - uint8_t setting = (resp.data.asBytes[2] >> 6); - switch(setting) { - case 0: - PrintAndLogEx(SUCCESS, " [00] (3)DES operation of PICC master key"); - break; - case 1: - PrintAndLogEx(SUCCESS, " [01] 3K3DES operation of PICC master key"); - break; - case 2: - PrintAndLogEx(SUCCESS, " [02] AES operation of PICC master key"); - break; - default: - break; - } - - str = (resp.data.asBytes[2] & (1 << 3)) ? _GREEN_("YES") : "NO"; + PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), resp.data.asBytes[2]); + + str = (resp.data.asBytes[1] & (1 << 3)) ? _GREEN_("YES") : "NO"; PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", str); - str = (resp.data.asBytes[2] & (1 << 2)) ? "NO" : _GREEN_("YES"); + + str = (resp.data.asBytes[1] & (1 << 2)) ? _GREEN_("YES") : "NO"; PrintAndLogEx(SUCCESS, " [0x04] CMK required for create/delete : %s", str); - str = (resp.data.asBytes[2] & (1 << 1)) ? "NO" : _GREEN_("YES"); + + str = (resp.data.asBytes[1] & (1 << 1)) ? _GREEN_("YES") : "NO"; PrintAndLogEx(SUCCESS, " [0x02] Directory list access with CMK : %s", str); - str = (resp.data.asBytes[2] & (1 << 0)) ? _GREEN_("YES") : "NO"; + + str = (resp.data.asBytes[1] & (1 << 0)) ? _GREEN_("YES") : "NO"; PrintAndLogEx(SUCCESS, " [0x01] CMK is changeable : %s", str); } - // dd == key version - // cla ins p1 p2 lc dd le - { // 90, 64, - uint8_t data[] = {GET_KEY_VERSION, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x64 + { + uint8_t data[] = {GET_KEY_VERSION, 0x00, 0x00, 0x01, 0x0, 0x00}; // 0x64 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { return; } isOK = resp.oldarg[0] & 0xff; if (!isOK) { @@ -310,21 +296,18 @@ void getKeySettings(uint8_t *aid) { } if (resp.length == 6) { PrintAndLogEx(SUCCESS, ""); - PrintAndLogEx(SUCCESS, " Max number of keys : " _YELLOW_("%d"), resp.data.asBytes[1]); PrintAndLogEx(SUCCESS, " Master key Version : " _YELLOW_("%d (0x%02x)"), resp.data.asBytes[3], resp.data.asBytes[3]); PrintAndLogEx(INFO, " ----------------------------------------------------------"); } - { - // cla ins p1 p2 lc dd le uint8_t data[] = {AUTHENTICATE, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x0A, KEY 0 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; - PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); + if (resp.length == 13) + PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); { uint8_t data[] = {AUTHENTICATE_ISO, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x1A, KEY 0 @@ -333,16 +316,19 @@ void getKeySettings(uint8_t *aid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; - PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); + if (resp.length >= 13) + PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); { - uint8_t data[] = {AUTHENTICATE_AES, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0xAA, KEY 0 + uint8_t data[] = {AUTHENTICATE_AES, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0xAA, KEY 0 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} isOK = resp.data.asBytes[2] & 0xff; - PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); + if (resp.length == 13) + PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); } else { From fe0d9c8d9faf3d467b214dbc747242006bf1f6bf Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 17 Mar 2020 11:37:38 +0100 Subject: [PATCH 162/298] hf mfdes enum - fixes WIP --- armsrc/mifaredesfire.c | 41 ++++++++------------- client/cmdhfmfdes.c | 82 +++++++++++++++++++++--------------------- client/cmdhfmfdes.h | 10 ------ include/mifare.h | 10 ++++++ 4 files changed, 65 insertions(+), 78 deletions(-) diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index 3a3d0007c..06a3f3f8c 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -15,6 +15,7 @@ #include "mbedtls/aes.h" #include "commonutil.h" #include "util.h" +#include "mifare.h" #define MAX_APPLICATION_COUNT 28 #define MAX_FILE_COUNT 16 @@ -35,6 +36,8 @@ static uint8_t deselect_cmd[] = {0xc2, 0xe0, 0xb4}; bool InitDesfireCard() { + pcb_blocknum = 0; + iso14a_card_select_t card; iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@ -48,28 +51,14 @@ bool InitDesfireCard() { return true; } -// ARG0 flag enums -enum { - NONE = 0x00, - INIT = 0x01, - DISCONNECT = 0x02, - CLEARTRACE = 0x04, - BAR = 0x08, -} CmdOptions ; - void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) { - /* ARG0 contains flags. - 0x01 = init card. - 0x02 = Disconnect - 0x03 - */ uint8_t flags = arg0; size_t datalen = arg1; uint8_t resp[RECEIVE_SIZE]; memset(resp, 0, sizeof(resp)); - if (DBGLEVEL >= 4) { + if (DBGLEVEL >= DBG_EXTENDED) { Dbprintf(" flags : %02X", flags); Dbprintf(" len : %02X", datalen); print_result(" RX : ", datain, datalen); @@ -79,12 +68,13 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) { clear_trace(); if (flags & INIT) { - if (!InitDesfireCard()) + if (!InitDesfireCard()) { return; + } } int len = DesfireAPDU(datain, datalen, resp); - if (DBGLEVEL >= 4) + if (DBGLEVEL >= DBG_EXTENDED) print_result("RESP <--: ", resp, len); if (!len) { @@ -92,9 +82,6 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) { return; } - // reset the pcb_blocknum, - pcb_blocknum = 0; - if (flags & DISCONNECT) OnSuccess(); @@ -482,7 +469,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // dekryptera tagnonce. if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { - if (DBGLEVEL >= 4) { + if (DBGLEVEL >= DBG_EXTENDED) { DbpString("mbedtls_aes_setkey_dec failed"); } OnError(7); @@ -495,7 +482,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) memcpy(both + 16, decRndB, 16); uint8_t encBoth[32] = {0x00}; if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) { - if (DBGLEVEL >= 4) { + if (DBGLEVEL >= DBG_EXTENDED) { DbpString("mbedtls_aes_setkey_enc failed"); } OnError(7); @@ -549,23 +536,23 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout) { wrappedLen = CreateAPDU(cmd, cmd_len, wCmd); - if (DBGLEVEL >= 4) + if (DBGLEVEL >= DBG_EXTENDED) print_result("WCMD <--: ", wCmd, wrappedLen); ReaderTransmit(wCmd, wrappedLen, NULL); len = ReaderReceive(resp, par); if (!len) { - if (DBGLEVEL >= 4) Dbprintf("fukked"); + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("fukked"); return false; //DATA LINK ERROR } // if we received an I- or R(ACK)-Block with a block number equal to the // current block number, toggle the current block number - else if (len >= 4 // PCB+CID+CRC = 4 bytes + if (len >= 4 // PCB+CID+CRC = 4 bytes && ((resp[0] & 0xC0) == 0 // I-Block || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 && (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers - pcb_blocknum ^= 1; //toggle next block + pcb_blocknum ^= 1; //toggle next block } memcpy(dataout, resp, len); @@ -583,6 +570,8 @@ size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) { cmd[0] = 0x02; // 0x0A = send cid, 0x02 = no cid. cmd[0] |= pcb_blocknum; // OR the block number into the PCB + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("pcb_blocknum %d == %d ", pcb_blocknum, cmd[0] ); + cmd[1] = 0x90; // CID: 0x00 //TODO: allow multiple selected cards memcpy(cmd + 2, datain, len); diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 2479270fa..1aade35fb 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -19,6 +19,7 @@ #include "mbedtls/des.h" #include "crypto/libpcrypto.h" #include "protocols.h" +#include "mifare.h" // desfire raw command options uint8_t key_zero_data[16] = { 0x00 }; uint8_t key_ones_data[16] = { 0x01 }; @@ -299,54 +300,49 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(SUCCESS, " Master key Version : " _YELLOW_("%d (0x%02x)"), resp.data.asBytes[3], resp.data.asBytes[3]); PrintAndLogEx(INFO, " ----------------------------------------------------------"); } - + { + // 0x0A uint8_t data[] = {AUTHENTICATE, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x0A, KEY 0 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} - isOK = resp.data.asBytes[2] & 0xff; - if (resp.length == 13) - PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); + PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (resp.length == 13) ? _YELLOW_("YES") : "NO"); { + // 0x1A uint8_t data[] = {AUTHENTICATE_ISO, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x1A, KEY 0 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} - isOK = resp.data.asBytes[2] & 0xff; - if (resp.length >= 13) - PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); + PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (resp.length >= 13) ? _YELLOW_("YES") : "NO"); { + // 0xAA uint8_t data[] = {AUTHENTICATE_AES, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0xAA, KEY 0 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} - isOK = resp.data.asBytes[2] & 0xff; - if (resp.length == 13) - PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (isOK == 0xAE) ? "NO" : _YELLOW_("YES")); + PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (resp.length >= 13) ? _YELLOW_("YES") : "NO"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); } else { - // AID - APPLICATIO MASTER KEYS + // AID - APPLICATION MASTER KEYS PrintAndLogEx(SUCCESS, " AMK - Application Master Key settings"); - PrintAndLogEx(INFO, " ----------------------------------------------------------"); - PrintAndLogEx(INFO, "Selecting AID: %s", sprint_hex(aid, 3) ); + PrintAndLogEx(INFO, " ----------------------------------------------------------"); + PrintAndLogEx(INFO, " select AID: " _YELLOW_("%s"), sprint_hex(aid, 3) ); // SELECT AID { - uint8_t data[] = {SELECT_APPLICATION, 0x00, 0x00, 0x00}; // 0x5a - memcpy(data + 1, aid, 3); - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | CLEARTRACE, sizeof(data), 0, data, sizeof(data)); + uint8_t data[] = {SELECT_APPLICATION, 0x00, 0x00, 0x03, aid[0], aid[1], aid[2], 0x00}; // 0x5a + //memcpy(data + 1, aid, 3); + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT, sizeof(data), 0, data, sizeof(data)); } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { PrintAndLogEx(WARNING, _RED_(" Timed-out")); return; } @@ -362,7 +358,7 @@ void getKeySettings(uint8_t *aid) { SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { return; } isOK = resp.oldarg[0] & 0xff; @@ -370,15 +366,15 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings")); } else { // Access rights. - uint8_t rights = (resp.data.asBytes[3] >> 4 & 0xff); + uint8_t rights = (resp.data.asBytes[1] >> 4 & 0x0F); switch (rights) { - case 0x00: + case 0x0: str = "AMK authentication is necessary to change any key (default)"; break; - case 0x0e: + case 0xE: str = "Authentication with the key to be changed (same KeyNo) is necessary to change a key"; break; - case 0x0f: + case 0xF: str = "All keys (except AMK,see Bit0) within this application are frozen"; break; default: @@ -389,20 +385,20 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(SUCCESS, "-- " _GREEN_("%s"), str); PrintAndLogEx(SUCCESS, ""); // same as CMK - str = (resp.data.asBytes[3] & (1 << 3)) ? "YES" : "NO"; + str = (resp.data.asBytes[1] & (1 << 3)) ? "YES" : "NO"; PrintAndLogEx(SUCCESS, " 0x08 Configuration changeable : %s", str); - str = (resp.data.asBytes[3] & (1 << 2)) ? "NO" : "YES"; + str = (resp.data.asBytes[1] & (1 << 2)) ? "NO" : "YES"; PrintAndLogEx(SUCCESS, " 0x04 AMK required for create/delete : %s", str); - str = (resp.data.asBytes[3] & (1 << 1)) ? "NO" : "YES"; + str = (resp.data.asBytes[1] & (1 << 1)) ? "NO" : "YES"; PrintAndLogEx(SUCCESS, " 0x02 Directory list access with AMK : %s", str); - str = (resp.data.asBytes[3] & (1 << 0)) ? "YES" : "NO"; + str = (resp.data.asBytes[1] & (1 << 0)) ? "YES" : "NO"; PrintAndLogEx(SUCCESS, " 0x01 AMK is changeable : %s", str); } // KEY VERSION - AMK { - uint8_t data[] = {GET_KEY_VERSION, 0x00, 0x00, 0x00}; // 0x64 - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); + uint8_t data[] = {GET_KEY_VERSION, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x64 + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -439,8 +435,8 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { uint8_t isOK = 0x00; uint8_t aid[3]; { - uint8_t data[1] = {GET_APPLICATION_IDS}; //0x6a - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + uint8_t data[] = {GET_APPLICATION_IDS, 0x00, 0x00, 0x00}; //0x6a + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | CLEARTRACE | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } PacketResponseNG resp; @@ -454,17 +450,18 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { return PM3_ESOFT; } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "-- Desfire Enumerate Applications ---------------------------"); + PrintAndLogEx(INFO, "-- Desfire Enumerate Applications ---------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); - PacketResponseNG respAid; - PacketResponseNG respFiles; +// PacketResponseNG respAid; +// PacketResponseNG respFiles; uint8_t num = 0; int max = resp.oldarg[1] - 3 - 2; + PrintAndLogEx(INFO," MAX %d", max); - for (int i = 3; i <= max; i += 3) { - PrintAndLogEx(SUCCESS, " Aid %d : %02X %02X %02X ", num, resp.data.asBytes[i], resp.data.asBytes[i + 1], resp.data.asBytes[i + 2]); + for (int i = 1; i < max; i += 3) { + PrintAndLogEx(SUCCESS, " Aid %d : %02X %02X %02X ", num, resp.data.asBytes[i], resp.data.asBytes[i+1], resp.data.asBytes[i+2]); num++; aid[0] = resp.data.asBytes[i]; @@ -472,11 +469,11 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { aid[2] = resp.data.asBytes[i + 2]; getKeySettings(aid); +/* // Select Application { - uint8_t data[4] = {SELECT_APPLICATION}; // 0x5a - memcpy(data + 1, &resp.data.asBytes[i], 3); - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT, sizeof(data), 0, data, sizeof(data)); + uint8_t data[] = {SELECT_APPLICATION, 0x00, 0x00, 0x03, aid[0], aid[1], aid[2], 0x00}; // 0x5a + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &respAid, 1500)) { @@ -491,7 +488,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { // Get File IDs { - uint8_t data[1] = {GET_FILE_IDS}; // 0x6f + uint8_t data[] = {GET_FILE_IDS, 0x00, 0x00, 0x00}; // 0x6f SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } @@ -512,7 +509,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { // Get ISO File IDs { - uint8_t data[1] = {GET_ISOFILE_IDS}; // 0x61 + uint8_t data[] = {GET_ISOFILE_IDS, 0x00, 0x00, 0x00}; // 0x61 SendCommandMIX(CMD_HF_DESFIRE_COMMAND, DISCONNECT, sizeof(data), 0, data, sizeof(data)); } @@ -530,6 +527,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { } } } + */ } PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; diff --git a/client/cmdhfmfdes.h b/client/cmdhfmfdes.h index 3a19f6d83..5c4dcb5e2 100644 --- a/client/cmdhfmfdes.h +++ b/client/cmdhfmfdes.h @@ -19,16 +19,6 @@ char *getProtocolStr(uint8_t id); char *getVersionStr(uint8_t major, uint8_t minor); void getKeySettings(uint8_t *aid); -// Command options for Desfire behavior. -enum { - NONE = 0x00, - INIT = 0x01, - DISCONNECT = 0x02, - CLEARTRACE = 0x04, - BAR = 0x08, -} CmdOptions ; - - #define CREATE_APPLICATION 0xca #define DELETE_APPLICATION 0xda #define GET_APPLICATION_IDS 0x6a diff --git a/include/mifare.h b/include/mifare.h index 63b14c117..b8df9a2ec 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -70,6 +70,16 @@ typedef struct { uint32_t ProxToAirDuration; uint8_t par; // enough for precalculated parity of 8 Byte responses } PACKED tag_response_info_t; + +// DESFIRE_RAW flag enums +typedef enum DESFIRE_COMMAND { + NONE = 0x00, + INIT = 0x01, + DISCONNECT = 0x02, + CLEARTRACE = 0x04, + BAR = 0x10, +} desfire_command_t; + //----------------------------------------------------------------------------- // ISO 14443B //----------------------------------------------------------------------------- From 9ff3ed2933d5d7927790e0d87275566be86c3ed4 Mon Sep 17 00:00:00 2001 From: Winds <60715874+Windslab@users.noreply.github.com> Date: Tue, 17 Mar 2020 13:37:38 +0300 Subject: [PATCH 163/298] Create hf-writer.lua --- client/luascripts/hf-writer.lua | 124 ++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 client/luascripts/hf-writer.lua diff --git a/client/luascripts/hf-writer.lua b/client/luascripts/hf-writer.lua new file mode 100644 index 000000000..512a17f2e --- /dev/null +++ b/client/luascripts/hf-writer.lua @@ -0,0 +1,124 @@ +local utils = require('utils') +local read14a = require('read14a') +local uid = {} -- Array for eml files +local B = {} -- Array for B keys +local eml = {} -- Array for data in block 32 dig +local a = 0 +local b = 0 +local tab = string.rep('-', 64) + +local function read() + u = read14a.read(true, true).uid + return u +end + +local function fkey() + f = 'FFFFFFFFFFFF' + return f +end + +local function finish() + read14a.disconnect() + core.clearCommandBuffer() +end + +local function wait() read14a.waitFor14443a() end + +wait() + +print(tab) + +if string.len(read()) == 14 then -- Detect 7 byte card + l = 29 -- 7 byte length of eml file + s = 7 + e = 20 +else + l = 23 -- 4 byte length of eml file + s = 7 + e = 14 +end + +for _ in io.popen([[dir ".\" /b]]):lines() do -- for UNIX: ls + if string.find(_, '%.eml$') then + if string.len(_) == l then -- There length of eml file + a = a + 1 + uid[a] = string.sub(tostring(_), s, e) -- Cut UID from eml file + print(' ' .. a .. ' ' .. '|' .. ' ' .. uid[a]) + end + end +end + +print(tab) +print(' Your card has ' .. read() .. ' UID number\n') +print(' Choice your dump number to write (from 1 until ' .. a .. ')') +print(tab) +io.write(' --> ') + +local no = tonumber(io.read()) +local dump = io.open('./hf-mf-' .. uid[no] .. '-data.eml', 'r'); + +print(tab) +print(' You have been selected ' .. no .. ' card dump, it UID is ' .. uid[no]) + +for _ in dump:lines() do table.insert(eml, _); end +for i = 1, #eml do + if (i % 4 == 0) then + repeat + b = b + 1 + B[b] = string.sub(tostring(eml[i]), (string.len(eml[i]) - 11), + string.len(eml[i])) -- Cut key from block + until b % 4 == 0 + end +end + +print(tab) + +if (utils.confirm(' Do the UID changing?') == true) then + wait() + core.console('hf 14a raw -s -c -t 2000 90f0cccc10' .. tostring(eml[1])) + print(tab) + print(' The new card UID is: ' .. read()) +end + +print(tab) + +if (utils.confirm(' Would you like to BLOCK the UID for any changing?') == true) then + wait() + core.console('hf 14a raw -s -c -t 2000 90fd111100') +end + +print(tab) + +if (utils.confirm(' At this case are you using a Blank Card?') == true) then + wait() + for i = 1, #eml do + core.console('hf mf wrbl ' .. (i - 1) .. ' B ' .. fkey() .. ' ' .. + tostring(eml[i])) + end + print(tab) +else + print(tab) + if (utils.confirm( + ' Do you wishing DELETE ALL DATA and rewrite all keys to ' .. fkey() .. + '?') == true) then + wait() + for i = 1, #eml do + if (i % 4 == 0) then + core.console( + 'hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. ' ' .. + fkey() .. '78778800' .. fkey()) + else + core.console( + 'hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. ' ' .. + string.rep('0', 32)) + end + end + else + wait() + for i = 1, #eml do + core.console('hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. + ' ' .. tostring(eml[i])) + end + end +end +finish() From e9b293e8e9a06bd0bb74f632df90483953936b4f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 17 Mar 2020 13:38:51 +0100 Subject: [PATCH 164/298] hf mfp info - textual / colours --- client/cmdhfmfp.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 9c7b9cb3c..a5619756d 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -39,6 +39,10 @@ static int CmdHFMFPInfo(const char *Cmd) { if (Cmd && strlen(Cmd) > 0) PrintAndLogEx(WARNING, "command don't have any parameters.\n"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "-- Mifare Plus Tag Information ------------------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + // info about 14a part infoHF14A(false, false, false); @@ -54,57 +58,62 @@ static int CmdHFMFPInfo(const char *Cmd) { uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision if (select_status == 1 || select_status == 2) { - PrintAndLogEx(NORMAL, "----------------------------------------------"); - PrintAndLogEx(NORMAL, "Mifare Plus info:"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, " Fingerprint"); + // MIFARE Type Identification Procedure // https://www.nxp.com/docs/en/application-note/AN10833.pdf uint16_t ATQA = card.atqa[0] + (card.atqa[1] << 8); - if (ATQA == 0x0004) PrintAndLogEx(INFO, "ATQA: Mifare Plus 2k 4bUID"); - if (ATQA == 0x0002) PrintAndLogEx(INFO, "ATQA: Mifare Plus 4k 4bUID"); - if (ATQA == 0x0044) PrintAndLogEx(INFO, "ATQA: Mifare Plus 2k 7bUID"); - if (ATQA == 0x0042) PrintAndLogEx(INFO, "ATQA: Mifare Plus 4k 7bUID"); + if (ATQA == 0x0004) PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 2K") " (4b UID)"); + if (ATQA == 0x0002) PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 4K") " (4b UID)"); + if (ATQA == 0x0044) PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 2K") " (7b UID)"); + if (ATQA == 0x0042) PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 4K") " (7b UID)"); uint8_t SLmode = 0xff; if (card.sak == 0x08) { - PrintAndLogEx(INFO, "SAK: Mifare Plus 2k 7bUID"); + PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 2K 7b UID")); if (select_status == 2) SLmode = 1; } if (card.sak == 0x18) { - PrintAndLogEx(INFO, "SAK: Mifare Plus 4k 7bUID"); + PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 4K 7b UID")); if (select_status == 2) SLmode = 1; } if (card.sak == 0x10) { - PrintAndLogEx(INFO, "SAK: Mifare Plus 2k"); + PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 2K")); if (select_status == 2) SLmode = 2; } if (card.sak == 0x11) { - PrintAndLogEx(INFO, "SAK: Mifare Plus 4k"); + PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 4K")); if (select_status == 2) SLmode = 2; } if (card.sak == 0x20) { - PrintAndLogEx(INFO, "SAK: Mifare Plus SL0/SL3 or Mifare desfire"); - if (card.ats_len > 0) { - SLmode = 3; + PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus SL0/SL3") "or " _GREEN_("Mifare DESFire")); + if (card.ats_len > 0) { + + PrintAndLogEx(INFO, ""); + PrintAndLogEx(INFO, " SL fingerprint"); + SLmode = 3; // check SL0 uint8_t data[250] = {0}; int datalen = 0; // https://github.com/Proxmark/proxmark3/blob/master/client/luascripts/mifarePlus.lua#L161 uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00}; int res = ExchangeRAW14a(cmd, sizeof(cmd), false, false, data, sizeof(data), &datalen, false); + if (!res && datalen > 1 && data[0] == 0x09) { SLmode = 0; } } } - if (SLmode != 0xff) - PrintAndLogEx(INFO, "Mifare Plus SL mode: SL%d", SLmode); + if (SLmode != 0xFF) + PrintAndLogEx(SUCCESS, "\tMifare Plus SL mode: " _YELLOW_("SL%d"), SLmode); else - PrintAndLogEx(WARNING, "Mifare Plus SL mode: unknown("); + PrintAndLogEx(WARNING, "\tMifare Plus SL mode: " _YELLOW_("unknown")); } else { - PrintAndLogEx(INFO, "Mifare Plus info not available."); + PrintAndLogEx(INFO, "\tMifare Plus info not available."); } DropField(); From 53d00dc7c35080d778d93e9c4e82f01a2759ca7b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 17 Mar 2020 13:40:28 +0100 Subject: [PATCH 165/298] whitespace --- client/cmdhfmfu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 5c70f37cd..51d13ce53 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -895,12 +895,12 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, public_keys[public_key], uid, 7, signature, signature_len, false); bool is_valid = (res == 0); - PrintAndLogEx(NORMAL, "\n--- Tag Signature"); - PrintAndLogEx(NORMAL, "IC signature public key name : NXP NTAG21x (2013)"); - PrintAndLogEx(NORMAL, "IC signature public key value : %s", sprint_hex(public_keys[public_key], PUBLIC_ECDA_KEYLEN)); - PrintAndLogEx(NORMAL, " Elliptic curve parameters : NID_secp128r1"); - PrintAndLogEx(NORMAL, " TAG IC Signature : %s", sprint_hex(signature, signature_len)); - PrintAndLogEx(NORMAL, "Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); + PrintAndLogEx(INFO, "\n--- Tag Signature"); + PrintAndLogEx(INFO, "IC signature public key name : NXP NTAG21x (2013)"); + PrintAndLogEx(INFO, "IC signature public key value : %s", sprint_hex(public_keys[public_key], PUBLIC_ECDA_KEYLEN)); + PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp128r1"); + PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, signature_len)); + PrintAndLogEx(SUCCESS, "Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); return PM3_SUCCESS; } From 6783986fca514a3153dc51e71d2e6bf19d514f27 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 17 Mar 2020 13:41:46 +0100 Subject: [PATCH 166/298] hf mfdes info - textual --- client/cmdhfmfdes.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 1aade35fb..b921b0914 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -52,7 +52,7 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign bool is_valid = (res == 0); PrintAndLogEx(INFO, " Tag Signature"); - PrintAndLogEx(INFO, " IC signature public key name : NXP ???"); + PrintAndLogEx(INFO, " IC signature public key name : NXP DESFire Light"); PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_desfire_keys[public_key], 16)); PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 16, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 32, 16)); @@ -124,7 +124,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "-- Desfire Information --------------------------------------"); + PrintAndLogEx(INFO, "-- Mifare DESFire Tag Information ---------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(SUCCESS, " UID : " _GREEN_("%s"), sprint_hex(package->uid, sizeof(package->uid))); PrintAndLogEx(SUCCESS, " Batch number : " _GREEN_("%s"), sprint_hex(package->details + 7, 5)); @@ -413,7 +413,7 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(WARNING, " Can't read Application Master key version. Trying all keys"); //numOfKeys = MAX_NUM_KEYS; } else { - numOfKeys = resp.data.asBytes[4]; + numOfKeys = resp.data.asBytes[1]; PrintAndLogEx(SUCCESS, " Max number of keys : %d", numOfKeys); PrintAndLogEx(SUCCESS, " Application Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); PrintAndLogEx(INFO, "-------------------------------------------------------------"); @@ -533,6 +533,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { return PM3_SUCCESS; } + // MIAFRE DesFire Authentication // #define BUFSIZE 256 From eab2ebafaeb137caac7db9b1c2f05611aedd557b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 17 Mar 2020 17:12:27 +0100 Subject: [PATCH 167/298] added pwdgen test --- client/cmdhfmfu.c | 22 +--------------------- common/generator.c | 33 +++++++++++++++++++++++---------- pm3test.sh | 4 +++- 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 51d13ce53..c1cd5d31a 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -296,26 +296,6 @@ uint8_t UL_MEMORY_ARRAY[ARRAYLEN(UL_TYPES_ARRAY)] = { MAX_ULEV1a_BLOCKS, MAX_NTAG_213, MAX_NTAG_216, MAX_UL_NANO_40, MAX_NTAG_I2C_1K }; -static int ul_ev1_pwdgen_selftest() { - - uint8_t uid1[] = {0x04, 0x11, 0x12, 0x11, 0x12, 0x11, 0x10}; - uint32_t pwd1 = ul_ev1_pwdgenA(uid1); - PrintAndLogEx(NORMAL, "UID | %s | %08X | %s", sprint_hex(uid1, 7), pwd1, (pwd1 == 0x8432EB17) ? "OK" : "->8432EB17<-"); - - uint8_t uid2[] = {0x04, 0x1f, 0x98, 0xea, 0x1e, 0x3e, 0x81}; - uint32_t pwd2 = ul_ev1_pwdgenB(uid2); - PrintAndLogEx(NORMAL, "UID | %s | %08X | %s", sprint_hex(uid2, 7), pwd2, (pwd2 == 0x5fd37eca) ? "OK" : "->5fd37eca<--"); - - uint8_t uid3[] = {0x04, 0x62, 0xB6, 0x8A, 0xB4, 0x42, 0x80}; - uint32_t pwd3 = ul_ev1_pwdgenC(uid3); - PrintAndLogEx(NORMAL, "UID | %s | %08X | %s", sprint_hex(uid3, 7), pwd3, (pwd3 == 0x5a349515) ? "OK" : "->5a349515<--"); - - uint8_t uid4[] = {0x04, 0xC5, 0xDF, 0x4A, 0x6D, 0x51, 0x80}; - uint32_t pwd4 = ul_ev1_pwdgenD(uid4); - PrintAndLogEx(NORMAL, "UID | %s | %08X | %s", sprint_hex(uid4, 7), pwd4, (pwd4 == 0x72B1EC61) ? "OK" : "->72B1EC61<--"); - return PM3_SUCCESS; -} - //------------------------------------ // get version nxp product type static char *getProductTypeStr(uint8_t id) { @@ -2578,7 +2558,7 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_pwdgen(); - if (cmdp == 't') return ul_ev1_pwdgen_selftest(); + if (cmdp == 't') return generator_selftest(); if (cmdp == 'r') { // read uid from tag diff --git a/common/generator.c b/common/generator.c index 4be63a925..fa1fd7cd3 100644 --- a/common/generator.c +++ b/common/generator.c @@ -418,43 +418,56 @@ int mfc_algo_sky_all(uint8_t *uid, uint8_t *keys) { //------------------------------------ int generator_selftest() { - PrintAndLogEx(SUCCESS, "Generators selftest"); - PrintAndLogEx(SUCCESS, "-------------------"); +#define NUM_OF_TEST 5 - bool success; + PrintAndLogEx(INFO, "PWD / KEY generator selftest"); + PrintAndLogEx(INFO, "----------------------------"); + + bool success = false; + uint8_t testresult = 0; uint8_t uid1[] = {0x04, 0x11, 0x12, 0x11, 0x12, 0x11, 0x10}; uint32_t pwd1 = ul_ev1_pwdgenA(uid1); success = (pwd1 == 0x8432EB17); - PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X | %s", sprint_hex(uid1, 7), pwd1, success ? "OK" : "->8432EB17<-"); + if (success) + testresult++; + PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid1, 7), pwd1, success ? "OK" : "->8432EB17<-"); uint8_t uid2[] = {0x04, 0x1f, 0x98, 0xea, 0x1e, 0x3e, 0x81}; uint32_t pwd2 = ul_ev1_pwdgenB(uid2); success = (pwd2 == 0x5fd37eca); - PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X | %s", sprint_hex(uid2, 7), pwd2, success ? "OK" : "->5fd37eca<--"); + if (success) + testresult++; + PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid2, 7), pwd2, success ? "OK" : "->5fd37eca<--"); uint8_t uid3[] = {0x04, 0x62, 0xB6, 0x8A, 0xB4, 0x42, 0x80}; uint32_t pwd3 = ul_ev1_pwdgenC(uid3); success = (pwd3 == 0x5a349515); - PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X | %s", sprint_hex(uid3, 7), pwd3, success ? "OK" : "->5a349515<--"); + if (success) + testresult++; + PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid3, 7), pwd3, success ? "OK" : "->5a349515<--"); uint8_t uid4[] = {0x04, 0xC5, 0xDF, 0x4A, 0x6D, 0x51, 0x80}; uint32_t pwd4 = ul_ev1_pwdgenD(uid4); success = (pwd4 == 0x72B1EC61); - PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X | %s", sprint_hex(uid4, 7), pwd4, success ? "OK" : "->72B1EC61<--"); + if (success) + testresult++; + PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid4, 7), pwd4, success ? "OK" : "->72B1EC61<--"); // uint8_t uid5[] = {0x11, 0x22, 0x33, 0x44}; // uint64_t key1 = mfc_algo_a(uid5); // success = (key1 == 0xD1E2AA68E39A); -// PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" | %s", sprint_hex(uid5, 4), key1, success ? "OK" : "->D1E2AA68E39A<--"); +// PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid5, 4), key1, success ? "OK" : "->D1E2AA68E39A<--"); uint8_t uid6[] = {0x74, 0x57, 0xCA, 0xA9}; uint64_t key6 = 0; mfc_algo_sky_one(uid6, 15, 0, &key6); success = (key6 == 0x82c7e64bc565); - PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" | %s", sprint_hex(uid6, 4), key6, success ? "OK" : "->82C7E64BC565<--"); + if (success) + testresult++; + PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid6, 4), key6, success ? "OK" : "->82C7E64BC565<--"); - PrintAndLogEx(SUCCESS, "-------------------"); + PrintAndLogEx(SUCCESS, "------------------- Selftest %s", (testresult == NUM_OF_TEST) ? "OK" : "fail"); return PM3_SUCCESS; } diff --git a/pm3test.sh b/pm3test.sh index 6a2256192..11b459ab4 100755 --- a/pm3test.sh +++ b/pm3test.sh @@ -95,7 +95,8 @@ while true; do printf "\n${C_BLUE}Testing data manipulation:${C_NC}\n" if ! CheckExecute "reveng test" "./client/proxmark3 -c 'reveng -w 8 -s 01020304e3 010204039d'" "CRC-8/SMBUS"; then break; fi - + if ! CheckExecute "mfu pwdgen test" "./client/proxmark3 -c 'hf mfu pwdgen t'" "Selftest OK"; then break; fi + printf "\n${C_BLUE}Testing LF:${C_NC}\n" if ! CheckExecute "lf em4x05 test" "./client/proxmark3 -c 'data load traces/em4x05.pm3;lf search'" "FDX-B ID found"; then break; fi @@ -120,6 +121,7 @@ while true; do if ! CheckExecute "findbits test" "tools/findbits.py 73 0110010101110011" "Match at bit 9: 011001010"; then break; fi if ! CheckExecute "findbits_test test" "tools/findbits_test.py 2>&1" "OK"; then break; fi if ! CheckExecute "pm3_eml_mfd test" "tools/pm3_eml_mfd_test.py 2>&1" "OK"; then break; fi + printf "\n${C_GREEN}Tests [OK]${C_NC}\n\n" exit 0 done From 6b30e1ab0076c2fabd7c9ad2e3a53c2ccc80a219 Mon Sep 17 00:00:00 2001 From: Winds <60715874+Windslab@users.noreply.github.com> Date: Wed, 18 Mar 2020 13:39:10 +0300 Subject: [PATCH 168/298] Update hf-writer.lua Adapted your script to the coding standards --- client/luascripts/hf-writer.lua | 211 ++++++++++++++++++-------------- 1 file changed, 122 insertions(+), 89 deletions(-) diff --git a/client/luascripts/hf-writer.lua b/client/luascripts/hf-writer.lua index 512a17f2e..0c15dff56 100644 --- a/client/luascripts/hf-writer.lua +++ b/client/luascripts/hf-writer.lua @@ -7,6 +7,28 @@ local a = 0 local b = 0 local tab = string.rep('-', 64) +copyright = '' +author = 'Winds' +version = 'v1.0.0' +desc = [[ + That's script gives for you a easy way to write your an *.eml dumps, using a Proxmark 3. + It's working for 4 and 7 bytes NXP MIFARE Classic 1K cards. + The script has including an injection of UID changig for the Chinese Magic Cards GEN 3. + + Whith choosen an *.eml file you can do: + + 1. Write it to the equals of current card UID. + 2. Write it to anther card with changable UID. + 3. Send command to lock UID for the Chinese Magic Cards GEN 3. + 4. Erease all data at the card and set the FFFFFFFFFFFF keys, and Access Conditions to 78778800. +]] +example = [[ + 1. script run hf-writer +]] +usage = [[ + You should choose your *.eml dump from being list to write it to the card by wizard +]] + local function read() u = read14a.read(true, true).uid return u @@ -22,103 +44,114 @@ local function finish() core.clearCommandBuffer() end -local function wait() read14a.waitFor14443a() end - -wait() - -print(tab) - -if string.len(read()) == 14 then -- Detect 7 byte card - l = 29 -- 7 byte length of eml file - s = 7 - e = 20 -else - l = 23 -- 4 byte length of eml file - s = 7 - e = 14 +local function wait() + read14a.waitFor14443a() end -for _ in io.popen([[dir ".\" /b]]):lines() do -- for UNIX: ls - if string.find(_, '%.eml$') then - if string.len(_) == l then -- There length of eml file - a = a + 1 - uid[a] = string.sub(tostring(_), s, e) -- Cut UID from eml file - print(' ' .. a .. ' ' .. '|' .. ' ' .. uid[a]) - end - end -end - -print(tab) -print(' Your card has ' .. read() .. ' UID number\n') -print(' Choice your dump number to write (from 1 until ' .. a .. ')') -print(tab) -io.write(' --> ') - -local no = tonumber(io.read()) -local dump = io.open('./hf-mf-' .. uid[no] .. '-data.eml', 'r'); - -print(tab) -print(' You have been selected ' .. no .. ' card dump, it UID is ' .. uid[no]) - -for _ in dump:lines() do table.insert(eml, _); end -for i = 1, #eml do - if (i % 4 == 0) then - repeat - b = b + 1 - B[b] = string.sub(tostring(eml[i]), (string.len(eml[i]) - 11), - string.len(eml[i])) -- Cut key from block - until b % 4 == 0 - end -end - -print(tab) - -if (utils.confirm(' Do the UID changing?') == true) then +local function main(args) + --File lienght check for detect 4 or 7 bytes wait() - core.console('hf 14a raw -s -c -t 2000 90f0cccc10' .. tostring(eml[1])) print(tab) - print(' The new card UID is: ' .. read()) -end - -print(tab) - -if (utils.confirm(' Would you like to BLOCK the UID for any changing?') == true) then - wait() - core.console('hf 14a raw -s -c -t 2000 90fd111100') -end - -print(tab) - -if (utils.confirm(' At this case are you using a Blank Card?') == true) then - wait() - for i = 1, #eml do - core.console('hf mf wrbl ' .. (i - 1) .. ' B ' .. fkey() .. ' ' .. - tostring(eml[i])) - end - print(tab) -else - print(tab) - if (utils.confirm( - ' Do you wishing DELETE ALL DATA and rewrite all keys to ' .. fkey() .. - '?') == true) then - wait() - for i = 1, #eml do - if (i % 4 == 0) then - core.console( - 'hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. ' ' .. - fkey() .. '78778800' .. fkey()) - else - core.console( - 'hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. ' ' .. - string.rep('0', 32)) + if string.len(read()) == 14 then -- Detect 7 byte card + l = 29 -- 7 byte length of eml file + s = 7 + e = 20 + else + l = 23 -- 4 byte length of eml file + s = 7 + e = 14 + end + ---Listern EML files at Client catalog + for _ in io.popen([[dir ".\" /b]]):lines() do -- for UNIX: ls + if string.find(_, '%.eml$') then + if string.len(_) == l then -- There length of eml file + a = a + 1 + uid[a] = string.sub(tostring(_), s, e) -- Cut UID from eml file + print(' ' .. a .. ' ' .. '|' .. ' ' .. uid[a]) end end - else + end + + print(tab) + print(' Your card has ' .. read() .. ' UID number\n') + print(' Choice your dump number to write (from 1 until ' .. a .. ')') + print(tab) + io.write(' --> ') + + local no = tonumber(io.read()) + local dump = io.open('./hf-mf-' .. uid[no] .. '-data.eml', 'r'); + + print(tab) + print(' You have been selected ' .. no .. ' card dump, it UID is ' .. uid[no]) + ---EML get B key from opened EML file + for _ in dump:lines() do table.insert(eml, _); end + for i = 1, #eml do + if (i % 4 == 0) then + repeat + b = b + 1 + B[b] = string.sub(tostring(eml[i]), (string.len(eml[i]) - 11), + string.len(eml[i])) -- Cut key from block + until b % 4 == 0 + end + end + + print(tab) + ---UID Changing + if (utils.confirm(' Do the UID changing?') == true) then + wait() + core.console('hf 14a raw -s -c -t 2000 90f0cccc10' .. tostring(eml[1])) + print(tab) + print(' The new card UID is: ' .. read()) + end + + print(tab) + ---UID Blocking + if (utils.confirm(' Would you like to BLOCK the UID for any changing?') == true) then + wait() + core.console('hf 14a raw -s -c -t 2000 90fd111100') + end + + print(tab) + ---Wriiting block + if (utils.confirm(' At this case are you using a Blank Card?') == true) then wait() for i = 1, #eml do - core.console('hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. - ' ' .. tostring(eml[i])) + core.console('hf mf wrbl ' .. (i - 1) .. ' B ' .. fkey() .. ' ' .. + tostring(eml[i])) + end + print(tab) + else + print(tab) + if (utils.confirm( + ' Do you wishing DELETE ALL DATA and rewrite all keys to ' .. fkey() .. + '?') == true) then + wait() + for i = 1, #eml do + if (i % 4 == 0) then + core.console( + 'hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. ' ' .. + fkey() .. '78778800' .. fkey()) + else + core.console( + 'hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. ' ' .. + string.rep('0', 32)) + end + end + else + wait() + for i = 1, #eml do + core.console('hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. + ' ' .. tostring(eml[i])) + end end end + finish() end -finish() +main(args) + +---General thinks for the future: +---Add support another types of dumps: BIN, JSON +---Maybe it will be not only as `hf-writer`, like a universal dump manager. +---Add undependence from the operation system. At the moment code not working in Linux. +---Add more chinesse backdoors RAW commands for UID changing (find RAW for the 4 byte familiar chinese card, from native it soft: http://bit.ly/39VIDsU) +---Hide system messages when you writing a dumps, replace it to some of like [#####----------] 40% From 3947528996d75a50d6836e9720fb1119579569d6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Mar 2020 05:44:47 +0100 Subject: [PATCH 169/298] optional color for serial text in prompt --- client/proxmark3.c | 14 +++++++++----- client/proxmark3.h | 8 ++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index 3217d0583..5a6ae23a9 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -58,7 +58,11 @@ static void showBanner(void) { static int check_comm(void) { // If communications thread goes down. Device disconnected then this should hook up PM3 again. if (IsCommunicationThreadDead() && session.pm3_present) { - rl_set_prompt(PROXPROMPT_OFFLINE); + if (session.supports_colors) + rl_set_prompt(PROXPROMPT_OFFLINE_COLOR); + else + rl_set_prompt(PROXPROMPT_OFFLINE); + rl_forced_update_display(); CloseProxmark(); PrintAndLogEx(INFO, "Running in " _YELLOW_("OFFLINE") "mode. Use "_YELLOW_("\"hw connect\"") "to reconnect\n"); @@ -150,7 +154,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) { // loops every time enter is pressed... while (1) { bool printprompt = false; - const char *prompt = PROXPROMPT_CON; + const char *prompt = (session.supports_colors) ? PROXPROMPT_CON_COLOR : PROXPROMPT_CON; check_script: // If there is a script file @@ -214,11 +218,11 @@ check_script: rl_event_hook = check_comm; if (session.pm3_present) { if (conn.send_via_fpc_usart == false) - prompt = PROXPROMPT_USB; + prompt = (session.supports_colors) ? PROXPROMPT_USB_COLOR : PROXPROMPT_USB; else - prompt = PROXPROMPT_FPC; + prompt = (session.supports_colors) ? PROXPROMPT_FPC_COLOR : PROXPROMPT_FPC; } else { - prompt = PROXPROMPT_OFFLINE; + prompt = (session.supports_colors) ? PROXPROMPT_OFFLINE_COLOR : PROXPROMPT_OFFLINE; } cmd = readline(prompt); fflush(NULL); diff --git a/client/proxmark3.h b/client/proxmark3.h index d3e3629ec..107e64859 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -15,9 +15,17 @@ #include "common.h" #define PROXPROMPT_CON "[con] pm3 --> " +#define PROXPROMPT_CON_COLOR "[\001\033[1;32m\002con\001\033[0m\002] pm3 --> " + #define PROXPROMPT_USB "[usb] pm3 --> " +#define PROXPROMPT_USB_COLOR "[\001\033[1;32m\002usb\001\033[0m\002] pm3 --> " + #define PROXPROMPT_FPC "[fpc] pm3 --> " +#define PROXPROMPT_FPC_COLOR "[\001\033[1;32m\002fpc\001\033[0m\002] pm3 --> " + #define PROXPROMPT_OFFLINE "[offline] pm3 --> " +#define PROXPROMPT_OFFLINE_COLOR "[\001\033[1;31m\002offline\001\033[0m\002] pm3 --> " + #define PROXHISTORY "history.txt" #define PROXLOG "log_%Y%m%d.txt" #define MAX_NESTED_CMDSCRIPT 10 From 37011158e1dbc302a40e0bab2ec641617c301201 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Mar 2020 09:26:56 +0100 Subject: [PATCH 170/298] chg: hf mfp info - more text / better detection between DESFire and Plus --- client/cmdhfmfp.c | 85 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index a5619756d..641e959a1 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -65,35 +65,51 @@ static int CmdHFMFPInfo(const char *Cmd) { // MIFARE Type Identification Procedure // https://www.nxp.com/docs/en/application-note/AN10833.pdf uint16_t ATQA = card.atqa[0] + (card.atqa[1] << 8); - if (ATQA == 0x0004) PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 2K") " (4b UID)"); - if (ATQA == 0x0002) PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 4K") " (4b UID)"); - if (ATQA == 0x0044) PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 2K") " (7b UID)"); - if (ATQA == 0x0042) PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 4K") " (7b UID)"); + + bool isPlus = false; + + if (ATQA == 0x0004) { + PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 2K") " (4b UID)"); + isPlus = true; + } + if (ATQA == 0x0002) { + PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 4K") " (4b UID)"); + isPlus = true; + } + if (ATQA == 0x0044) { + PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 2K") " (7b UID)"); + isPlus = true; + } + if (ATQA == 0x0042) { + PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 4K") " (7b UID)"); + isPlus = true; + } uint8_t SLmode = 0xff; - if (card.sak == 0x08) { - PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 2K 7b UID")); - if (select_status == 2) SLmode = 1; - } - if (card.sak == 0x18) { - PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 4K 7b UID")); - if (select_status == 2) SLmode = 1; - } - if (card.sak == 0x10) { - PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 2K")); - if (select_status == 2) SLmode = 2; - } - if (card.sak == 0x11) { - PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 4K")); - if (select_status == 2) SLmode = 2; + if (isPlus) { + if (card.sak == 0x08) { + PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 2K 7b UID")); + if (select_status == 2) SLmode = 1; + } + if (card.sak == 0x18) { + PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 4K 7b UID")); + if (select_status == 2) SLmode = 1; + } + if (card.sak == 0x10) { + PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 2K")); + if (select_status == 2) SLmode = 2; + } + if (card.sak == 0x11) { + PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus 4K")); + if (select_status == 2) SLmode = 2; + } } + if (card.sak == 0x20) { PrintAndLogEx(INFO, " SAK - " _GREEN_("Mifare Plus SL0/SL3") "or " _GREEN_("Mifare DESFire")); if (card.ats_len > 0) { - PrintAndLogEx(INFO, ""); - PrintAndLogEx(INFO, " SL fingerprint"); SLmode = 3; // check SL0 uint8_t data[250] = {0}; @@ -102,12 +118,38 @@ static int CmdHFMFPInfo(const char *Cmd) { uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00}; int res = ExchangeRAW14a(cmd, sizeof(cmd), false, false, data, sizeof(data), &datalen, false); + if (memcmp(data, "\x67\x00", 2) == 0) { + PrintAndLogEx(INFO, "\tMost likely a Mifare DESFire tag"); + PrintAndLogEx(HINT, "Hint: Try " _YELLOW_("`hf mfdes info`")); + DropField(); + return PM3_SUCCESS; + } + if (!res && datalen > 1 && data[0] == 0x09) { SLmode = 0; } } } +// How do we detect SL0 / SL1 / SL2 / SL3 modes?!? + PrintAndLogEx(INFO, "Security Level (SL)"); + switch(SLmode) { + case 0: + PrintAndLogEx(INFO, "SL 0: initial delivery configuration, used for card personalization"); + break; + case 1: + PrintAndLogEx(INFO, "SL 1: backwards functional compatibility mode (with MIFARE Classic 1K and MIFARE Classic 4K) with an optional AES authentication"); + break; + case 2: + PrintAndLogEx(INFO, "SL 2: "); + break; + case 3: + PrintAndLogEx(INFO, "SL 3: 3-Pass authentication based on AES, data manipulation commands secured by AES encryption and an AES based MACing method."); + break; + default: + break; + } + if (SLmode != 0xFF) PrintAndLogEx(SUCCESS, "\tMifare Plus SL mode: " _YELLOW_("SL%d"), SLmode); else @@ -117,7 +159,6 @@ static int CmdHFMFPInfo(const char *Cmd) { } DropField(); - return PM3_SUCCESS; } From 4bbe0827f5d743824a6f10584b63a005b0bd49c7 Mon Sep 17 00:00:00 2001 From: Winds <60715874+Windslab@users.noreply.github.com> Date: Thu, 19 Mar 2020 12:29:39 +0300 Subject: [PATCH 171/298] Update hf-writer.lua Add the possibility for a -h helptext param --- client/luascripts/hf-writer.lua | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/client/luascripts/hf-writer.lua b/client/luascripts/hf-writer.lua index 0c15dff56..8c5740af6 100644 --- a/client/luascripts/hf-writer.lua +++ b/client/luascripts/hf-writer.lua @@ -1,4 +1,5 @@ local utils = require('utils') +local getopt = require('getopt') local read14a = require('read14a') local uid = {} -- Array for eml files local B = {} -- Array for B keys @@ -29,6 +30,17 @@ usage = [[ You should choose your *.eml dump from being list to write it to the card by wizard ]] +--- +-- Usage help +local function help() + print(copyright) + print(author) + print(version) + print(desc) + print(example) + print(usage) +end + local function read() u = read14a.read(true, true).uid return u @@ -49,6 +61,11 @@ local function wait() end local function main(args) + -- Arguments for the script + for o, a in getopt.getopt(args, 'h') do + if o == 'h' then return help() end + end + --File lienght check for detect 4 or 7 bytes wait() print(tab) From 7a1c65d1af5009244920d5213177da387a4c80e8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Mar 2020 12:05:29 +0100 Subject: [PATCH 172/298] chg: hf mfdes info - refactored a bit. \nchg: hf mfdes enum - now works again --- client/cmdhfmfdes.c | 626 ++++++++++++++++++++++++++++---------------- 1 file changed, 401 insertions(+), 225 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index b921b0914..5ab35a12d 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -28,6 +28,73 @@ uint8_t key_picc_data[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x static int CmdHelp(const char *Cmd); +//ICEMAN: Turn on field method? +//none +static int test_desfire_authenticate() { + uint8_t c[] = {AUTHENTICATE, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x0A, KEY 0 + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(c), 0, c, sizeof(c)); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { + DropField(); + return PM3_ETIMEOUT; + } + if (resp.length == 13) + return PM3_SUCCESS; + return PM3_ESOFT; +} +// none +static int test_desfire_authenticate_iso() { + uint8_t c[] = {AUTHENTICATE_ISO, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x1A, KEY 0 + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(c), 0, c, sizeof(c)); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { + DropField(); + return PM3_ETIMEOUT; + } + if (resp.length >= 13) + return PM3_SUCCESS; + return PM3_ESOFT; +} +//none +static int test_desfire_authenticate_aes() { + uint8_t c[] = {AUTHENTICATE_AES, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0xAA, KEY 0 + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(c), 0, c, sizeof(c)); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { + DropField(); + return PM3_ETIMEOUT; + } + if (resp.length >= 13) + return PM3_SUCCESS; + return PM3_ESOFT; +} + +// --- FREE MEM +static int desfire_print_freemem(uint32_t free_mem) { + PrintAndLogEx(SUCCESS, " Available free memory on card : " _GREEN_("%d bytes"), free_mem); + return PM3_SUCCESS; +} + +// init / disconnect +static int get_desfire_freemem(uint32_t *free_mem) { + uint8_t c[] = {GET_FREE_MEMORY, 0x00, 0x00, 0x00}; // 0x6E + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, (INIT | DISCONNECT), sizeof(c), 0, c, sizeof(c)); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + return PM3_ETIMEOUT; + } + + if (resp.length == 8) { + *free_mem = le24toh(resp.data.asBytes + 1); + return PM3_SUCCESS; + } + + *free_mem = 0; + return PM3_ESOFT; +} + + +// --- GET SIGNATURE static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len) { #define PUBLIC_DESFIRE_ECDA_KEYLEN 57 @@ -66,12 +133,12 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; } + +// init / disconnect static int get_desfire_signature(uint8_t *signature, size_t *signature_len) { - - PacketResponseNG resp; - uint8_t c[] = {MFDES_READSIG, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x3C SendCommandMIX(CMD_HF_DESFIRE_COMMAND, (INIT | DISCONNECT), sizeof(c), 0, c, sizeof(c)); + PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return PM3_ETIMEOUT; @@ -85,6 +152,190 @@ static int get_desfire_signature(uint8_t *signature, size_t *signature_len) { } } + +// --- KEY SETTING +static int desfire_print_keysetting(uint8_t key_settings, uint8_t num_keys) { + + PrintAndLogEx(SUCCESS, " AID Key settings : %02x", key_settings); + PrintAndLogEx(SUCCESS, " Max number of keys in AID : %d", num_keys); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " Changekey Access rights"); + + // Access rights. + uint8_t rights = (key_settings >> 4 & 0x0F); + switch (rights) { + case 0x0: + PrintAndLogEx(SUCCESS, " -- AMK authentication is necessary to change any key (default)"); + break; + case 0xE: + PrintAndLogEx(SUCCESS, " -- Authentication with the key to be changed (same KeyNo) is necessary to change a key"); + break; + case 0xF: + PrintAndLogEx(SUCCESS, " -- All keys (except AMK,see Bit0) within this application are frozen"); + break; + default: + PrintAndLogEx(SUCCESS, " -- Authentication with the specified key is necessary to change any key.\nA change key and a PICC master key (CMK) can only be changed after authentication with the master key.\nFor keys other then the master or change key, an authentication with the same key is needed."); + break; + } + + PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO"); + PrintAndLogEx(SUCCESS, " [0x04] AMK required for create/delete : %s", (key_settings & (1 << 2)) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, " [0x02] Directory list access with AMK : %s", (key_settings & (1 << 1)) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, " [0x01] AMK is changeable : %s", (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO"); + return PM3_SUCCESS; +} + +// none +static int get_desfire_keysettings(uint8_t *key_settings, uint8_t *num_keys) { + PacketResponseNG resp; + uint8_t c[] = {MFDES_GET_KEY_SETTINGS, 0x00, 0x00, 0x00}; // 0x45 + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(c), 0, c, sizeof(c)); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(WARNING, _RED_(" Timed-out")); + return PM3_ETIMEOUT; + } + + uint8_t isOK = resp.oldarg[0] & 0xFF; + if (isOK == false) { + return PM3_ESOFT; + } + + if (resp.data.asBytes[1] == 0x91 && resp.data.asBytes[2] == 0xae) { + PrintAndLogEx(WARNING, _RED_(" authentication error")); + return PM3_ESOFT; + } +// PrintAndLogEx(INFO, "ICE: KEYSETTING resp :: %s", sprint_hex(resp.data.asBytes, resp.length)); + *key_settings = resp.data.asBytes[1]; + *num_keys = resp.data.asBytes[2]; + return PM3_SUCCESS; +} + +// --- KEY VERSION +static int desfire_print_keyversion(uint8_t key_idx, uint8_t key_version) { + PrintAndLogEx(SUCCESS, " Key [%u] Version : %d (0x%02x)", key_idx, key_version, key_version); + return PM3_SUCCESS; +} + +// none +static int get_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) { + PacketResponseNG resp; + uint8_t c[] = {MFDES_GET_KEY_VERSION, 0x00, 0x00, 0x01, curr_key, 0x00}; // 0x64 + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(c), 0, c, sizeof(c)); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(WARNING, _RED_(" Timed-out")); + return PM3_ETIMEOUT; + } + + uint8_t isOK = resp.oldarg[0] & 0xFF; + if (isOK == false) { + return PM3_ESOFT; + } + + if ( resp.data.asBytes[1] == 0x91 && resp.data.asBytes[2] == 0x40) { + return PM3_ESOFT; + } + + *num_versions = resp.data.asBytes[1]; + return PM3_SUCCESS; +} + + +// init +static int get_desfire_select_application(uint8_t *aid) { + if (aid == NULL) return PM3_ESOFT; + + uint8_t c[] = {SELECT_APPLICATION, 0x00, 0x00, 0x03, aid[0], aid[1], aid[2], 0x00}; // 0x5a + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT, sizeof(c), 0, c, sizeof(c)); + + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { + PrintAndLogEx(WARNING, _RED_(" timed-out")); + return PM3_ETIMEOUT; + } + + uint8_t isOK = resp.oldarg[0] & 0xff; + if (!isOK) { + PrintAndLogEx(WARNING, " Can't select AID: " _RED_("%s"), sprint_hex(aid, 3)); + return PM3_ESOFT; + } + + if (resp.data.asBytes[1] == 0x91 && resp.data.asBytes[2] == 0x00) { + return PM3_SUCCESS; + } + + return PM3_ESOFT; +} + + +// init / disconnect +static int get_desfire_appids(uint8_t *dest, uint8_t *app_ids_len) { + + uint8_t c[] = {GET_APPLICATION_IDS, 0x00, 0x00, 0x00}; //0x6a + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | CLEARTRACE | DISCONNECT , sizeof(c), 0, c, sizeof(c)); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + return PM3_ETIMEOUT; + } + + uint8_t isOK = resp.oldarg[0] & 0xff; + if (!isOK) { + PrintAndLogEx(WARNING, _RED_("Command unsuccessful")); + return PM3_ESOFT; + } + + *app_ids_len = resp.length - 5; + + // resp.length - 2crc, 2status, 1pcb... + memcpy(dest, resp.data.asBytes + 1, *app_ids_len); + + if (resp.data.asBytes[resp.length - 3] == MFDES_ADDITIONAL_FRAME) { + + c[0] = MFDES_ADDITIONAL_FRAME; //0xAF + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(c), 0, c, sizeof(c)); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + return PM3_ETIMEOUT; + } + + isOK = resp.oldarg[0] & 0xff; + if (!isOK) { + PrintAndLogEx(WARNING, _RED_("Command unsuccessful")); + return PM3_ESOFT; + } + + memcpy(dest + *app_ids_len, resp.data.asBytes + 1, resp.length - 5); + + *app_ids_len += (resp.length - 5); + } + return PM3_SUCCESS; +} + + +// none +static int get_desfire_fileids(uint8_t *dest, uint8_t *file_ids_len) { + uint8_t c[] = {MFDES_GET_FILE_IDS, 0x00, 0x00, 0x00}; // 0x6f + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(c), 0, c, sizeof(c)); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(WARNING, _RED_(" Timed-out")); + return PM3_ETIMEOUT; + } + + uint8_t isOK = resp.oldarg[0] & 0xff; + if (!isOK) { + PrintAndLogEx(WARNING, _RED_("Command unsuccessful")); + return PM3_ESOFT; + } + + if (resp.data.asBytes[resp.length - 4] == 0x91 && resp.data.asBytes[resp.length - 3] == 0x00) { + *file_ids_len = resp.length - 5; + memcpy(dest, resp.data.asBytes + 1, *file_ids_len); + return PM3_SUCCESS; + } + + return PM3_ESOFT; +} + static int CmdHF14ADesInfo(const char *Cmd) { (void)Cmd; // Cmd is not used so far @@ -93,6 +344,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { if (!WaitForResponseTimeout(CMD_HF_DESFIRE_INFO, &resp, 1500)) { PrintAndLogEx(WARNING, "Command execute timeout"); + DropField(); return PM3_ETIMEOUT; } @@ -147,6 +399,27 @@ static int CmdHF14ADesInfo(const char *Cmd) { PrintAndLogEx(SUCCESS, " Protocol : %s", getProtocolStr(package->versionSW[6])); PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "Card capabilities"); + uint8_t major = package->versionSW[3]; + uint8_t minor = package->versionSW[4]; + if (major == 0 && minor == 4) + PrintAndLogEx(INFO, "\t0.4 - DESFire MF3ICD40, No support for APDU (only native commands)"); + if (major == 0 && minor == 5) + PrintAndLogEx(INFO, "\t0.5 - DESFire MF3ICD40, Support for wrapping commands inside ISO 7816 style APDUs"); + if (major == 0 && minor == 6) + PrintAndLogEx(INFO, "\t0.6 - DESFire MF3ICD40, Add ISO/IEC 7816 command set compatibility"); + if (major == 1 && minor == 3) + PrintAndLogEx(INFO, "\t1.3 - DESFire Ev1, Support extended APDU commands"); + if (major == 1 && minor == 4) + PrintAndLogEx(INFO, "\t1.4 - DESFire Ev1, N/A information about this version. report to iceman!"); + if (major == 2 && minor == 0) + PrintAndLogEx(INFO, "\t2.0 - DESFire Ev2, Originality check, proximity check"); + + if (major == 0 && minor == 2) + PrintAndLogEx(INFO, "\t0.2 - DESFire Light, Originality check, "); + + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + // Signature originality check uint8_t signature[56] = {0}; size_t signature_len = 0; @@ -155,24 +428,19 @@ static int CmdHF14ADesInfo(const char *Cmd) { desfire_print_signature(package->uid, signature, signature_len); // Master Key settings - getKeySettings(NULL); + uint8_t master_aid[3] = {0x00, 0x00, 0x00}; + getKeySettings(master_aid); // Free memory on card - uint8_t c[] = {GET_FREE_MEMORY, 0x00, 0x00, 0x00}; // 0x6E - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, (INIT | DISCONNECT), sizeof(c), 0, c, sizeof(c)); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) - return PM3_ETIMEOUT; - - PrintAndLogEx(INFO, " Free memory"); - // Desfire Light doesn't support FREEMEM (len = 5) - if (resp.length == 8) { - uint8_t tmp[3]; - memcpy(tmp, resp.data.asBytes + 1, 3); - PrintAndLogEx(SUCCESS, " Available free memory on card : " _GREEN_("%d bytes"), le24toh(tmp)); + PrintAndLogEx(INFO, " Free memory"); + uint32_t free_mem = 0; + if (get_desfire_freemem(&free_mem) == PM3_SUCCESS) { + desfire_print_freemem(free_mem); } else { PrintAndLogEx(SUCCESS, " Card doesn't support 'free mem' cmd"); } PrintAndLogEx(INFO, "-------------------------------------------------------------"); + /* Card Master key (CMK) 0x00 AID = 00 00 00 (card level) Application Master Key (AMK) 0x00 AID != 00 00 00 @@ -187,6 +455,8 @@ static int CmdHF14ADesInfo(const char *Cmd) { keys 12,13,14,15 R */ + + DropField(); return PM3_SUCCESS; } @@ -230,13 +500,13 @@ char *getVersionStr(uint8_t major, uint8_t minor) { char *retStr = buf; if (major == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("Desfire MF3ICD40") ")", major, minor); + sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire MF3ICD40") ")", major, minor); else if (major == 0x01 && minor == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("Desfire EV1") ")", major, minor); + sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV1") ")", major, minor); else if (major == 0x12 && minor == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("Desfire EV2") ")", major, minor); + sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV2") ")", major, minor); else if (major == 0x30 && minor == 0x00) - sprintf(retStr, "%x.%x ( " _YELLOW_("Desfire Light") ")", major, minor); + sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire Light") ")", major, minor); else sprintf(retStr, "%x.%x ( " _YELLOW_("Unknown") ")", major, minor); return buf; @@ -246,267 +516,162 @@ void getKeySettings(uint8_t *aid) { char messStr[512] = {0x00}; const char *str = messStr; - uint8_t isOK = 0; - PacketResponseNG resp; - if (aid == NULL) { + if (memcmp(aid, "\x00\x00\x00", 3) == 0) { // CARD MASTER KEY - PrintAndLogEx(INFO, " CMK - PICC, Card Master Key settings"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); - { - uint8_t data[] = {GET_KEY_SETTINGS, 0x00, 0x00, 0x00}; // 0x45 - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); - } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} - isOK = resp.oldarg[0] & 0xff; - if (!isOK) { - PrintAndLogEx(WARNING, _RED_(" Can't select master application")); + + if (get_desfire_select_application(aid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, _RED_(" Can't select AID")); + DropField(); return; } - // Not supported 02 91 1c c4 ca - // OK - 02 0f 01 91 00 7e fe - if (resp.length == 7 ) { - + + // KEY Settings - AMK + uint8_t num_keys = 0; + uint8_t key_setting = 0; + if (get_desfire_keysettings(&key_setting, &num_keys) == PM3_SUCCESS) { // number of Master keys (0x01) - PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), resp.data.asBytes[2]); - - str = (resp.data.asBytes[1] & (1 << 3)) ? _GREEN_("YES") : "NO"; - PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", str); + PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), (num_keys & 0x3F) ); - str = (resp.data.asBytes[1] & (1 << 2)) ? _GREEN_("YES") : "NO"; - PrintAndLogEx(SUCCESS, " [0x04] CMK required for create/delete : %s", str); - - str = (resp.data.asBytes[1] & (1 << 1)) ? _GREEN_("YES") : "NO"; - PrintAndLogEx(SUCCESS, " [0x02] Directory list access with CMK : %s", str); - - str = (resp.data.asBytes[1] & (1 << 0)) ? _GREEN_("YES") : "NO"; - PrintAndLogEx(SUCCESS, " [0x01] CMK is changeable : %s", str); + PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", (key_setting & (1 << 3)) ? _GREEN_("YES") : "NO"); + PrintAndLogEx(SUCCESS, " [0x04] CMK required for create/delete : %s", (key_setting & (1 << 2)) ? _GREEN_("YES") : "NO"); + PrintAndLogEx(SUCCESS, " [0x02] Directory list access with CMK : %s", (key_setting & (1 << 1)) ? _GREEN_("YES") : "NO"); + PrintAndLogEx(SUCCESS, " [0x01] CMK is changeable : %s", (key_setting & (1 << 0)) ? _GREEN_("YES") : "NO"); + } else { + PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings")); } - { - uint8_t data[] = {GET_KEY_VERSION, 0x00, 0x00, 0x01, 0x0, 0x00}; // 0x64 - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + + memset(messStr, 0x00, sizeof(messStr)); + str = " Operation of PICC master key : " _YELLOW_("%s"); + + // 2 MSB denotes + switch (num_keys >> 6) { + case 0: + PrintAndLogEx(SUCCESS, str, "(3)DES"); + break; + case 1: + PrintAndLogEx(SUCCESS, str, "3K3DES"); + break; + case 2: + PrintAndLogEx(SUCCESS, str, "AES"); + break; + default: + break; } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { return; } - isOK = resp.oldarg[0] & 0xff; - if (!isOK) { - PrintAndLogEx(WARNING, _RED_(" Can't read key-version")); - return; - } - if (resp.length == 6) { - PrintAndLogEx(SUCCESS, ""); - PrintAndLogEx(SUCCESS, " Master key Version : " _YELLOW_("%d (0x%02x)"), resp.data.asBytes[3], resp.data.asBytes[3]); + + uint8_t cmk_num_versions = 0; + if (get_desfire_keyversion(0, &cmk_num_versions) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, " PICC Master key Version : " _YELLOW_("%d (0x%02x)"), cmk_num_versions, cmk_num_versions); PrintAndLogEx(INFO, " ----------------------------------------------------------"); } - - { - // 0x0A - uint8_t data[] = {AUTHENTICATE, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x0A, KEY 0 - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); - } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} - PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (resp.length == 13) ? _YELLOW_("YES") : "NO"); - { - // 0x1A - uint8_t data[] = {AUTHENTICATE_ISO, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x1A, KEY 0 - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); - } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} - PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (resp.length >= 13) ? _YELLOW_("YES") : "NO"); + // Authentication tests + int res = test_desfire_authenticate(); + if (res == PM3_ETIMEOUT) return; + PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); - { - // 0xAA - uint8_t data[] = {AUTHENTICATE_AES, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0xAA, KEY 0 - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); - } - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {return;} - PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (resp.length >= 13) ? _YELLOW_("YES") : "NO"); + res = test_desfire_authenticate_iso(); + if (res == PM3_ETIMEOUT) return; + PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); + + res = test_desfire_authenticate_aes(); + if (res == PM3_ETIMEOUT) return; + PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); } else { // AID - APPLICATION MASTER KEYS - PrintAndLogEx(SUCCESS, " AMK - Application Master Key settings"); PrintAndLogEx(INFO, " ----------------------------------------------------------"); - PrintAndLogEx(INFO, " select AID: " _YELLOW_("%s"), sprint_hex(aid, 3) ); - // SELECT AID - { - uint8_t data[] = {SELECT_APPLICATION, 0x00, 0x00, 0x03, aid[0], aid[1], aid[2], 0x00}; // 0x5a - //memcpy(data + 1, aid, 3); - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT, sizeof(data), 0, data, sizeof(data)); - } - - if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { - PrintAndLogEx(WARNING, _RED_(" Timed-out")); - return; - } - isOK = resp.oldarg[0] & 0xff; - if (!isOK) { - PrintAndLogEx(WARNING, " Can't select AID: " _RED_("%s"), sprint_hex(aid, 3)); + if (get_desfire_select_application(aid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, _RED_(" Can't select AID")); + DropField(); return; } - // KEY SETTINGS - { - uint8_t data[] = {GET_KEY_SETTINGS, 0x00, 0x00, 0x00}; // 0x45 - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); - } - - if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { - return; - } - isOK = resp.oldarg[0] & 0xff; - if (!isOK) { - PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings")); + // KEY Settings - AMK + uint8_t num_keys = 0; + uint8_t key_setting = 0; + if (get_desfire_keysettings(&key_setting, &num_keys) == PM3_SUCCESS) { + desfire_print_keysetting(key_setting, num_keys); } else { - // Access rights. - uint8_t rights = (resp.data.asBytes[1] >> 4 & 0x0F); - switch (rights) { - case 0x0: - str = "AMK authentication is necessary to change any key (default)"; - break; - case 0xE: - str = "Authentication with the key to be changed (same KeyNo) is necessary to change a key"; - break; - case 0xF: - str = "All keys (except AMK,see Bit0) within this application are frozen"; - break; - default: - str = "Authentication with the specified key is necessary to change any key. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed."; - break; - } - PrintAndLogEx(SUCCESS, "Changekey Access rights"); - PrintAndLogEx(SUCCESS, "-- " _GREEN_("%s"), str); - PrintAndLogEx(SUCCESS, ""); - // same as CMK - str = (resp.data.asBytes[1] & (1 << 3)) ? "YES" : "NO"; - PrintAndLogEx(SUCCESS, " 0x08 Configuration changeable : %s", str); - str = (resp.data.asBytes[1] & (1 << 2)) ? "NO" : "YES"; - PrintAndLogEx(SUCCESS, " 0x04 AMK required for create/delete : %s", str); - str = (resp.data.asBytes[1] & (1 << 1)) ? "NO" : "YES"; - PrintAndLogEx(SUCCESS, " 0x02 Directory list access with AMK : %s", str); - str = (resp.data.asBytes[1] & (1 << 0)) ? "YES" : "NO"; - PrintAndLogEx(SUCCESS, " 0x01 AMK is changeable : %s", str); + PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings")); } // KEY VERSION - AMK - { - uint8_t data[] = {GET_KEY_VERSION, 0x00, 0x00, 0x01, 0x00, 0x00}; // 0x64 - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, DISCONNECT, sizeof(data), 0, data, sizeof(data)); - } - - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(WARNING, _RED_(" Timed-out")); - return; - } - - int numOfKeys; - - isOK = resp.oldarg[0] & 0xff; - if (isOK == false) { - PrintAndLogEx(WARNING, " Can't read Application Master key version. Trying all keys"); - //numOfKeys = MAX_NUM_KEYS; - } else { - numOfKeys = resp.data.asBytes[1]; - PrintAndLogEx(SUCCESS, " Max number of keys : %d", numOfKeys); - PrintAndLogEx(SUCCESS, " Application Master key Version : %d (0x%02x)", resp.data.asBytes[3], resp.data.asBytes[3]); + uint8_t num_version = 0; + if (get_desfire_keyversion(0, &num_version) == PM3_SUCCESS) { PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, " Application keys"); + desfire_print_keyversion(0, num_version); + } else { + PrintAndLogEx(WARNING, " Can't read AID master key version. Trying all keys"); } - // LOOP over numOfKeys that we got before. // From 0x01 to numOfKeys. We already got 0x00. (AMK) - // TODO (iceman) - /* - for (int i = 0x01; i <= 0x0f; ++i) { + num_keys &= 0x3F; + if (num_keys > 1) { + for (uint8_t i = 0x01; i < num_keys; ++i) { + if (get_desfire_keyversion(i, &num_version) == PM3_SUCCESS) { + desfire_print_keyversion(i, num_version); + } else { + PrintAndLogEx(WARNING, " Can't read key %d (0x%02x) version", i, i); } - */ + } + } + PrintAndLogEx(INFO, "-------------------------------------------------------------"); } + + DropField(); } static int CmdHF14ADesEnumApplications(const char *Cmd) { (void)Cmd; // Cmd is not used so far - uint8_t isOK = 0x00; +// uint8_t isOK = 0x00; uint8_t aid[3]; - { - uint8_t data[] = {GET_APPLICATION_IDS, 0x00, 0x00, 0x00}; //0x6a - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | CLEARTRACE | DISCONNECT, sizeof(data), 0, data, sizeof(data)); - } - PacketResponseNG resp; - - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - return PM3_ETIMEOUT; - } - - isOK = resp.oldarg[0] & 0xff; - if (!isOK) { - PrintAndLogEx(WARNING, _RED_("Command unsuccessful")); + uint8_t app_ids[78] = {0}; + uint8_t app_ids_len = 0; + + uint8_t file_ids[33] = {0}; + uint8_t file_ids_len = 0; + + if (get_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Can't get list of applications on tag"); return PM3_ESOFT; } + PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "-- Desfire Enumerate Applications ---------------------------"); + PrintAndLogEx(INFO, "-- Mifare DESFire Enumerate applications --------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") "application%c", app_ids_len / 3, (app_ids_len == 3) ? ' ' : 's'); + + for (int i = 0; i < app_ids_len; i += 3) { -// PacketResponseNG respAid; -// PacketResponseNG respFiles; + aid[0] = app_ids[i]; + aid[1] = app_ids[i + 1]; + aid[2] = app_ids[i + 2]; + + PrintAndLogEx(SUCCESS, " AID %d : " _GREEN_("%02X %02X %02X"), i, app_ids[i], app_ids[i+1], app_ids[i+2]); - uint8_t num = 0; - int max = resp.oldarg[1] - 3 - 2; - PrintAndLogEx(INFO," MAX %d", max); - - for (int i = 1; i < max; i += 3) { - PrintAndLogEx(SUCCESS, " Aid %d : %02X %02X %02X ", num, resp.data.asBytes[i], resp.data.asBytes[i+1], resp.data.asBytes[i+2]); - num++; - - aid[0] = resp.data.asBytes[i]; - aid[1] = resp.data.asBytes[i + 1]; - aid[2] = resp.data.asBytes[i + 2]; getKeySettings(aid); -/* - // Select Application - { - uint8_t data[] = {SELECT_APPLICATION, 0x00, 0x00, 0x03, aid[0], aid[1], aid[2], 0x00}; // 0x5a - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); - } - - if (!WaitForResponseTimeout(CMD_ACK, &respAid, 1500)) { - PrintAndLogEx(WARNING, _RED_(" Timed-out")); - continue; - } - isOK = respAid.data.asBytes[2] & 0xff; - if (isOK != 0x00) { - PrintAndLogEx(WARNING, " Can't select AID: " _RED_("%s"), sprint_hex(resp.data.asBytes + i, 3)); - continue; - } - // Get File IDs - { - uint8_t data[] = {GET_FILE_IDS, 0x00, 0x00, 0x00}; // 0x6f - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); - } - - if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) { - PrintAndLogEx(WARNING, _RED_(" Timed-out")); - continue; - } else { - isOK = respFiles.data.asBytes[2] & 0xff; - if (!isOK) { - PrintAndLogEx(WARNING, _RED_(" Can't get file ids ")); - } else { - int respfileLen = resp.oldarg[1] - 3 - 2; - for (int j = 0; j < respfileLen; ++j) { - PrintAndLogEx(SUCCESS, " Fileid %d :", resp.data.asBytes[j + 3]); - } + if (get_desfire_fileids(file_ids, &file_ids_len) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") "file%c", file_ids_len, (file_ids_len == 1) ? ' ' : 's'); + for (int i = 0; i < file_ids_len; ++i) { + PrintAndLogEx(SUCCESS, " Fileid %d (0x%02x)", file_ids[i], file_ids[i]); } } +/* // Get ISO File IDs { uint8_t data[] = {GET_ISOFILE_IDS, 0x00, 0x00, 0x00}; // 0x61 @@ -530,11 +695,22 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { */ } PrintAndLogEx(INFO, "-------------------------------------------------------------"); + DropField(); return PM3_SUCCESS; } +/* + uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00}; + int res = ExchangeRAW14a(cmd, sizeof(cmd), false, false, data, sizeof(data), &datalen, false); + + if (!res && datalen > 1 && data[0] == 0x09) { + SLmode = 0; + } + +*/ -// MIAFRE DesFire Authentication + +// MIAFRE DESFire Authentication // #define BUFSIZE 256 static int CmdHF14ADesAuth(const char *Cmd) { From be3932d3c0a3306c73a872361819cfd138c2b6a6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Mar 2020 12:05:48 +0100 Subject: [PATCH 173/298] textual --- client/cmdhfmfp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 641e959a1..2a1533344 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -138,10 +138,10 @@ static int CmdHFMFPInfo(const char *Cmd) { PrintAndLogEx(INFO, "SL 0: initial delivery configuration, used for card personalization"); break; case 1: - PrintAndLogEx(INFO, "SL 1: backwards functional compatibility mode (with MIFARE Classic 1K and MIFARE Classic 4K) with an optional AES authentication"); + PrintAndLogEx(INFO, "SL 1: backwards functional compatibility mode (with MIFARE Classic 1K / 4K) with an optional AES authentication"); break; case 2: - PrintAndLogEx(INFO, "SL 2: "); + PrintAndLogEx(INFO, "SL 2: 3-Pass Authentication based on AES followed by MIFARE CRYPTO1 authentication, communication secured by MIFARE CRYPTO1"); break; case 3: PrintAndLogEx(INFO, "SL 3: 3-Pass authentication based on AES, data manipulation commands secured by AES encryption and an AES based MACing method."); From 4d335b1fbe1039ad7e84b84620c86ad2f6c6cad8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Mar 2020 12:16:55 +0100 Subject: [PATCH 174/298] text --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b75de3ee..607bcd64e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix 'hf mfdes enum' - now actually manages to enumerate files under all AID's. :smiley: (@iceman1001) + - Fix 'hf mfdes info' - now detects DESFire light and work properly Wrapped commands :+1: (@iceman1001) - :smiling_imp: support (@doegox) - Additional colour changes as recommended by @iceman (@dunderhay) - Change type colour for `hf 14a` card types (@dunderhay) From cf47e50267b7dd15a2228a8bee23a6a80fd34c26 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Mar 2020 12:18:29 +0100 Subject: [PATCH 175/298] define additional frame --- include/protocols.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/protocols.h b/include/protocols.h index 519172af6..89038a789 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -385,6 +385,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MFDES_CHANGE_KEY 0xc4 #define MFDES_GET_KEY_VERSION 0x64 #define MFDES_AUTHENTICATION_FRAME 0xAF +#define MFDES_ADDITIONAL_FRAME 0xAF #define MFDES_READSIG 0x3C // LEGIC Commands From 8ef3f3438435157faf613d1b816c83c08d81915c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 20 Mar 2020 11:09:23 +0100 Subject: [PATCH 176/298] update ex4x05 timing, @mwalker (@marshmellow42, https://github.com/marshmellow42/proxmark3/commit/1ebf9f25602371b3542097efe94c56edc42638c4) --- armsrc/lfops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 84bddc192..904d37c61 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2399,13 +2399,13 @@ void SendForward(uint8_t fwd_bit_count) { TurnReadLF_off(EM_START_GAP); TurnReadLFOn(18 * 8); - // now start writting with bitbanging the antenna. + // now start writting with bitbanging the antenna. (each bit should be 32*8 total length) while (fwd_bit_sz-- > 0) { //prepare next bit modulation if (((*fwd_write_ptr++) & 1) == 1) { WaitUS(32 * 8); } else { TurnReadLF_off(23 * 8); - TurnReadLFOn(18 * 8); + TurnReadLFOn(32-23 * 8); } } } From d870b52d7bac48d294c5966829c1b8a41ed18dd3 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sat, 21 Mar 2020 13:37:33 +1100 Subject: [PATCH 177/298] Update cmdlfkeri.c --- client/cmdlfkeri.c | 40 ++++++++-------------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 4a0c3c8fd..982eb8193 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -59,20 +59,15 @@ typedef enum {Scramble = 0,Descramble = 1} KeriMSScramble_t; static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *ID, uint32_t *CardID) { // 255 = Not used/Unknown other values are the bit offset in the ID/FC values - uint8_t CardToID [] = { 255,255,255,255, 13, 12, 17, 5,255, 6,255, 18, 8,255, 0, 7, - 10,255,255, 11, 4, 1,255, 19,255, 20, 2,255, 3, 9,255,255 }; - uint8_t CardToFC [] = { 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, - 255,255, 2,255,255,255,255,255,255,255,255,255,255,255, 1,255 }; + uint8_t CardToID [] = { 255,255,255,255, 13, 12, 20, 5, 16, 6, 21, 17, 8,255, 0, 7, + 10, 15,255, 11, 4, 1,255, 18,255, 19, 2, 14, 3, 9,255,255 }; + + uint8_t CardToFC [] = { 255,255,255,255,255,255,255,255,255,255,255,255,255, 0,255,255, + 255,255, 2,255,255,255, 3,255, 4,255,255,255,255,255, 1,255 }; uint8_t CardIdx; // 0 - 31 bool BitState; - // Used to track known bit states - remove when all bit maps are known - char IDDecodeState[33] = {0x00}; - char FCDecodeState[33] = {0x00}; - memset (IDDecodeState,'-',32); - memset (FCDecodeState,'-',32); - if (Action == Descramble) { *FC = 0; *ID = 0; @@ -82,31 +77,12 @@ static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *I // Card ID if (CardToID[CardIdx] < 32) { *ID = *ID | (BitState << CardToID[CardIdx]); - // Remove when all bits are known - IDDecodeState[31-CardToID[CardIdx]] = '0'+BitState; } // Card FC if (CardToFC[CardIdx] < 32) { *FC = *FC | (BitState << CardToFC[CardIdx]); - // Remove when all bits are known - FCDecodeState[31-CardToFC[CardIdx]] = '0'+BitState; } } - - // Patch for bit order group unknown - remove when all Keri MS Bits maps are known - // Reverse order for easy mapping for unknowns - // I know that these bit groups are a in the correct location, unknown order. - if (IDDecodeState[31-17] == '1') IDDecodeState[31-17] = '?'; - if (IDDecodeState[31-18] == '1') IDDecodeState[31-18] = '?'; - if (IDDecodeState[31-19] == '1') IDDecodeState[31-19] = '?'; - if (IDDecodeState[31-20] == '1') IDDecodeState[31-20] = '?'; - - if (FCDecodeState[31- 1] == '1') FCDecodeState[31- 1] = '?'; - if (FCDecodeState[31- 2] == '1') FCDecodeState[31- 2] = '?'; - - PrintAndLogEx(SUCCESS, "Partial Keri MS decode"); - PrintAndLogEx(SUCCESS, "BitState ID : %s",IDDecodeState); - PrintAndLogEx(SUCCESS, "BitState FC : %s",FCDecodeState); } if (Action == Scramble) @@ -119,12 +95,12 @@ static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *I if (CardToID[CardIdx] < 32) { if ((*ID & (1 << CardToID[CardIdx])) > 0) *CardID |= (1 << CardIdx); - } - // Card FC + } + // Card FC if (CardToFC[CardIdx] < 32) { if ((*ID & (1 << CardToFC[CardIdx])) > 0) *CardID |= (1 << CardIdx); - } + } } // Fixed bits and parity/check bits From 311f43172f1056fab458e3c35b1bc119b0679477 Mon Sep 17 00:00:00 2001 From: Artem Gnatyuk Date: Sat, 21 Mar 2020 15:48:16 +0700 Subject: [PATCH 178/298] LF_EM4100EMULV1 - renamed to LF_EM4100EMUL. Make more easy control. Short click - switch slot and satrt simulation LF_EM4100EMULV2 - deleted. LF_EM4100EMULV3 - renamed to LF_EM4100RWC --- armsrc/Standalone/Makefile.hal | 19 +- armsrc/Standalone/Makefile.inc | 26 +-- .../{lf_em4100emulV1.c => lf_em4100emul.c} | 31 +-- armsrc/Standalone/lf_em4100emulV3.c | 197 ------------------ .../{lf_em4100emulV2.c => lf_em4100rwc.c} | 8 +- 5 files changed, 26 insertions(+), 255 deletions(-) rename armsrc/Standalone/{lf_em4100emulV1.c => lf_em4100emul.c} (77%) delete mode 100644 armsrc/Standalone/lf_em4100emulV3.c rename armsrc/Standalone/{lf_em4100emulV2.c => lf_em4100rwc.c} (96%) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index 776ae3f0f..fd52817db 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -35,28 +35,19 @@ define KNOWN_STANDALONE_DEFINITIONS | HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth | | (RDV4 only) | storing in flashmem - Bogito | +----------------------------------------------------------+ -| HF_14ASNIFF | 14a sniff to flashmem | -| (RDV4 only) | | -+----------------------------------------------------------+ -| LF_ICEHID | LF HID collector to flashmem | -| (RDV4 only) | | -+----------------------------------------------------------+ -| LF_EM4100EMULV1 | Simulate predefined em4100 tags only | +| LF_EM4100EMUL | Simulate predefined em4100 tags only | | | | +----------------------------------------------------------+ -| LF_EM4100EMULV2 | Read/simulate em4100 tags | -| | | -+----------------------------------------------------------+ -| LF_EM4100EMULV3 | Read/simulate em4100 tags & clone it | +| LF_EM4100RWC | Read/simulate em4100 tags & clone it | | | to T555x tags | +----------------------------------------------------------+ endef -STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_ICEHID LF_EM4100EMULV1 LF_EM4100EMULV2 LF_EM4100EMULV3 -STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG HF_14ASNIFF +STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_EM4100EMUL LF_EM4100RWC +STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG STANDALONE_MODES_REQ_SMARTCARD := -STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG HF_14ASNIFF LF_ICEHID +STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE) ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),) diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index e7ca1bfe0..686cc66f0 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -33,23 +33,11 @@ endif ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS))) SRC_STANDALONE = hf_bog.c endif -# WITH_STANDALONE_HF_14ASNIFF -ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS))) - SRC_STANDALONE = hf_14asniff.c -endif -# WITH_STANDALONE_LF_ICEHID -ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS))) - SRC_STANDALONE = lf_icehid.c -endif -# WITH_STANDALONE_LF_EM4100EMULV1 -ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMULV1,$(APP_CFLAGS))) - SRC_STANDALONE = lf_em4100emulV1.c -endif -# WITH_STANDALONE_LF_EM4100EMULV2 -ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMULV2,$(APP_CFLAGS))) - SRC_STANDALONE = lf_em4100emulV2.c -endif -# WITH_STANDALONE_LF_EM4100EMULV3 -ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMULV3,$(APP_CFLAGS))) - SRC_STANDALONE = lf_em4100emulV3.c +# WITH_STANDALONE_LF_EM4100EMUL +ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMUL,$(APP_CFLAGS))) + SRC_STANDALONE = lf_em4100emul.c endif +# WITH_STANDALONE_LF_EM4100RWC +ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RWC,$(APP_CFLAGS))) + SRC_STANDALONE = lf_em4100rwc.c +endif \ No newline at end of file diff --git a/armsrc/Standalone/lf_em4100emulV1.c b/armsrc/Standalone/lf_em4100emul.c similarity index 77% rename from armsrc/Standalone/lf_em4100emulV1.c rename to armsrc/Standalone/lf_em4100emul.c index d132f3650..907445912 100644 --- a/armsrc/Standalone/lf_em4100emulV1.c +++ b/armsrc/Standalone/lf_em4100emul.c @@ -5,9 +5,8 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// LF emul V1 - Very simple mode. Simulate only predefined in low[] IDs -// Short click - change current slot -// Long press - simulate tag ID from current slot +// LF emul - Very simple mode. Simulate only predefined in low[] IDs +// Short click - select next slot and start simulation //----------------------------------------------------------------------------- #include "standalone.h" #include "proxmark3_arm.h" @@ -32,7 +31,7 @@ uint8_t *bba,slots_count; int buflen; void ModInfo(void) { - DbpString(" LF EM4100 simulate standalone V1"); + DbpString(" LF EM4100 simulator standalone mode"); } uint64_t ReversQuads(uint64_t bits){ @@ -72,6 +71,7 @@ void ConstructEM410xEmulBuf(uint64_t id) { } void LED_Slot(int i) { + LEDsoff(); if (slots_count > 4) { LED(i % MAX_IND, 0); //binary indication for slots_count > 4 } else { @@ -82,26 +82,17 @@ void LED_Slot(int i) { void RunMod() { StandAloneMode(); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - int selected = 0; + int selected = 0; //selected slot after start slots_count = sizeof(low)/sizeof(low[0]); bba = BigBuf_get_addr(); - LED_Slot(selected); for (;;) { WDT_HIT(); if (data_available()) break; - int button_pressed = BUTTON_HELD(1000); - SpinDelay(300); - if (button_pressed == 1) { - SpinUp(100); - SpinOff(10); - LED_Slot(selected); - ConstructEM410xEmulBuf(ReversQuads(low[selected])); - SimulateTagLowFrequency(buflen, 0, true); - LED_Slot(selected); - } else if (button_pressed < 0) { - selected = (selected + 1) % slots_count; - LEDsoff(); - LED_Slot(selected); - } + SpinDelay(100); + SpinUp(100); + LED_Slot(selected); + ConstructEM410xEmulBuf(ReversQuads(low[selected])); + SimulateTagLowFrequency(buflen, 0, true); + selected = (selected + 1) % slots_count; } } diff --git a/armsrc/Standalone/lf_em4100emulV3.c b/armsrc/Standalone/lf_em4100emulV3.c deleted file mode 100644 index b1bf0d930..000000000 --- a/armsrc/Standalone/lf_em4100emulV3.c +++ /dev/null @@ -1,197 +0,0 @@ -//----------------------------------------------------------------------------- -// Artyom Gnatyuk, 2020 -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// LF emul V3 - This mode can simulate ID from selected slot, read ID to -// selected slot, write from selected slot to T5555 tag and store -// readed ID to flash (only RDV4). Also you can set predefined IDs -// in any slot. -// To recall stored ID from flash execute: -// mem dump o offset l 5 p -// where offset = 5 * selected slot -//----------------------------------------------------------------------------- -#include "standalone.h" -#include "proxmark3_arm.h" -#include "appmain.h" -#include "fpgaloader.h" -#include "lfops.h" -#include "util.h" -#include "dbprint.h" -#include "ticks.h" -#include "string.h" -#include "BigBuf.h" - -#ifdef WITH_FLASH -#include "flashmem.h" -#endif - -#define MAX_IND 16 // 4 LEDs - 2^4 combinations -#define CLOCK 64 //for 125kHz - -// low & high - array for storage IDs. Its length must be equal. -// Predefined IDs must be stored in low[]. -// In high[] must be nulls -uint64_t low[] = {0x565AF781C7,0x540053E4E2,0x1234567890,0,0,0,0,0,0,0,0,0,0,0,0,0}; -uint32_t high[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -uint8_t *bba,slots_count; -int buflen; - -void ModInfo(void) { - DbpString(" LF EM4100 simulate standalone V3"); -} - -uint64_t ReversQuads(uint64_t bits){ - uint64_t result = 0; - for (int i = 0; i < 16; i++){ - result += ((bits >> (60 - 4 *i)) & 0xf) << (4 * i); - } - return result >> 24; -} - -void FillBuff(uint8_t bit) { - memset (bba + buflen, bit, CLOCK / 2); - buflen += (CLOCK / 2); - memset (bba + buflen, bit^1,CLOCK / 2); - buflen += (CLOCK / 2); -} - -void ConstructEM410xEmulBuf(uint64_t id) { - - int i, j, binary[4], parity[4]; - buflen = 0; - for (i = 0; i < 9; i++) - FillBuff(1); - parity[0] = parity[1] = parity[2] = parity[3] = 0; - for (i = 0; i < 10; i++) { - for (j = 3; j >= 0; j--, id /= 2) - binary[j] = id % 2; - for (j = 0; j < 4; j++) - FillBuff(binary[j]); - FillBuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); - for (j = 0; j < 4; j++) - parity[j] ^= binary[j]; - } - for (j = 0; j < 4; j++) - FillBuff(parity[j]); - FillBuff(0); -} - -void LED_Slot(int i) { - if (slots_count > 4) { - LED(i % MAX_IND, 0); //binary indication, usefully for slots_count > 4 - } else { - LED(1 << i,0); //simple indication for slots_count <=4 - } -} - -void FlashLEDs(uint32_t speed, uint8_t times) { - for (int i = 0; i < times * 2; i++) { - LED_A_INV(); - LED_B_INV(); - LED_C_INV(); - LED_D_INV(); - SpinDelay(speed); - } -} - -#ifdef WITH_FLASH -void SaveIDtoFlash (int addr, uint64_t id) { - uint8_t b, *ptr; - for (int i = 0; i < 5; i++) { - b = (uint8_t) (id >> 8 * i & 0xff); - ptr = &b; - Flash_WriteData(addr * 5 + 4 - i,ptr,1); - } -} -#endif - -void RunMod() { - StandAloneMode(); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - int selected = 0; - //state 0 - select slot - // 1 - read tag to selected slot, - // 2 - simulate tag from selected slot - // 3 - write to T5555 tag - uint8_t state = 0; - slots_count = sizeof(low)/sizeof(low[0]); - bba = BigBuf_get_addr(); - LED_Slot(selected); - for (;;) { - WDT_HIT(); - if (data_available()) break; - int button_pressed = BUTTON_HELD(1000); - SpinDelay(300); - switch (state){ - case 0: - // Select mode - if (button_pressed == 1) { - // Long press - switch to simulate mode - SpinUp(100); - SpinOff(100); - LED_Slot(selected); - state = 2; - } else if (button_pressed < 0) { - // Click - switch to next slot - selected = (selected + 1) % slots_count; - LEDsoff(); - LED_Slot(selected); - } - break; - case 1: - // Read mode. - if (button_pressed > 0) { - // Long press - switch to read mode - SpinUp(100); - SpinOff(10); - LED_Slot(selected); - state = 3; - } else if (button_pressed < 0) { - // Click - exit to select mode - CmdEM410xdemod(1, &high[selected], &low[selected], 0); - FlashLEDs(100,5); - #ifdef WITH_FLASH - SaveIDtoFlash(selected, low[selected]); - #endif - state = 0; - } - break; - case 2: - // Simulate mode - if (button_pressed > 0) { - // Long press - switch to read mode - SpinDown(100); - SpinOff(10); - LED_Slot(selected); - state = 1; - } else if (button_pressed < 0) { - // Click - start simulating. Click again to exit from simelate mode - LED_Slot(selected); - ConstructEM410xEmulBuf(ReversQuads(low[selected])); - FlashLEDs(100,5); - SimulateTagLowFrequency(buflen, 0, 1); - LED_Slot(selected); - state = 0; // Switch to select mode - } - break; - case 3: - // Write tag mode - if (button_pressed > 0) { - // Long press - switch to select mode - SpinDown(100); - SpinOff(10); - LED_Slot(selected); - state = 0; - } else if (button_pressed < 0) { - // Click - write ID to tag - WriteEM410x(0, (uint32_t) (low[selected] >> 32), (uint32_t) (low[selected] & 0xffffffff)); - LED_Slot(selected); - state = 0; // Switch to select mode - } - break; - } - } -} diff --git a/armsrc/Standalone/lf_em4100emulV2.c b/armsrc/Standalone/lf_em4100rwc.c similarity index 96% rename from armsrc/Standalone/lf_em4100emulV2.c rename to armsrc/Standalone/lf_em4100rwc.c index 2b48aeced..a336112ba 100644 --- a/armsrc/Standalone/lf_em4100emulV2.c +++ b/armsrc/Standalone/lf_em4100rwc.c @@ -5,7 +5,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// LF emul V2 - This mode can simulate tag ID from selected slot and read tag ID +// LF rwc - This mode can simulate tag ID from selected slot and read tag ID // to selected slot and to flash (only RDV4). Also you can set // predefined IDs in any slot. // To recall stored ID from flash execute: @@ -39,7 +39,7 @@ uint8_t *bba,slots_count; int buflen; void ModInfo(void) { - DbpString(" LF EM4100 simulate standalone V2"); + DbpString(" LF EM4100 read/write/clone standalone mode"); } uint64_t ReversQuads(uint64_t bits){ @@ -79,6 +79,7 @@ void ConstructEM410xEmulBuf(uint64_t id) { } void LED_Slot(int i) { + LEDsoff(); if (slots_count > 4) { LED(i % MAX_IND, 0); //binary indication, usefully for slots_count > 4 } else { @@ -130,12 +131,10 @@ void RunMod() { // Long press - switch to simulate mode SpinUp(100); SpinOff(100); - LED_Slot(selected); state = 2; } else if (button_pressed < 0) { // Click - switch to next slot selected = (selected + 1) % slots_count; - LEDsoff(); LED_Slot(selected); } break; @@ -153,7 +152,6 @@ void RunMod() { if (button_pressed > 0) { // Long press - switch to read mode SpinDown(100); - SpinOff(10); LED_Slot(selected); state = 1; } else if (button_pressed < 0) { From 19aa618fbd94b3d4cac0ee2c2fd6104850a29e83 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Mar 2020 10:03:36 +0100 Subject: [PATCH 179/298] keys --- client/dictionaries/mfc_default_keys.dic | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 405f0d6f0..b3dfbd128 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1105,3 +1105,6 @@ fe04ecfe5577 # comfort inn hotel 4d57414c5648 4d48414c5648 +# +# unknown hotel key +6d9b485a4845 From 4443ae5500384e9dbced87a533aa4464e047e9f0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Mar 2020 10:04:03 +0100 Subject: [PATCH 180/298] rework script --- client/luascripts/hf-writer.lua | 189 ++++++++++++++++++-------------- 1 file changed, 105 insertions(+), 84 deletions(-) diff --git a/client/luascripts/hf-writer.lua b/client/luascripts/hf-writer.lua index 8c5740af6..010a0eb30 100644 --- a/client/luascripts/hf-writer.lua +++ b/client/luascripts/hf-writer.lua @@ -1,33 +1,45 @@ local utils = require('utils') local getopt = require('getopt') local read14a = require('read14a') -local uid = {} -- Array for eml files -local B = {} -- Array for B keys -local eml = {} -- Array for data in block 32 dig -local a = 0 -local b = 0 -local tab = string.rep('-', 64) + +[[-- +---Suggestions of improvement: +--- Add support another types of dumps: BIN, JSON +--- Maybe it will be not only as `mfc_gen3_writer`, like a universal dump manager. +--- Add undependence from the operation system. At the moment code not working in Linux. +--- Add more chinesse backdoors RAW commands for UID changing (find RAW for the 4 byte familiar chinese card, from native it soft: http://bit.ly/39VIDsU) +--- Hide system messages when you writing a dumps, replace it to some of like [#####----------] 40% + +-- iceman notes: +-- doesn't take consideration filepaths for dump files. +-- doesn't allow A keys for authenticating when writing +-- doesn't verify that card is magic gen3. +--]] copyright = '' author = 'Winds' version = 'v1.0.0' desc = [[ - That's script gives for you a easy way to write your an *.eml dumps, using a Proxmark 3. - It's working for 4 and 7 bytes NXP MIFARE Classic 1K cards. - The script has including an injection of UID changig for the Chinese Magic Cards GEN 3. - - Whith choosen an *.eml file you can do: + The script gives you a easy way to write your *.eml dumps onto normal MFC and magic Gen3 cards. - 1. Write it to the equals of current card UID. - 2. Write it to anther card with changable UID. - 3. Send command to lock UID for the Chinese Magic Cards GEN 3. - 4. Erease all data at the card and set the FFFFFFFFFFFF keys, and Access Conditions to 78778800. + Works with both 4 and 7 bytes NXP MIFARE Classic 1K cards. + The script also has the possibility to change UID and permanent lock uid on magic Gen3 cards. + + It supports the following functionality. + + 1. Write it to the same of current card UID. + 2. Write it to magic Gen3 card. + 3. Change uid to match dump on magic Gen3 card. + 4. Permanent lock UID on magic Gen3 card. + 5. Erase all data at the card and set the FF FF FF FF FF FF keys, and Access Conditions to 78778800. + + Script works in a wizard styled way. ]] example = [[ - 1. script run hf-writer + 1. script run mfc_gen3_writer ]] usage = [[ - You should choose your *.eml dump from being list to write it to the card by wizard + Select your *.eml dump from list to write to the card. ]] --- @@ -40,135 +52,144 @@ local function help() print(example) print(usage) end - -local function read() - u = read14a.read(true, true).uid - return u +--- +-- GetUID +local function GetUID() + return read14a.read(true, true).uid end - -local function fkey() - f = 'FFFFFFFFFFFF' - return f -end - -local function finish() +--- +-- +local function dropfield() read14a.disconnect() core.clearCommandBuffer() end - +--- +-- Wait for tag (MFC) local function wait() read14a.waitFor14443a() end - +--- +-- local function main(args) + -- Arguments for the script for o, a in getopt.getopt(args, 'h') do if o == 'h' then return help() end end - --File lienght check for detect 4 or 7 bytes + local files = {} -- Array for eml files + local b_keys = {} -- Array for B keys + local eml = {} -- Array for data in block 32 + local num_dumps = 0 -- num of found eml dump files + + local tab = string.rep('-', 64) + -- wait() print(tab) - if string.len(read()) == 14 then -- Detect 7 byte card - l = 29 -- 7 byte length of eml file - s = 7 + + local length = 23 + local e = 14 + -- Detect 7 byte card + if string.len(GetUID()) == 14 then + length = 29 e = 20 - else - l = 23 -- 4 byte length of eml file - s = 7 - e = 14 end - ---Listern EML files at Client catalog + + ---List all EML files in /client for _ in io.popen([[dir ".\" /b]]):lines() do -- for UNIX: ls + if string.find(_, '%.eml$') then - if string.len(_) == l then -- There length of eml file - a = a + 1 - uid[a] = string.sub(tostring(_), s, e) -- Cut UID from eml file - print(' ' .. a .. ' ' .. '|' .. ' ' .. uid[a]) + + if string.len(_) == length then -- The length of eml file + num_dumps = num_dumps + 1 + files[num_dumps] = string.sub(tostring(_), 7, e) -- Cut UID from eml file + print(' '..num_dumps..' | '..files[a]) end + end end print(tab) - print(' Your card has ' .. read() .. ' UID number\n') - print(' Choice your dump number to write (from 1 until ' .. a .. ')') + print(' Your card has UID '..GetUID()) + print('') + print(' Select which dump to write (1 until '..num_dumps..')') print(tab) - io.write(' --> ') + io.write(' --> ') local no = tonumber(io.read()) - local dump = io.open('./hf-mf-' .. uid[no] .. '-data.eml', 'r'); + local dump = io.open('./hf-mf-' .. files[no] .. '-data.eml', 'r'); print(tab) - print(' You have been selected ' .. no .. ' card dump, it UID is ' .. uid[no]) - ---EML get B key from opened EML file + print(' You have been selected ' .. no .. ' card dump, with UID : '..files[no]) + + --- Load eml file for _ in dump:lines() do table.insert(eml, _); end + + --- Extract B key from EML file + local b = 0 for i = 1, #eml do + print('line is type: ', type(eml[i]) ) + if (i % 4 == 0) then repeat b = b + 1 - B[b] = string.sub(tostring(eml[i]), (string.len(eml[i]) - 11), - string.len(eml[i])) -- Cut key from block + -- Cut key from block + b_keys[b] = string.sub(tostring(eml[i]), (string.len(eml[i]) - 11), string.len(eml[i])) until b % 4 == 0 end end + print(tab) - print(tab) - ---UID Changing - if (utils.confirm(' Do the UID changing?') == true) then + --- Change UID on certain version of magic Gen3 card. + if (utils.confirm(' Change UID ?') == true) then wait() - core.console('hf 14a raw -s -c -t 2000 90f0cccc10' .. tostring(eml[1])) + core.console('hf 14a raw -s -c -t 2000 90f0cccc10'..tostring(eml[1])) print(tab) - print(' The new card UID is: ' .. read()) + print(' The new card UID : ' .. GetUID()) end - print(tab) - ---UID Blocking - if (utils.confirm(' Would you like to BLOCK the UID for any changing?') == true) then + + --- Lock UID + if (utils.confirm(' Permanent lock UID ? (card can never change uid again) ') == true) then wait() core.console('hf 14a raw -s -c -t 2000 90fd111100') end + print(tab) + + --- Writing blocks + local default_key = 'FFFFFFFFFFFF' + local default_key_blk = 'FFFFFFFFFFFF78778800FFFFFFFFFFFF' + local empty = string.rep('0', 32) + local cmd_wrbl = 'hf mf wrbl %d B %s %s' - print(tab) - ---Wriiting block - if (utils.confirm(' At this case are you using a Blank Card?') == true) then + if (utils.confirm(' Are you using a empty card with default key?') == true) then wait() for i = 1, #eml do - core.console('hf mf wrbl ' .. (i - 1) .. ' B ' .. fkey() .. ' ' .. - tostring(eml[i])) + core.console(string.format(cmd_wrbl, (i-1), default_key, eml[i])) end - print(tab) else print(tab) - if (utils.confirm( - ' Do you wishing DELETE ALL DATA and rewrite all keys to ' .. fkey() .. - '?') == true) then + if (utils.confirm(' Delete ALL data and write all keys to 0x'..default_key..' ?') == true) then wait() for i = 1, #eml do if (i % 4 == 0) then - core.console( - 'hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. ' ' .. - fkey() .. '78778800' .. fkey()) + core.console(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk)) else - core.console( - 'hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. ' ' .. - string.rep('0', 32)) + core.console(string.format(cmd_wrbl, (i-1), b_keys[i], empty)) end end else + print(tab) + print('Writing to card') wait() for i = 1, #eml do - core.console('hf mf wrbl ' .. (i - 1) .. ' B ' .. tostring(B[i]) .. - ' ' .. tostring(eml[i])) + core.console(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i])) end end end - finish() + dropfield() + print(tab) + print('Done') end -main(args) ----General thinks for the future: ----Add support another types of dumps: BIN, JSON ----Maybe it will be not only as `hf-writer`, like a universal dump manager. ----Add undependence from the operation system. At the moment code not working in Linux. ----Add more chinesse backdoors RAW commands for UID changing (find RAW for the 4 byte familiar chinese card, from native it soft: http://bit.ly/39VIDsU) ----Hide system messages when you writing a dumps, replace it to some of like [#####----------] 40% +main(args) From 3125812f93c3f5ca0a596b22c241fd7111907957 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sat, 21 Mar 2020 20:08:11 +1100 Subject: [PATCH 181/298] Update cmdlfkeri.c Added clone for FC and CardID --- client/cmdlfkeri.c | 83 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 11 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 982eb8193..2fa8181b3 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -30,13 +30,21 @@ static int CmdHelp(const char *Cmd); static int usage_lf_keri_clone(void) { PrintAndLogEx(NORMAL, "clone a KERI tag to a T55x7 tag."); PrintAndLogEx(NORMAL, "Usage: lf keri clone [h] "); + PrintAndLogEx(NORMAL, "Usage extended: lf keri clone [h] t [f ] i [Q5]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " : Keri Internal ID"); PrintAndLogEx(NORMAL, " : specify write to Q5 (t5555 instead of t55x7)"); + // New format + PrintAndLogEx(NORMAL, " [m|i] : Type. m - MS, i - Internal ID"); + PrintAndLogEx(NORMAL, " : Facility Code"); + PrintAndLogEx(NORMAL, " : Card ID"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf keri clone 112233"); + PrintAndLogEx(NORMAL, " lf keri clone type ms fc 6 id 12345"); + PrintAndLogEx(NORMAL, " lf keri clone t m f 6 i 12345"); + return PM3_SUCCESS; } @@ -98,7 +106,7 @@ static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *I } // Card FC if (CardToFC[CardIdx] < 32) { - if ((*ID & (1 << CardToFC[CardIdx])) > 0) + if ((*FC & (1 << CardToFC[CardIdx])) > 0) *CardID |= (1 << CardIdx); } } @@ -122,7 +130,7 @@ static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *I // Bit 31 was fixed but not in check/parity bits *CardID |= (1 << 31); - PrintAndLogEx(SUCCESS, "Scrambled FC : %d - Card ID : %d to RAW : E0000000%08X",*FC,*ID,*CardID); + PrintAndLogEx(SUCCESS, "Scrambled MS : FC %d - Card ID %d to RAW : E0000000%08X",*FC,*ID,*CardID); } return PM3_SUCCESS; } @@ -192,10 +200,10 @@ static int CmdKeriDemod(const char *Cmd) { /* Scamble: For dev testing only, will/should move to the create keri-ms code when added. - - uint32_t testCard = 0; - CmdKeriMSScramble (Scramble,&fc,&cardid,&testCard); -*/ + */ + // uint32_t testCard = 0; + // CmdKeriMSScramble (Scramble,&fc,&cardid,&testCard); + // End Descramble test @@ -216,6 +224,11 @@ static int CmdKeriRead(const char *Cmd) { static int CmdKeriClone(const char *Cmd) { + uint8_t cmdptr = 0; + char format = 'r'; // default to raw + uint32_t fc = 0; + uint32_t cid = 0; + uint32_t cardid = 0; uint32_t internalid = 0; uint32_t blocks[3] = { T55x7_TESTMODE_DISABLED | @@ -233,8 +246,45 @@ static int CmdKeriClone(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_clone(); - internalid = param_get32ex(Cmd, 0, 0, 10); + // Assume old format for backwards compatibility and only parameter is the internal id + cid = param_get32ex(Cmd, 0, 0, 10); + // find other options + while (param_getchar(Cmd, cmdptr) != 0x00) { // && !errors) { + PrintAndLogEx (SUCCESS,"[%c]",param_getchar(Cmd, cmdptr)); + switch (tolower(param_getchar(Cmd, cmdptr))) { + case 'h': // help + return usage_lf_keri_clone(); + case 't': // format type + format = tolower(param_getchar(Cmd,cmdptr+1)); + cmdptr += 2; + break; + case 'f': // fc + fc = param_get32ex(Cmd,cmdptr+1,0,10); + cmdptr += 2; + break; + case 'c': // cardid + cid = param_get32ex(Cmd,cmdptr+1,0,10); + cmdptr += 2; + break; + case 'q': // q5 + blocks[0] = + T5555_MODULATION_PSK1 | + T5555_SET_BITRATE(128) | + T5555_PSK_RF_2 | + 2 << T5555_MAXBLOCK_SHIFT; + cmdptr++; + break; + default: + // Skip unknown + cmdptr++; + } + } + + // this is managed in above code + // internalid = param_get32ex(Cmd, 0, 0, 10); +/* + // Q5 is caught in the while loop //Q5 if (tolower(param_getchar(Cmd, 1)) == 'q') { blocks[0] = @@ -243,10 +293,21 @@ static int CmdKeriClone(const char *Cmd) { T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT; } - - // MSB is ONE - internalid |= 0x80000000; - +*/ + // Setup card data + switch (format) { + case 'i' : // Internal ID + // MSB is ONE + internalid = cid | 0x80000000; + break; + case 'm' : // MS + cardid = 0; + CmdKeriMSScramble (Scramble,&fc,&cid,&cardid); + internalid = 0xE000000000000000 + cardid; + break; + } + + // Prepare and write to card // 3 LSB is ONE uint64_t data = ((uint64_t)internalid << 3) + 7; PrintAndLogEx(INFO, "Preparing to clone KERI to T55x7 with Internal Id: %" PRIx32, internalid); From 6440f4c5b0d6797607b14b322e5ac3f4f56dc817 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sat, 21 Mar 2020 21:36:37 +1100 Subject: [PATCH 182/298] Update cmdlfkeri.c --- client/cmdlfkeri.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 2fa8181b3..9f292c091 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -30,7 +30,7 @@ static int CmdHelp(const char *Cmd); static int usage_lf_keri_clone(void) { PrintAndLogEx(NORMAL, "clone a KERI tag to a T55x7 tag."); PrintAndLogEx(NORMAL, "Usage: lf keri clone [h] "); - PrintAndLogEx(NORMAL, "Usage extended: lf keri clone [h] t [f ] i [Q5]"); + PrintAndLogEx(NORMAL, "Usage extended: lf keri clone [h] t [f ] c [Q5]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " : Keri Internal ID"); @@ -225,7 +225,7 @@ static int CmdKeriRead(const char *Cmd) { static int CmdKeriClone(const char *Cmd) { uint8_t cmdptr = 0; - char format = 'r'; // default to raw + char format = 'i'; // default to raw uint32_t fc = 0; uint32_t cid = 0; uint32_t cardid = 0; @@ -294,7 +294,7 @@ static int CmdKeriClone(const char *Cmd) { 2 << T5555_MAXBLOCK_SHIFT; } */ - // Setup card data + // Setup card data/build internal id switch (format) { case 'i' : // Internal ID // MSB is ONE From 4175297f57af0d44b6a067276c52ac3990814486 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sat, 21 Mar 2020 21:42:00 +1100 Subject: [PATCH 183/298] Update cmdlfkeri.c help update --- client/cmdlfkeri.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 9f292c091..a5d66caff 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -32,18 +32,18 @@ static int usage_lf_keri_clone(void) { PrintAndLogEx(NORMAL, "Usage: lf keri clone [h] "); PrintAndLogEx(NORMAL, "Usage extended: lf keri clone [h] t [f ] c [Q5]"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " : Keri Internal ID"); - PrintAndLogEx(NORMAL, " : specify write to Q5 (t5555 instead of t55x7)"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " : Keri Internal ID"); + PrintAndLogEx(NORMAL, " : specify write to Q5 (t5555 instead of t55x7)"); // New format - PrintAndLogEx(NORMAL, " [m|i] : Type. m - MS, i - Internal ID"); - PrintAndLogEx(NORMAL, " : Facility Code"); - PrintAndLogEx(NORMAL, " : Card ID"); + PrintAndLogEx(NORMAL, " [m|i] : Type. m - MS, i - Internal ID"); + PrintAndLogEx(NORMAL, " : Facility Code"); + PrintAndLogEx(NORMAL, " : Card ID"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf keri clone 112233"); - PrintAndLogEx(NORMAL, " lf keri clone type ms fc 6 id 12345"); - PrintAndLogEx(NORMAL, " lf keri clone t m f 6 i 12345"); + PrintAndLogEx(NORMAL, " lf keri clone type ms fc 6 cardid 12345"); + PrintAndLogEx(NORMAL, " lf keri clone t m f 6 c 12345"); return PM3_SUCCESS; } From e80eb37b5e6e2080525cd8bf51a1e404072a1b6d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Mar 2020 12:34:58 +0100 Subject: [PATCH 184/298] more rework --- client/luascripts/hf-writer.lua | 88 +++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/client/luascripts/hf-writer.lua b/client/luascripts/hf-writer.lua index 010a0eb30..167c2e896 100644 --- a/client/luascripts/hf-writer.lua +++ b/client/luascripts/hf-writer.lua @@ -2,7 +2,7 @@ local utils = require('utils') local getopt = require('getopt') local read14a = require('read14a') -[[-- +--[[ ---Suggestions of improvement: --- Add support another types of dumps: BIN, JSON --- Maybe it will be not only as `mfc_gen3_writer`, like a universal dump manager. @@ -14,6 +14,7 @@ local read14a = require('read14a') -- doesn't take consideration filepaths for dump files. -- doesn't allow A keys for authenticating when writing -- doesn't verify that card is magic gen3. +-- doesn't take several versions of same dump ( -1, -2, -3 ) styles. --]] copyright = '' @@ -42,6 +43,34 @@ usage = [[ Select your *.eml dump from list to write to the card. ]] +-- Some globals +local DEBUG = false -- the debug flag + +------------------------------- +-- Some utilities +------------------------------- + +--- +-- A debug printout-function +local function dbg(args) + if not DEBUG then return end + if type(args) == 'table' then + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print('###', args) + end +end +--- +-- This is only meant to be used when errors occur +local function oops(err) + print('ERROR:', err) + core.clearCommandBuffer() + return nil, err +end --- -- Usage help local function help() @@ -49,6 +78,7 @@ local function help() print(author) print(version) print(desc) + print('Example usage') print(example) print(usage) end @@ -87,28 +117,31 @@ local function main(args) wait() print(tab) - local length = 23 - local e = 14 + local length = 25 + local e = 16 -- Detect 7 byte card if string.len(GetUID()) == 14 then - length = 29 - e = 20 + length = 31 + e = 22 end + dropfield() ---List all EML files in /client - for _ in io.popen([[dir ".\" /b]]):lines() do -- for UNIX: ls - - if string.find(_, '%.eml$') then - - if string.len(_) == length then -- The length of eml file - num_dumps = num_dumps + 1 - files[num_dumps] = string.sub(tostring(_), 7, e) -- Cut UID from eml file - print(' '..num_dumps..' | '..files[a]) - end - + local dumpEML = "find '.' -iname '*dump.eml' -type f" + local p = assert(io.popen(dumpEML)) + for _ in p:lines() do + + -- The length of eml file + if string.len(_) == length then + num_dumps = num_dumps + 1 + -- cut UID from eml file + files[num_dumps] = string.sub(_, 9, e) + print(' '..num_dumps..' | '..files[num_dumps]) end end + if num_dumps == 0 then return oops("Didn't find any dump files") end + print(tab) print(' Your card has UID '..GetUID()) print('') @@ -117,10 +150,10 @@ local function main(args) io.write(' --> ') local no = tonumber(io.read()) - local dump = io.open('./hf-mf-' .. files[no] .. '-data.eml', 'r'); + local dump = assert(io.open('./hf-mf-' .. files[no] .. '-dump.eml', 'r')) print(tab) - print(' You have been selected ' .. no .. ' card dump, with UID : '..files[no]) + print(' You have been selected card dump ' .. no .. ', with UID : '..files[no]) --- Load eml file for _ in dump:lines() do table.insert(eml, _); end @@ -128,22 +161,23 @@ local function main(args) --- Extract B key from EML file local b = 0 for i = 1, #eml do - print('line is type: ', type(eml[i]) ) - if (i % 4 == 0) then repeat b = b + 1 -- Cut key from block - b_keys[b] = string.sub(tostring(eml[i]), (string.len(eml[i]) - 11), string.len(eml[i])) + b_keys[b] = string.sub(eml[i], (#eml[i] - 11), #eml[i]) until b % 4 == 0 end end print(tab) + dbg(b_keys) + dbg(eml) --- Change UID on certain version of magic Gen3 card. if (utils.confirm(' Change UID ?') == true) then wait() - core.console('hf 14a raw -s -c -t 2000 90f0cccc10'..tostring(eml[1])) + --core.console('hf 14a raw -s -c -t 2000 90f0cccc10'..tostring(eml[1])) + print('hf 14a raw -s -c -t 2000 90f0cccc10'..tostring(eml[1])) print(tab) print(' The new card UID : ' .. GetUID()) end @@ -165,7 +199,8 @@ local function main(args) if (utils.confirm(' Are you using a empty card with default key?') == true) then wait() for i = 1, #eml do - core.console(string.format(cmd_wrbl, (i-1), default_key, eml[i])) + --core.console(string.format(cmd_wrbl, (i-1), default_key, eml[i])) + print(string.format(cmd_wrbl, (i-1), default_key, eml[i])) end else print(tab) @@ -173,9 +208,11 @@ local function main(args) wait() for i = 1, #eml do if (i % 4 == 0) then - core.console(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk)) + --core.console(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk)) + print(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk)) else - core.console(string.format(cmd_wrbl, (i-1), b_keys[i], empty)) + --core.console(string.format(cmd_wrbl, (i-1), b_keys[i], empty)) + print(string.format(cmd_wrbl, (i-1), b_keys[i], empty)) end end else @@ -183,7 +220,8 @@ local function main(args) print('Writing to card') wait() for i = 1, #eml do - core.console(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i])) + --core.console(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i])) + print(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i])) end end end From 80f79b10668b847b33ea108f49babc5b78573878 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Mar 2020 12:37:40 +0100 Subject: [PATCH 185/298] swap to live execution --- client/luascripts/hf-writer.lua | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/client/luascripts/hf-writer.lua b/client/luascripts/hf-writer.lua index 167c2e896..76e7708e4 100644 --- a/client/luascripts/hf-writer.lua +++ b/client/luascripts/hf-writer.lua @@ -103,8 +103,9 @@ end local function main(args) -- Arguments for the script - for o, a in getopt.getopt(args, 'h') do + for o, a in getopt.getopt(args, 'hd') do if o == 'h' then return help() end + if o == 'd' then DEBUG = true end end local files = {} -- Array for eml files @@ -199,8 +200,7 @@ local function main(args) if (utils.confirm(' Are you using a empty card with default key?') == true) then wait() for i = 1, #eml do - --core.console(string.format(cmd_wrbl, (i-1), default_key, eml[i])) - print(string.format(cmd_wrbl, (i-1), default_key, eml[i])) + core.console(string.format(cmd_wrbl, (i-1), default_key, eml[i])) end else print(tab) @@ -208,11 +208,9 @@ local function main(args) wait() for i = 1, #eml do if (i % 4 == 0) then - --core.console(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk)) - print(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk)) + core.console(string.format(cmd_wrbl, (i-1), b_keys[i], default_key_blk)) else - --core.console(string.format(cmd_wrbl, (i-1), b_keys[i], empty)) - print(string.format(cmd_wrbl, (i-1), b_keys[i], empty)) + core.console(string.format(cmd_wrbl, (i-1), b_keys[i], empty)) end end else @@ -220,8 +218,7 @@ local function main(args) print('Writing to card') wait() for i = 1, #eml do - --core.console(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i])) - print(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i])) + core.console(string.format(cmd_wrbl, (i-1), b_keys[i], eml[i])) end end end From 9a2fc52a9284980b852187221a45d2bc0cc6ee00 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Mar 2020 12:40:16 +0100 Subject: [PATCH 186/298] closing files are use... --- client/luascripts/hf-writer.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/luascripts/hf-writer.lua b/client/luascripts/hf-writer.lua index 76e7708e4..c1812902d 100644 --- a/client/luascripts/hf-writer.lua +++ b/client/luascripts/hf-writer.lua @@ -140,6 +140,7 @@ local function main(args) print(' '..num_dumps..' | '..files[num_dumps]) end end + p.close() if num_dumps == 0 then return oops("Didn't find any dump files") end @@ -151,13 +152,13 @@ local function main(args) io.write(' --> ') local no = tonumber(io.read()) - local dump = assert(io.open('./hf-mf-' .. files[no] .. '-dump.eml', 'r')) - print(tab) print(' You have been selected card dump ' .. no .. ', with UID : '..files[no]) --- Load eml file - for _ in dump:lines() do table.insert(eml, _); end + local dumpfile = assert(io.open('./hf-mf-' .. files[no] .. '-dump.eml', 'r')) + for _ in dumpfile:lines() do table.insert(eml, _); end + dumpfile.close() --- Extract B key from EML file local b = 0 From 097595cdefdef75b0e266cda45360aaa9ba3aceb Mon Sep 17 00:00:00 2001 From: Artem Gnatyuk Date: Sat, 21 Mar 2020 21:27:57 +0700 Subject: [PATCH 187/298] [RDV4] Readed IDs store to file in spiffs --- armsrc/Standalone/lf_em4100rwc.c | 75 +++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/armsrc/Standalone/lf_em4100rwc.c b/armsrc/Standalone/lf_em4100rwc.c index a336112ba..08ab76cc1 100644 --- a/armsrc/Standalone/lf_em4100rwc.c +++ b/armsrc/Standalone/lf_em4100rwc.c @@ -5,12 +5,16 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// LF rwc - This mode can simulate tag ID from selected slot and read tag ID -// to selected slot and to flash (only RDV4). Also you can set -// predefined IDs in any slot. +// LF rwc - This mode can simulate ID from selected slot, read ID to +// selected slot, write from selected slot to T5555 tag and store +// readed ID to flash (only RDV4). Also you can set predefined IDs +// in any slot. // To recall stored ID from flash execute: -// mem dump o offset l 5 p -// where offset = 5 * selected slot +// mem spifss dump o emdump p +// or: +// mem spifss dump o emdump f emdump +// then from shell: +// hexdump emdump -e '5/1 "%02X" /0 "\n"' //----------------------------------------------------------------------------- #include "standalone.h" #include "proxmark3_arm.h" @@ -22,6 +26,7 @@ #include "ticks.h" #include "string.h" #include "BigBuf.h" +#include "spiffs.h" #ifdef WITH_FLASH #include "flashmem.h" @@ -33,13 +38,13 @@ // low & high - array for storage IDs. Its length must be equal. // Predefined IDs must be stored in low[]. // In high[] must be nulls -uint64_t low[] = {0x565AF781C7,0x540053E4E2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +uint64_t low[] = {0x565AF781C7,0x540053E4E2,0x1234567890,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint32_t high[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t *bba,slots_count; int buflen; void ModInfo(void) { - DbpString(" LF EM4100 read/write/clone standalone mode"); + DbpString(" LF EM4100 simulate standalone V2"); } uint64_t ReversQuads(uint64_t bits){ @@ -99,11 +104,16 @@ void FlashLEDs(uint32_t speed, uint8_t times) { #ifdef WITH_FLASH void SaveIDtoFlash (int addr, uint64_t id) { - uint8_t b, *ptr; + uint8_t bt[5]; + char *filename = "emdump"; + rdv40_spiffs_mount(); for (int i = 0; i < 5; i++) { - b = (uint8_t) (id >> 8 * i & 0xff); - ptr = &b; - Flash_WriteData(addr * 5 + 4 - i,ptr,1); + bt[4-i] = (uint8_t) (id >> 8 * i & 0xff); + } + if (exists_in_spiffs(filename) == false){ + rdv40_spiffs_write(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL); + } else { + rdv40_spiffs_append(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL); } } #endif @@ -112,9 +122,10 @@ void RunMod() { StandAloneMode(); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); int selected = 0; - //state 0 - select slot, + //state 0 - select slot // 1 - read tag to selected slot, // 2 - simulate tag from selected slot + // 3 - write to T5555 tag uint8_t state = 0; slots_count = sizeof(low)/sizeof(low[0]); bba = BigBuf_get_addr(); @@ -130,7 +141,7 @@ void RunMod() { if (button_pressed == 1) { // Long press - switch to simulate mode SpinUp(100); - SpinOff(100); + LED_Slot(selected); state = 2; } else if (button_pressed < 0) { // Click - switch to next slot @@ -139,13 +150,21 @@ void RunMod() { } break; case 1: - // Read mode. Click - exit to select mode - CmdEM410xdemod(1, &high[selected], &low[selected], 0); - FlashLEDs(100,5); - #ifdef WITH_FLASH - SaveIDtoFlash(selected, low[selected]); - #endif - state = 0; + // Read mode. + if (button_pressed > 0) { + // Long press - switch to read mode + SpinUp(100); + LED_Slot(selected); + state = 3; + } else if (button_pressed < 0) { + // Click - exit to select mode + CmdEM410xdemod(1, &high[selected], &low[selected], 0); + FlashLEDs(100,5); + #ifdef WITH_FLASH + SaveIDtoFlash(selected, low[selected]); + #endif + state = 0; + } break; case 2: // Simulate mode @@ -155,7 +174,7 @@ void RunMod() { LED_Slot(selected); state = 1; } else if (button_pressed < 0) { - // Click - start simulating. Click again to exit from simelate mode + // Click - start simulating. Click again to exit from simulate mode LED_Slot(selected); ConstructEM410xEmulBuf(ReversQuads(low[selected])); FlashLEDs(100,5); @@ -164,6 +183,20 @@ void RunMod() { state = 0; // Switch to select mode } break; + case 3: + // Write tag mode + if (button_pressed > 0) { + // Long press - switch to select mode + SpinDown(100); + LED_Slot(selected); + state = 0; + } else if (button_pressed < 0) { + // Click - write ID to tag + WriteEM410x(0, (uint32_t) (low[selected] >> 32), (uint32_t) (low[selected] & 0xffffffff)); + LED_Slot(selected); + state = 0; // Switch to select mode + } + break; } } } From c36d86bc010a50537d6e0a6b265ea1ee09c07c43 Mon Sep 17 00:00:00 2001 From: Artem Gnatyuk Date: Sat, 21 Mar 2020 21:39:30 +0700 Subject: [PATCH 188/298] Make style --- armsrc/Standalone/lf_em4100emul.c | 76 +++++----- armsrc/Standalone/lf_em4100rwc.c | 236 +++++++++++++++--------------- 2 files changed, 156 insertions(+), 156 deletions(-) diff --git a/armsrc/Standalone/lf_em4100emul.c b/armsrc/Standalone/lf_em4100emul.c index 907445912..f3939f923 100644 --- a/armsrc/Standalone/lf_em4100emul.c +++ b/armsrc/Standalone/lf_em4100emul.c @@ -23,36 +23,36 @@ #define CLOCK 64 //for 125kHz // low & high - array for storage IDs. Its length must be equal. -// Predefined IDs must be stored in low[]. +// Predefined IDs must be stored in low[]. // In high[] must be nulls -uint64_t low[] = {0x565A1140BE,0x365A398149,0x5555555555,0xFFFFFFFFFF}; -uint32_t high[] = {0,0,0,0}; -uint8_t *bba,slots_count; +uint64_t low[] = {0x565A1140BE, 0x365A398149, 0x5555555555, 0xFFFFFFFFFF}; +uint32_t high[] = {0, 0, 0, 0}; +uint8_t *bba, slots_count; int buflen; void ModInfo(void) { DbpString(" LF EM4100 simulator standalone mode"); } -uint64_t ReversQuads(uint64_t bits){ - uint64_t result = 0; - for (int i = 0; i < 16; i++){ - result += ((bits >> (60 - 4 *i)) & 0xf) << (4 * i); - } - return result >> 24; +uint64_t ReversQuads(uint64_t bits) { + uint64_t result = 0; + for (int i = 0; i < 16; i++) { + result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i); + } + return result >> 24; } void FillBuff(uint8_t bit) { - memset (bba + buflen, bit, CLOCK / 2); - buflen += (CLOCK / 2); - memset (bba + buflen, bit^1,CLOCK / 2); - buflen += (CLOCK / 2); + memset(bba + buflen, bit, CLOCK / 2); + buflen += (CLOCK / 2); + memset(bba + buflen, bit ^ 1, CLOCK / 2); + buflen += (CLOCK / 2); } void ConstructEM410xEmulBuf(uint64_t id) { - + int i, j, binary[4], parity[4]; - buflen = 0; + buflen = 0; for (i = 0; i < 9; i++) FillBuff(1); parity[0] = parity[1] = parity[2] = parity[3] = 0; @@ -60,39 +60,39 @@ void ConstructEM410xEmulBuf(uint64_t id) { for (j = 3; j >= 0; j--, id /= 2) binary[j] = id % 2; for (j = 0; j < 4; j++) - FillBuff(binary[j]); + FillBuff(binary[j]); FillBuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); for (j = 0; j < 4; j++) - parity[j] ^= binary[j]; + parity[j] ^= binary[j]; } - for (j = 0; j < 4; j++) - FillBuff(parity[j]); + for (j = 0; j < 4; j++) + FillBuff(parity[j]); FillBuff(0); } void LED_Slot(int i) { - LEDsoff(); - if (slots_count > 4) { - LED(i % MAX_IND, 0); //binary indication for slots_count > 4 - } else { - LED(1 << i,0); //simple indication for slots_count <=4 - } + LEDsoff(); + if (slots_count > 4) { + LED(i % MAX_IND, 0); //binary indication for slots_count > 4 + } else { + LED(1 << i, 0); //simple indication for slots_count <=4 + } } void RunMod() { StandAloneMode(); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - int selected = 0; //selected slot after start - slots_count = sizeof(low)/sizeof(low[0]); - bba = BigBuf_get_addr(); - for (;;) { - WDT_HIT(); + int selected = 0; //selected slot after start + slots_count = sizeof(low) / sizeof(low[0]); + bba = BigBuf_get_addr(); + for (;;) { + WDT_HIT(); if (data_available()) break; - SpinDelay(100); - SpinUp(100); - LED_Slot(selected); - ConstructEM410xEmulBuf(ReversQuads(low[selected])); - SimulateTagLowFrequency(buflen, 0, true); - selected = (selected + 1) % slots_count; - } + SpinDelay(100); + SpinUp(100); + LED_Slot(selected); + ConstructEM410xEmulBuf(ReversQuads(low[selected])); + SimulateTagLowFrequency(buflen, 0, true); + selected = (selected + 1) % slots_count; + } } diff --git a/armsrc/Standalone/lf_em4100rwc.c b/armsrc/Standalone/lf_em4100rwc.c index 08ab76cc1..b7394db69 100644 --- a/armsrc/Standalone/lf_em4100rwc.c +++ b/armsrc/Standalone/lf_em4100rwc.c @@ -5,10 +5,10 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// LF rwc - This mode can simulate ID from selected slot, read ID to -// selected slot, write from selected slot to T5555 tag and store +// LF rwc - This mode can simulate ID from selected slot, read ID to +// selected slot, write from selected slot to T5555 tag and store // readed ID to flash (only RDV4). Also you can set predefined IDs -// in any slot. +// in any slot. // To recall stored ID from flash execute: // mem spifss dump o emdump p // or: @@ -36,36 +36,36 @@ #define CLOCK 64 //for 125kHz // low & high - array for storage IDs. Its length must be equal. -// Predefined IDs must be stored in low[]. +// Predefined IDs must be stored in low[]. // In high[] must be nulls -uint64_t low[] = {0x565AF781C7,0x540053E4E2,0x1234567890,0,0,0,0,0,0,0,0,0,0,0,0,0}; -uint32_t high[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -uint8_t *bba,slots_count; +uint64_t low[] = {0x565AF781C7, 0x540053E4E2, 0x1234567890, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +uint32_t high[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +uint8_t *bba, slots_count; int buflen; void ModInfo(void) { DbpString(" LF EM4100 simulate standalone V2"); } -uint64_t ReversQuads(uint64_t bits){ - uint64_t result = 0; - for (int i = 0; i < 16; i++){ - result += ((bits >> (60 - 4 *i)) & 0xf) << (4 * i); - } - return result >> 24; +uint64_t ReversQuads(uint64_t bits) { + uint64_t result = 0; + for (int i = 0; i < 16; i++) { + result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i); + } + return result >> 24; } void FillBuff(uint8_t bit) { - memset (bba + buflen, bit, CLOCK / 2); - buflen += (CLOCK / 2); - memset (bba + buflen, bit^1,CLOCK / 2); - buflen += (CLOCK / 2); + memset(bba + buflen, bit, CLOCK / 2); + buflen += (CLOCK / 2); + memset(bba + buflen, bit ^ 1, CLOCK / 2); + buflen += (CLOCK / 2); } void ConstructEM410xEmulBuf(uint64_t id) { - + int i, j, binary[4], parity[4]; - buflen = 0; + buflen = 0; for (i = 0; i < 9; i++) FillBuff(1); parity[0] = parity[1] = parity[2] = parity[3] = 0; @@ -73,23 +73,23 @@ void ConstructEM410xEmulBuf(uint64_t id) { for (j = 3; j >= 0; j--, id /= 2) binary[j] = id % 2; for (j = 0; j < 4; j++) - FillBuff(binary[j]); + FillBuff(binary[j]); FillBuff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); for (j = 0; j < 4; j++) - parity[j] ^= binary[j]; + parity[j] ^= binary[j]; } - for (j = 0; j < 4; j++) - FillBuff(parity[j]); + for (j = 0; j < 4; j++) + FillBuff(parity[j]); FillBuff(0); } void LED_Slot(int i) { - LEDsoff(); - if (slots_count > 4) { - LED(i % MAX_IND, 0); //binary indication, usefully for slots_count > 4 - } else { - LED(1 << i,0); //simple indication for slots_count <=4 - } + LEDsoff(); + if (slots_count > 4) { + LED(i % MAX_IND, 0); //binary indication, usefully for slots_count > 4 + } else { + LED(1 << i, 0); //simple indication for slots_count <=4 + } } void FlashLEDs(uint32_t speed, uint8_t times) { @@ -103,100 +103,100 @@ void FlashLEDs(uint32_t speed, uint8_t times) { } #ifdef WITH_FLASH -void SaveIDtoFlash (int addr, uint64_t id) { - uint8_t bt[5]; - char *filename = "emdump"; - rdv40_spiffs_mount(); - for (int i = 0; i < 5; i++) { - bt[4-i] = (uint8_t) (id >> 8 * i & 0xff); - } - if (exists_in_spiffs(filename) == false){ - rdv40_spiffs_write(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL); - } else { - rdv40_spiffs_append(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL); - } +void SaveIDtoFlash(int addr, uint64_t id) { + uint8_t bt[5]; + char *filename = "emdump"; + rdv40_spiffs_mount(); + for (int i = 0; i < 5; i++) { + bt[4 - i] = (uint8_t)(id >> 8 * i & 0xff); + } + if (exists_in_spiffs(filename) == false) { + rdv40_spiffs_write(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL); + } else { + rdv40_spiffs_append(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL); + } } #endif void RunMod() { StandAloneMode(); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - int selected = 0; - //state 0 - select slot - // 1 - read tag to selected slot, - // 2 - simulate tag from selected slot - // 3 - write to T5555 tag - uint8_t state = 0; - slots_count = sizeof(low)/sizeof(low[0]); - bba = BigBuf_get_addr(); - LED_Slot(selected); - for (;;) { - WDT_HIT(); + int selected = 0; + //state 0 - select slot + // 1 - read tag to selected slot, + // 2 - simulate tag from selected slot + // 3 - write to T5555 tag + uint8_t state = 0; + slots_count = sizeof(low) / sizeof(low[0]); + bba = BigBuf_get_addr(); + LED_Slot(selected); + for (;;) { + WDT_HIT(); if (data_available()) break; - int button_pressed = BUTTON_HELD(1000); - SpinDelay(300); - switch (state){ - case 0: - // Select mode - if (button_pressed == 1) { - // Long press - switch to simulate mode - SpinUp(100); - LED_Slot(selected); - state = 2; - } else if (button_pressed < 0) { - // Click - switch to next slot - selected = (selected + 1) % slots_count; - LED_Slot(selected); - } - break; - case 1: - // Read mode. - if (button_pressed > 0) { - // Long press - switch to read mode - SpinUp(100); - LED_Slot(selected); - state = 3; - } else if (button_pressed < 0) { - // Click - exit to select mode - CmdEM410xdemod(1, &high[selected], &low[selected], 0); - FlashLEDs(100,5); - #ifdef WITH_FLASH - SaveIDtoFlash(selected, low[selected]); - #endif - state = 0; - } - break; - case 2: - // Simulate mode - if (button_pressed > 0) { - // Long press - switch to read mode - SpinDown(100); - LED_Slot(selected); - state = 1; - } else if (button_pressed < 0) { - // Click - start simulating. Click again to exit from simulate mode - LED_Slot(selected); - ConstructEM410xEmulBuf(ReversQuads(low[selected])); - FlashLEDs(100,5); - SimulateTagLowFrequency(buflen, 0, 1); - LED_Slot(selected); - state = 0; // Switch to select mode - } - break; - case 3: - // Write tag mode - if (button_pressed > 0) { - // Long press - switch to select mode - SpinDown(100); - LED_Slot(selected); - state = 0; - } else if (button_pressed < 0) { - // Click - write ID to tag - WriteEM410x(0, (uint32_t) (low[selected] >> 32), (uint32_t) (low[selected] & 0xffffffff)); - LED_Slot(selected); - state = 0; // Switch to select mode - } - break; - } - } + int button_pressed = BUTTON_HELD(1000); + SpinDelay(300); + switch (state) { + case 0: + // Select mode + if (button_pressed == 1) { + // Long press - switch to simulate mode + SpinUp(100); + LED_Slot(selected); + state = 2; + } else if (button_pressed < 0) { + // Click - switch to next slot + selected = (selected + 1) % slots_count; + LED_Slot(selected); + } + break; + case 1: + // Read mode. + if (button_pressed > 0) { + // Long press - switch to read mode + SpinUp(100); + LED_Slot(selected); + state = 3; + } else if (button_pressed < 0) { + // Click - exit to select mode + CmdEM410xdemod(1, &high[selected], &low[selected], 0); + FlashLEDs(100, 5); +#ifdef WITH_FLASH + SaveIDtoFlash(selected, low[selected]); +#endif + state = 0; + } + break; + case 2: + // Simulate mode + if (button_pressed > 0) { + // Long press - switch to read mode + SpinDown(100); + LED_Slot(selected); + state = 1; + } else if (button_pressed < 0) { + // Click - start simulating. Click again to exit from simulate mode + LED_Slot(selected); + ConstructEM410xEmulBuf(ReversQuads(low[selected])); + FlashLEDs(100, 5); + SimulateTagLowFrequency(buflen, 0, 1); + LED_Slot(selected); + state = 0; // Switch to select mode + } + break; + case 3: + // Write tag mode + if (button_pressed > 0) { + // Long press - switch to select mode + SpinDown(100); + LED_Slot(selected); + state = 0; + } else if (button_pressed < 0) { + // Click - write ID to tag + WriteEM410x(0, (uint32_t)(low[selected] >> 32), (uint32_t)(low[selected] & 0xffffffff)); + LED_Slot(selected); + state = 0; // Switch to select mode + } + break; + } + } } From 0abba96eb6605c90682eb4290a2aaa3617e82ebc Mon Sep 17 00:00:00 2001 From: Artem Gnatyuk Date: Sun, 22 Mar 2020 00:03:16 +0700 Subject: [PATCH 189/298] Add my modes after merging. --- armsrc/Standalone/Makefile.hal | 13 +++++++++---- armsrc/Standalone/Makefile.inc | 8 ++++++++ armsrc/Standalone/lf_em4100rwc.c | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index fd52817db..5c2352aaf 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -35,19 +35,24 @@ define KNOWN_STANDALONE_DEFINITIONS | HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth | | (RDV4 only) | storing in flashmem - Bogito | +----------------------------------------------------------+ +| HF_14ASNIFF | 14a sniff to flashmem | +| (RDV4 only) | | ++----------------------------------------------------------+ +| LF_ICEHID | LF HID collector to flashmem | +| (RDV4 only) | | ++----------------------------------------------------------+ | LF_EM4100EMUL | Simulate predefined em4100 tags only | | | | +----------------------------------------------------------+ | LF_EM4100RWC | Read/simulate em4100 tags & clone it | | | to T555x tags | +----------------------------------------------------------+ - endef -STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_EM4100EMUL LF_EM4100RWC -STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG +STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_ICEHID LF_EM4100EMUL LF_EM4100RWC +STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG HF_14ASNIFF STANDALONE_MODES_REQ_SMARTCARD := -STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG +STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG HF_14ASNIFF LF_ICEHID ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE) ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),) diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index 686cc66f0..e5a3304a8 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -33,6 +33,14 @@ endif ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS))) SRC_STANDALONE = hf_bog.c endif +# WITH_STANDALONE_HF_14ASNIFF +ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS))) + SRC_STANDALONE = hf_14asniff.c +endif +# WITH_STANDALONE_LF_ICEHID +ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS))) + SRC_STANDALONE = lf_icehid.c +endif # WITH_STANDALONE_LF_EM4100EMUL ifneq (,$(findstring WITH_STANDALONE_LF_EM4100EMUL,$(APP_CFLAGS))) SRC_STANDALONE = lf_em4100emul.c diff --git a/armsrc/Standalone/lf_em4100rwc.c b/armsrc/Standalone/lf_em4100rwc.c index b7394db69..a2414a6fa 100644 --- a/armsrc/Standalone/lf_em4100rwc.c +++ b/armsrc/Standalone/lf_em4100rwc.c @@ -44,7 +44,7 @@ uint8_t *bba, slots_count; int buflen; void ModInfo(void) { - DbpString(" LF EM4100 simulate standalone V2"); + DbpString(" LF EM4100 read/write/clone mode"); } uint64_t ReversQuads(uint64_t bits) { From 7e97062381da5c049f7605055bd617f94e466e55 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Mar 2020 20:18:42 +0100 Subject: [PATCH 190/298] change for bionic only to zero out if set --- client/comms.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/comms.c b/client/comms.c index 7a9086873..a551e59e3 100644 --- a/client/comms.c +++ b/client/comms.c @@ -671,7 +671,13 @@ void CloseProxmark(void) { // Clean up our state sp = NULL; +#ifdef __BIONIC__ + if (communication_thread != 0) { + memset(&communication_thread, 0, sizeof(pthread_t)); + } +#else memset(&communication_thread, 0, sizeof(pthread_t)); +#endif session.pm3_present = false; } From 5ceb83673fd44777456ef7201a96b9dc2504a572 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Mar 2020 20:34:57 +0100 Subject: [PATCH 191/298] save json, added basic support for 14b/15/t555/legic --- client/fileutils.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index f47e32b73..3343ebc05 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -233,6 +233,7 @@ out: int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, size_t datalen) { if (data == NULL) return PM3_EINVARG; + char *fileName = newfilenamemcopy(preferredName, ".json"); if (fileName == NULL) return PM3_EMALLOC; @@ -368,10 +369,34 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s } break; } - case jsf14b: - case jsf15: - case jsfLegic: - case jsfT5555: + case jsf14b: { + JsonSaveStr(root, "FileType", "14b"); + JsonSaveBufAsHexCompact(root, "raw", data, datalen); + break; + } + case jsf15: { + JsonSaveStr(root, "FileType", "15693"); + JsonSaveBufAsHexCompact(root, "raw", data, datalen); + break; + } + case jsfLegic: { + JsonSaveStr(root, "FileType", "legic"); + JsonSaveBufAsHexCompact(root, "raw", data, datalen); + break; + } + case jsfT5555: { + JsonSaveStr(root, "FileType", "t5555"); + uint8_t conf[4] = {0}; + memcpy(conf, data, 4); + JsonSaveBufAsHexCompact(root, "$.Card.ConfigBlock", conf, sizeof(conf)); + + for (size_t i = 0; i < (datalen / 4); i++) { + char path[PATH_MAX_LENGTH] = {0}; + sprintf(path, "$.blocks.%zu", i); + JsonSaveBufAsHexCompact(root, path, data + (i * 4), 4); + } + break; + } case jsfMfPlusKeys: JsonSaveStr(root, "FileType", "mfp"); JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 7); From dd3bd72af461d07963be62b47ca587665be2c425 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Mar 2020 20:38:58 +0100 Subject: [PATCH 192/298] chg: 'hf 15 dump' - add basic json format when saving\nchg: 'hf 15 restore' - match file template to hf-(tyoe)-(uid)-dump.(extension) --- client/cmdhf15.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 9a5665a31..9b0b8dbf1 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -399,7 +399,7 @@ static int usage_15_restore(void) { {"-2", "use slower '1 out of 256' mode"}, {"-o", "set OPTION Flag (needed for TI)"}, {"r ", "numbers of retries on error, default is 3"}, - {"u ", "load hf-15-dump-.bin"}, + {"u ", "load hf-15--dump.bin"}, {"f ", "load "}, {"b ", "block size, default is 4"} }; @@ -1214,8 +1214,9 @@ static int CmdHF15Dump(const char *Cmd) { PrintAndLogEx(NORMAL, "\n"); size_t datalen = blocknum * 4; + saveFile(filename, ".bin", data, datalen); saveFileEML(filename, data, datalen, 4); - saveFile(filename, ".bin", data, datalen); + saveFileJSON(filename, jsf15, data, datalen); return PM3_SUCCESS; } @@ -1603,7 +1604,7 @@ static int CmdHF15Restore(const char *Cmd) { case 'u': param_getstr(Cmd, cmdp + 1, buff, FILE_PATH_SIZE); cmdp++; - snprintf(filename, sizeof(filename), "hf-15-dump-%s-bin", buff); + snprintf(filename, sizeof(filename), "hf-15-%s-dump.bin", buff); break; case 'h': return usage_15_restore(); @@ -1622,6 +1623,7 @@ static int CmdHF15Restore(const char *Cmd) { } if ((f = fopen(filename, "rb")) == NULL) { + PrintAndLogEx(WARNING, "Could not find file %s", filename); return PM3_EFILE; } From 64e027faf70bff8fa5d3e3046a675aa6cd45b44b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Mar 2020 20:58:20 +0100 Subject: [PATCH 193/298] chg: unify dump file template used in this repo. hf-mf-(uid)-dump.(bin/eml/json) is the prefeered style. --- client/cmdhficlass.c | 4 ++-- client/cmdhfmf.c | 18 +++++++++--------- client/cmdlfem4x.c | 2 +- client/cmdlft55xx.c | 4 ++-- client/luascripts/mifare_autopwn.lua | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 827cbcc38..1dccaef5c 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -898,7 +898,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { return PM3_EMALLOC; } strcat(fptr, "hf-iclass-"); - FillFileNameByUID(fptr, hdr->csn, "-data-decrypted", sizeof(hdr->csn)); + FillFileNameByUID(fptr, hdr->csn, "-dump-decrypted", sizeof(hdr->csn)); saveFile(fptr, ".bin", decrypted, decryptedlen); saveFileEML(fptr, decrypted, decryptedlen, 8); @@ -1361,7 +1361,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { if (filename[0] == 0) { //Use the first block (CSN) for filename strcat(filename, "hf-iclass-"); - FillFileNameByUID(filename, tag_data, "-data", 8); + FillFileNameByUID(filename, tag_data, "-dump", 8); } // save the dump to .bin file diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 77278ee9a..6425e10a3 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -300,15 +300,15 @@ static int usage_hf14_restore(void) { PrintAndLogEx(NORMAL, "Usage: hf mf restore [card memory] u k f "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, " u : uid, try to restore from hf-mf--key.bin and hf-mf--data.bin"); + PrintAndLogEx(NORMAL, " u : uid, try to restore from hf-mf--key.bin and hf-mf--dump.bin"); PrintAndLogEx(NORMAL, " k : key filename, specific the full filename of key file"); PrintAndLogEx(NORMAL, " f : data filename, specific the full filename of data file"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf restore -- read the UID from tag first, then restore from hf-mf--key.bin and and hf-mf--data.bin"); - PrintAndLogEx(NORMAL, " hf mf restore 1 u 12345678 -- restore from hf-mf-12345678-key.bin and hf-mf-12345678-data.bin"); - PrintAndLogEx(NORMAL, " hf mf restore 1 u 12345678 k dumpkey.bin -- restore from dumpkey.bin and hf-mf-12345678-data.bin"); - PrintAndLogEx(NORMAL, " hf mf restore 4 -- read the UID from tag with 4K memory first, then restore from hf-mf--key.bin and and hf-mf--data.bin"); + PrintAndLogEx(NORMAL, " hf mf restore -- read the UID from tag first, then restore from hf-mf--key.bin and and hf-mf--dump.bin"); + PrintAndLogEx(NORMAL, " hf mf restore 1 u 12345678 -- restore from hf-mf-12345678-key.bin and hf-mf-12345678-dump.bin"); + PrintAndLogEx(NORMAL, " hf mf restore 1 u 12345678 k dumpkey.bin -- restore from dumpkey.bin and hf-mf-12345678-dump.bin"); + PrintAndLogEx(NORMAL, " hf mf restore 4 -- read the UID from tag with 4K memory first, then restore from hf-mf--key.bin and and hf-mf--dump.bin"); return PM3_SUCCESS; } static int usage_hf14_decryptbytes(void) { @@ -1064,7 +1064,7 @@ static int CmdHF14AMfDump(const char *Cmd) { PrintAndLogEx(SUCCESS, "\nSucceeded in dumping all blocks"); if (strlen(dataFilename) < 1) { - fptr = GenerateFilename("hf-mf-", "-data"); + fptr = GenerateFilename("hf-mf-", "-dump"); if (fptr == NULL) return PM3_ESOFT; @@ -1103,7 +1103,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { if (keyFilename[0] == 0x00) snprintf(keyFilename, FILE_PATH_SIZE, "hf-mf-%s-key.bin", szTemp); if (dataFilename[0] == 0x00) - snprintf(dataFilename, FILE_PATH_SIZE, "hf-mf-%s-data.bin", szTemp); + snprintf(dataFilename, FILE_PATH_SIZE, "hf-mf-%s-dump.bin", szTemp); cmdp += 2; break; case 'k': @@ -1161,7 +1161,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { fclose(fkeys); if (dataFilename[0] == 0x00) { - fptr = GenerateFilename("hf-mf-", "-data.bin"); + fptr = GenerateFilename("hf-mf-", "-dump.bin"); if (fptr == NULL) return 1; @@ -2507,7 +2507,7 @@ all_found: return PM3_ETIMEOUT; } - fnameptr = GenerateFilename("hf-mf-", "-data"); + fnameptr = GenerateFilename("hf-mf-", "-dump"); if (fnameptr == NULL) { free(dump); free(e_sector); diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index e759a4cf3..841f26652 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -1349,7 +1349,7 @@ static int CmdEM4x05Dump(const char *Cmd) { // saveFileEML will add .eml extension to filename // saveFile (binary) passes in the .bin extension. if (strcmp(preferredName, "") == 0) // Set default filename, if not set by user - sprintf(preferredName, "lf-4x05-%08X-data", BSWAP_32(data[1])); + sprintf(preferredName, "lf-4x05-%08X-dump", BSWAP_32(data[1])); saveFileEML(preferredName, (uint8_t *)data, 16 * sizeof(uint32_t), sizeof(uint32_t)); saveFile(preferredName, ".bin", data, sizeof(data)); diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index c88b8a051..fafb5d2da 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -202,7 +202,7 @@ static int usage_t55xx_restore() { PrintAndLogEx(NORMAL, _YELLOW_(" Assumes lf t55 detect has been run first!")); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx restore f lf-t55xx-00148040-data.bin"); + PrintAndLogEx(NORMAL, " lf t55xx restore f lf-t55xx-00148040-dump.bin"); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -2315,7 +2315,7 @@ static int CmdT55xxDump(const char *Cmd) { else break; } - strcat(preferredName, "-data"); + strcat(preferredName, "-dump"); } // Swap endian so the files match the txt display diff --git a/client/luascripts/mifare_autopwn.lua b/client/luascripts/mifare_autopwn.lua index 624cea419..bc7582760 100644 --- a/client/luascripts/mifare_autopwn.lua +++ b/client/luascripts/mifare_autopwn.lua @@ -115,7 +115,7 @@ local function dump_tag(uid, numsectors) if utils.confirm('Do you wish to create a memory dump of tag?') then - local dumpfile = 'hf-mf-'..uid..'-data' + local dumpfile = 'hf-mf-'..uid..'-dump' local dmp = ('hf mf dump %s f %s'):format(typ, dumpfile) core.console(dmp) From fc1c133c46aefc65dae10eb4fe81b39cd847c610 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Mar 2020 23:13:41 +0100 Subject: [PATCH 194/298] fix: script hf_bruteforce - ensure zeropadding --- client/luascripts/hf_bruteforce.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/luascripts/hf_bruteforce.lua b/client/luascripts/hf_bruteforce.lua index ff8ba6764..485d72809 100644 --- a/client/luascripts/hf_bruteforce.lua +++ b/client/luascripts/hf_bruteforce.lua @@ -96,10 +96,10 @@ local function main(args) local command = '' if mftype == 'mfc' then - command = 'hf 14a sim t 1 u %14X' + command = 'hf 14a sim t 1 u %014x' msg('Bruteforcing Mifare Classic card numbers') elseif mftype == 'mfu' then - command = 'hf 14a sim t 2 u %14X' + command = 'hf 14a sim t 2 u %014x' msg('Bruteforcing Mifare Ultralight card numbers') else return print(usage) From dfe36a2d606f41898867103ba509a48add38fecf Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 22 Mar 2020 11:55:38 +1100 Subject: [PATCH 195/298] Update cmdlfkeri.c Code clean and tune --- client/cmdlfkeri.c | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index a5d66caff..8bc3c7e54 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -197,15 +197,6 @@ static int CmdKeriDemod(const char *Cmd) { CmdKeriMSScramble (Descramble,&fc,&cardid,&raw2); PrintAndLogEx (SUCCESS,"Descrambled MS : FC %d - Card ID %d\n",fc,cardid); - -/* - Scamble: For dev testing only, will/should move to the create keri-ms code when added. - */ - // uint32_t testCard = 0; - // CmdKeriMSScramble (Scramble,&fc,&cardid,&testCard); - - -// End Descramble test if (invert) { PrintAndLogEx(INFO, "Had to Invert - probably KERI"); @@ -224,11 +215,10 @@ static int CmdKeriRead(const char *Cmd) { static int CmdKeriClone(const char *Cmd) { - uint8_t cmdptr = 0; - char format = 'i'; // default to raw + uint8_t cmdidx = 0; + char keritype = 'i'; // default to internalid uint32_t fc = 0; uint32_t cid = 0; - uint32_t cardid = 0; uint32_t internalid = 0; uint32_t blocks[3] = { T55x7_TESTMODE_DISABLED | @@ -250,22 +240,21 @@ static int CmdKeriClone(const char *Cmd) { cid = param_get32ex(Cmd, 0, 0, 10); // find other options - while (param_getchar(Cmd, cmdptr) != 0x00) { // && !errors) { - PrintAndLogEx (SUCCESS,"[%c]",param_getchar(Cmd, cmdptr)); - switch (tolower(param_getchar(Cmd, cmdptr))) { + while (param_getchar(Cmd, cmdidx) != 0x00) { // && !errors) { + switch (tolower(param_getchar(Cmd, cmdidx))) { case 'h': // help return usage_lf_keri_clone(); case 't': // format type - format = tolower(param_getchar(Cmd,cmdptr+1)); - cmdptr += 2; + keritype = tolower(param_getchar(Cmd,cmdidx+1)); + cmdidx += 2; break; case 'f': // fc - fc = param_get32ex(Cmd,cmdptr+1,0,10); - cmdptr += 2; + fc = param_get32ex(Cmd,cmdidx+1,0,10); + cmdidx += 2; break; case 'c': // cardid - cid = param_get32ex(Cmd,cmdptr+1,0,10); - cmdptr += 2; + cid = param_get32ex(Cmd,cmdidx+1,0,10); + cmdidx += 2; break; case 'q': // q5 blocks[0] = @@ -273,11 +262,11 @@ static int CmdKeriClone(const char *Cmd) { T5555_SET_BITRATE(128) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT; - cmdptr++; + cmdidx++; break; default: // Skip unknown - cmdptr++; + cmdidx++; } } @@ -295,15 +284,13 @@ static int CmdKeriClone(const char *Cmd) { } */ // Setup card data/build internal id - switch (format) { + switch (keritype) { case 'i' : // Internal ID // MSB is ONE internalid = cid | 0x80000000; break; case 'm' : // MS - cardid = 0; - CmdKeriMSScramble (Scramble,&fc,&cid,&cardid); - internalid = 0xE000000000000000 + cardid; + CmdKeriMSScramble (Scramble,&fc,&cid,&internalid); break; } From 1df6782312b61332a9a438e857527093585d75bc Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 22 Mar 2020 17:47:35 +1100 Subject: [PATCH 196/298] Update cmdlfkeri.c Card ID change to CN/Card Number --- client/cmdlfkeri.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 8bc3c7e54..ced67ad86 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -38,11 +38,11 @@ static int usage_lf_keri_clone(void) { // New format PrintAndLogEx(NORMAL, " [m|i] : Type. m - MS, i - Internal ID"); PrintAndLogEx(NORMAL, " : Facility Code"); - PrintAndLogEx(NORMAL, " : Card ID"); + PrintAndLogEx(NORMAL, " : Card Number"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf keri clone 112233"); - PrintAndLogEx(NORMAL, " lf keri clone type ms fc 6 cardid 12345"); + PrintAndLogEx(NORMAL, " lf keri clone type ms fc 6 cn 12345"); PrintAndLogEx(NORMAL, " lf keri clone t m f 6 c 12345"); return PM3_SUCCESS; @@ -130,7 +130,7 @@ static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *I // Bit 31 was fixed but not in check/parity bits *CardID |= (1 << 31); - PrintAndLogEx(SUCCESS, "Scrambled MS : FC %d - Card ID %d to RAW : E0000000%08X",*FC,*ID,*CardID); + PrintAndLogEx(SUCCESS, "Scrambled MS : FC %d - CN %d to RAW : E0000000%08X",*FC,*ID,*CardID); } return PM3_SUCCESS; } @@ -196,7 +196,7 @@ static int CmdKeriDemod(const char *Cmd) { // Just need to the low 32 bits without the 111 trailer CmdKeriMSScramble (Descramble,&fc,&cardid,&raw2); - PrintAndLogEx (SUCCESS,"Descrambled MS : FC %d - Card ID %d\n",fc,cardid); + PrintAndLogEx (SUCCESS,"Descrambled MS : FC %d - CN %d\n",fc,cardid); if (invert) { PrintAndLogEx(INFO, "Had to Invert - probably KERI"); From 8319b18bc76b62add81a8475417d8884ed9b82f5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Mar 2020 08:10:10 +0100 Subject: [PATCH 197/298] chg: hf mf sim - adapt number of sectors to print on type --- client/cmdhfmf.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 6425e10a3..89519b282 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3217,18 +3217,22 @@ static int CmdHF14AMfSim(const char *Cmd) { case 0: flags |= FLAG_MF_MINI; sprintf(csize, "MINI"); + k_sectorsCount = MIFARE_MINI_MAXSECTOR; break; case 1: flags |= FLAG_MF_1K; sprintf(csize, "1K"); + k_sectorsCount = MIFARE_1K_MAXSECTOR; break; case 2: flags |= FLAG_MF_2K; sprintf(csize, "2K with RATS"); + k_sectorsCount = MIFARE_2K_MAXSECTOR; break; case 4: flags |= FLAG_MF_4K; sprintf(csize, "4K"); + k_sectorsCount = MIFARE_4K_MAXSECTOR; break; default: PrintAndLogEx(WARNING, "Unknown parameter for option t"); @@ -3342,6 +3346,8 @@ static int CmdHF14AMfSim(const char *Cmd) { } showSectorTable(); } + + k_sectorsCount = MIFARE_4K_MAXSECTOR; return PM3_SUCCESS; } /* From 371e534ad422ec2791c81aa0beb08161585b352d Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 22 Mar 2020 21:05:27 +1100 Subject: [PATCH 198/298] Update CHANGELOG.md Keri MS support --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a36b58da..f4eeee148 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added keri MS decode/encode and update 'lf keri clone' to support MS fc/cid cloning. (@mwalker33) - Added `hf lto restore` - restore LTO cartridge memory from dump file [.bin|.eml] (@Kevin-Nakamoto) - Added `LF_ICEHID` standalone mode which searches for lf HID credentials and store to RDV4 flashmem (@iceman1001) - Added `HF_14ASNIFF` standalone mode with storing trace to RDV4 flashmem (@micolous) From d6f6f810944ab614ab71f0da883770eccd4f724b Mon Sep 17 00:00:00 2001 From: BarikMana <42164118+BarikMana@users.noreply.github.com> Date: Sun, 22 Mar 2020 23:44:06 +0900 Subject: [PATCH 199/298] Bosch Solution 6000 Key Sector 0 Key A&B Works with any Bosch Solution 6000 PR11xB reader. --- client/dictionaries/mfc_default_keys.dic | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index b3dfbd128..4682ad0e5 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1108,3 +1108,5 @@ fe04ecfe5577 # # unknown hotel key 6d9b485a4845 +# +5a7a52d5e20d # Bosch Solution 6000 From bc6de92771cddda46071e835b095d8f325a86389 Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Mon, 23 Mar 2020 21:32:20 -0700 Subject: [PATCH 200/298] Updates to the Tesla AIDs Now includes the AIDs that are used in the key fob and phone. Removed some AIDs that can't be selected. --- client/resources/aidlist.json | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/client/resources/aidlist.json b/client/resources/aidlist.json index 13e140e49..ddf844023 100644 --- a/client/resources/aidlist.json +++ b/client/resources/aidlist.json @@ -2128,27 +2128,19 @@ "Type": "EMV" }, { - "AID": "7465736C6153746F7265303032", + "AID": "7465736C614C6F6769633", "Vendor": "Tesla", "Country": "", - "Name": "teslaStore002", - "Description": "Tesla car key", + "Name": "teslaLogic (Original AID)", + "Description": "Key for Tesla vehicles", "Type": "Tesla" }, { - "AID": "7465736C614C6F67696330303201", + "AID": "F465736C614C6F6769633", "Vendor": "Tesla", "Country": "", - "Name": "teslaLogic002", - "Description": "Tesla car key", - "Type": "Tesla" - }, - { - "AID": "7465736C61", - "Vendor": "Tesla", - "Country": "", - "Name": "tesla", - "Description": "Tesla car key generic AID", + "Name": "teslaLogic (Alternate AID)", + "Description": "Key for Tesla vehicles", "Type": "Tesla" } -] \ No newline at end of file +] From 1e37c577294edd73f386f9484d9bba3a4241ebed Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 09:50:17 +0100 Subject: [PATCH 201/298] chg: hf mfdes info - adapted to support multiple keys --- client/cmdhfmfdes.c | 55 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 5ab35a12d..697ec596e 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -26,8 +26,32 @@ uint8_t key_ones_data[16] = { 0x01 }; uint8_t key_defa_data[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; uint8_t key_picc_data[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; + +typedef enum { + UNKNOWN = 0, + MF3ICD40, + EV1, + EV2, + LIGHT, +} desfire_cardtype_t; + + static int CmdHelp(const char *Cmd); +static desfire_cardtype_t getCardType(uint8_t major, uint8_t minor) { + + if (major == 0x00) + return MF3ICD40; + else if (major == 0x01 && minor == 0x00) + return EV1; + else if (major == 0x12 && minor == 0x00) + return EV2; + else if (major == 0x30 && minor == 0x00) + return LIGHT; + else + return UNKNOWN; +} + //ICEMAN: Turn on field method? //none static int test_desfire_authenticate() { @@ -95,11 +119,20 @@ static int get_desfire_freemem(uint32_t *free_mem) { // --- GET SIGNATURE -static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len) { +static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len, desfire_cardtype_t card_type) { + + uint8_t public_key; + if (card_type == LIGHT) + public_key = 0; + else if (card_type == EV2) + public_key = 1; + else + return PM3_EINVARG; + #define PUBLIC_DESFIRE_ECDA_KEYLEN 57 // ref: MIFARE Desfire Originality Signature Validation - uint8_t nxp_desfire_keys[1][PUBLIC_DESFIRE_ECDA_KEYLEN] = { + uint8_t nxp_desfire_keys[2][PUBLIC_DESFIRE_ECDA_KEYLEN] = { // DESFire Light { 0x04, 0x0E, 0x98, 0xE1, 0x17, 0xAA, 0xA3, 0x64, @@ -109,17 +142,26 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0x7B, 0x94, 0x2A, 0x97, 0x74, 0xA1, 0xD9, 0x4A, 0xD0, 0x25, 0x72, 0x42, 0x7E, 0x5A, 0xE0, 0xA2, 0xDD, 0x36, 0x59, 0x1B, 0x1F, 0xB3, 0x4F, 0xCF, 0x3D - } + }, // DESFire Ev2 + { + 0x04, 0x8A, 0x9B, 0x38, 0x0A, 0xF2, 0xEE, 0x1B, + 0x98, 0xDC, 0x41, 0x7F, 0xEC, 0xC2, 0x63, 0xF8, + 0x44, 0x9C, 0x76, 0x25, 0xCE, 0xCE, 0x82, 0xD9, + 0xB9, 0x16, 0xC9, 0x92, 0xDA, 0x20, 0x9D, 0x68, + 0x42, 0x2B, 0x81, 0xEC, 0x20, 0xB6, 0x5A, 0x66, + 0xB5, 0x10, 0x2A, 0x61, 0x59, 0x6A, 0xF3, 0x37, + 0x92, 0x00, 0x59, 0x93, 0x16, 0xA0, 0x0A, 0x14, 0x10 + } }; - uint8_t public_key = 0; + int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, nxp_desfire_keys[public_key], uid, 7, signature, signature_len, false); bool is_valid = (res == 0); PrintAndLogEx(INFO, " Tag Signature"); - PrintAndLogEx(INFO, " IC signature public key name : NXP DESFire Light"); + PrintAndLogEx(INFO, " IC signature public key name : %s", (card_type == LIGHT) ? "NXP DESFire Light" : "NXP DESFire Ev2"); PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_desfire_keys[public_key], 16)); PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 16, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 32, 16)); @@ -423,9 +465,10 @@ static int CmdHF14ADesInfo(const char *Cmd) { // Signature originality check uint8_t signature[56] = {0}; size_t signature_len = 0; + desfire_cardtype_t cardtype = getCardType(package->versionHW[3], package->versionHW[4]); if (get_desfire_signature(signature, &signature_len) == PM3_SUCCESS) - desfire_print_signature(package->uid, signature, signature_len); + desfire_print_signature(package->uid, signature, signature_len, cardtype); // Master Key settings uint8_t master_aid[3] = {0x00, 0x00, 0x00}; From 1f5de5debd9ae1edc6a0a7564748ba93edf9ca94 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 10:08:11 +0100 Subject: [PATCH 202/298] hitag sniff, use edgemode --- armsrc/lfadc.c | 57 +++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 32d1e73b6..0a85312bc 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -58,7 +58,7 @@ void lf_sample_mean(void) { periods++; } } - // division by 32 + // division by 32 adc_avg = adc_sum >> 5; if (DBGLEVEL >= DBG_EXTENDED) @@ -74,16 +74,16 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { while (!BUTTON_PRESS()) { // only every 100th times, in order to save time when collecting samples. -/* - if (checked == 1000) { - if (data_available()) { - break; - } else { - checked = 0; - } - } - ++checked; -*/ + /* + if (checked == 1000) { + if (data_available()) { + break; + } else { + checked = 0; + } + } + ++checked; + */ WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { @@ -136,12 +136,12 @@ void lf_reset_counter() { // TODO: find out the correct reset settings for tag and reader mode // if (reader_mode) { - // Reset values for reader mode - rising_edge = false; - previous_adc_val = 0xFF; + // Reset values for reader mode + rising_edge = false; + previous_adc_val = 0xFF; // } else { - // Reset values for tag/transponder mode + // Reset values for tag/transponder mode // rising_edge = false; // previous_adc_val = 0xFF; // } @@ -179,7 +179,8 @@ void lf_init(bool reader, bool simulate) { // FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); else - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); + // Sniff + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); } @@ -249,18 +250,18 @@ size_t lf_detect_field_drop(size_t max) { while (!BUTTON_PRESS()) { -/* - // only every 1000th times, in order to save time when collecting samples. - if (checked == 1000) { - if (data_available()) { - checked = -1; - break; - } else { - checked = 0; - } - } - ++checked; -*/ + /* + // only every 1000th times, in order to save time when collecting samples. + if (checked == 1000) { + if (data_available()) { + checked = -1; + break; + } else { + checked = 0; + } + } + ++checked; + */ WDT_HIT(); From 4f78edff3149f50de7665956cce6b64b2692f628 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 11:31:23 +0100 Subject: [PATCH 203/298] textual --- client/cmdlft55xx.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index fafb5d2da..574030f01 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -482,12 +482,16 @@ static bool t55xxProtect(bool lock, bool usepwd, uint8_t override, uint32_t pass int res = T55xxReadBlockEx(T55x7_CONFIGURATION_BLOCK, T55x7_PAGE0, usepwd, override, password, downlink_mode, false); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Failed to read block0, use `p` password parameter?"); + PrintAndLogEx(WARNING, "Failed to read block0, use " _YELLOW_("`p`") "password parameter?"); return false; } - if (GetT55xxBlockData(&block0) == false) + if (GetT55xxBlockData(&block0) == false) { + PrintAndLogEx(DEBUG, "ERROR decoded block0 == %08x", block0); return false; + } + PrintAndLogEx(DEBUG, "OK read block0 == %08x", block0); + bool isPwdBitAlreadySet = (block0 >> (32 - 28) & 1); if (isPwdBitAlreadySet) { @@ -3679,7 +3683,7 @@ static int CmdT55xxProtect(const char *Cmd) { // lock if (t55xxProtect(true, usepwd, override, password, downlink_mode, new_password) == false) { - PrintAndLogEx(WARNING, "Command failed. Did you run `lf t55xx detect` before?"); + PrintAndLogEx(WARNING, "Command failed. Did you run " _YELLOW_("`lf t55xx detect`") "before?"); return PM3_ESOFT; } return PM3_SUCCESS; From f5a8b0601b93b3cfccd9895149a8e64cba31ac7e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 11:33:52 +0100 Subject: [PATCH 204/298] fix: coverity 274220 --- client/ui.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ui.c b/client/ui.c index df62b9bff..bac8b2956 100644 --- a/client/ui.c +++ b/client/ui.c @@ -159,6 +159,7 @@ void PrintAndLogEx(logLevel_t level, const char *fmt, ...) { break; case DEBUG: strncpy(prefix, _BLUE_("[#]"), sizeof(prefix) - 1); + break; case HINT: case SUCCESS: strncpy(prefix, _GREEN_("[+]"), sizeof(prefix) - 1); From a8aadb27515819c52c6068a29340566616d59a4d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 11:45:57 +0100 Subject: [PATCH 205/298] cppchecker missing includes --- armsrc/LCD_disabled.c | 2 +- client/cmdhfmfdesfire_disabled.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/LCD_disabled.c b/armsrc/LCD_disabled.c index 32a917928..97bf6da71 100644 --- a/armsrc/LCD_disabled.c +++ b/armsrc/LCD_disabled.c @@ -5,7 +5,7 @@ //----------------------------------------------------------------------------- // LCD code //----------------------------------------------------------------------------- -#include "LCD.h" +#include "LCD_disabled.h" void LCDSend(unsigned int data) { // 9th bit set for data, clear for command diff --git a/client/cmdhfmfdesfire_disabled.c b/client/cmdhfmfdesfire_disabled.c index fc123667b..e2d43630f 100644 --- a/client/cmdhfmfdesfire_disabled.c +++ b/client/cmdhfmfdesfire_disabled.c @@ -8,7 +8,7 @@ // High frequency MIFARE commands //----------------------------------------------------------------------------- -#include "cmdhfmfdesfire.h" +#include "cmdhfmfdesfire_disabled.h" #include "cmdparser.h" // command_t From b63495cce72d3bd192a64358d6db01de4f6f8002 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 11:56:03 +0100 Subject: [PATCH 206/298] cppchecker missing includes --- armsrc/buzzer_disabled.c | 2 +- armsrc/desfire_crypto_disabled.c | 4 +--- armsrc/fonts_disabled.c | 2 +- armsrc/mifaresniff_disabled.c | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/armsrc/buzzer_disabled.c b/armsrc/buzzer_disabled.c index 708b7d3f7..579ffaa4e 100644 --- a/armsrc/buzzer_disabled.c +++ b/armsrc/buzzer_disabled.c @@ -1,4 +1,4 @@ -#include "buzzer.h" +#include "buzzer_disabled.h" void Ring_BEE_ONCE(uint16_t music_note) { BEE_ON(); diff --git a/armsrc/desfire_crypto_disabled.c b/armsrc/desfire_crypto_disabled.c index d835a55d4..02896afa8 100644 --- a/armsrc/desfire_crypto_disabled.c +++ b/armsrc/desfire_crypto_disabled.c @@ -26,9 +26,7 @@ * May 2005 */ #include - -#include "desfire_crypto.h" - +#include "desfire_crypto_disabled.h" #include "crc32.h" #include "printf.h" #include "desfire.h" diff --git a/armsrc/fonts_disabled.c b/armsrc/fonts_disabled.c index 97079f48a..45a85e679 100644 --- a/armsrc/fonts_disabled.c +++ b/armsrc/fonts_disabled.c @@ -6,7 +6,7 @@ // Fonts for the LCD //----------------------------------------------------------------------------- -#include "fonts.h" +#include "fonts_disabled.h" const char FONT6x8[97][8] = { {0x06, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, // columns, rows, bytes per char diff --git a/armsrc/mifaresniff_disabled.c b/armsrc/mifaresniff_disabled.c index 799fd62be..6ccdc8e6c 100644 --- a/armsrc/mifaresniff_disabled.c +++ b/armsrc/mifaresniff_disabled.c @@ -8,7 +8,7 @@ // Routines to support mifare classic sniffer. //----------------------------------------------------------------------------- -#include "mifaresniff.h" +#include "mifaresniff_disabled.h" #ifndef CheckCrc14A # define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len)) From 90a9c215de47d48c4dbf867149f1a06a63f6d017 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 11:59:22 +0100 Subject: [PATCH 207/298] cppchecker missing includes --- armsrc/hitag2crack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/hitag2crack.c b/armsrc/hitag2crack.c index d66f740bc..34d35ada6 100644 --- a/armsrc/hitag2crack.c +++ b/armsrc/hitag2crack.c @@ -11,7 +11,7 @@ // hitag2 attack functions //----------------------------------------------------------------------------- -#include "hitagcrypto.h" +#include "hitag2_crypto.h" #include "hitag2crack.h" #define READP0CMD "1100000111" From 0fbf7d6328ed2088c72564f55bfa3e9b56cc75e8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 13:06:09 +0100 Subject: [PATCH 208/298] cppchecker - shadow --- client/cmdhfmfdes.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 697ec596e..7209a5a71 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -557,9 +557,6 @@ char *getVersionStr(uint8_t major, uint8_t minor) { void getKeySettings(uint8_t *aid) { - char messStr[512] = {0x00}; - const char *str = messStr; - if (memcmp(aid, "\x00\x00\x00", 3) == 0) { // CARD MASTER KEY @@ -587,9 +584,7 @@ void getKeySettings(uint8_t *aid) { PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings")); } - - memset(messStr, 0x00, sizeof(messStr)); - str = " Operation of PICC master key : " _YELLOW_("%s"); + const char *str = " Operation of PICC master key : " _YELLOW_("%s"); // 2 MSB denotes switch (num_keys >> 6) { @@ -709,8 +704,8 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { // Get File IDs if (get_desfire_fileids(file_ids, &file_ids_len) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") "file%c", file_ids_len, (file_ids_len == 1) ? ' ' : 's'); - for (int i = 0; i < file_ids_len; ++i) { - PrintAndLogEx(SUCCESS, " Fileid %d (0x%02x)", file_ids[i], file_ids[i]); + for (int j = 0; j < file_ids_len; ++j) { + PrintAndLogEx(SUCCESS, " Fileid %d (0x%02x)", file_ids[j], file_ids[j]); } } From 5acd681f8f72ced055d4dc5f129dbfdcacb94427 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 13:11:50 +0100 Subject: [PATCH 209/298] cppchecker - too many shifts --- client/cmdlfkeri.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 1299d767a..a77f3c477 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -128,7 +128,7 @@ static int CmdKeriMSScramble (KeriMSScramble_t Action, uint32_t *FC, uint32_t *I *CardID = *CardID | Parity; // Bit 31 was fixed but not in check/parity bits - *CardID |= (uint32_t)(1 << 31); + *CardID |= 1UL << 31; PrintAndLogEx(SUCCESS, "Scrambled MS : FC %d - CN %d to RAW : E0000000%08X",*FC,*ID,*CardID); } From 10243d9bce05782ca8300c7d5ea361657295e06b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 13:16:47 +0100 Subject: [PATCH 210/298] cppchecker - too many shifts --- client/wiegand_formatutils.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/wiegand_formatutils.c b/client/wiegand_formatutils.c index ba446957a..836da717d 100644 --- a/client/wiegand_formatutils.c +++ b/client/wiegand_formatutils.c @@ -36,21 +36,21 @@ bool set_bit_by_position(wiegand_message_t *data, bool value, uint8_t pos) { return false; } else if (pos > 63) { if (value) - data->Top |= (1 << (pos - 64)); + data->Top |= (1UL << (pos - 64)); else - data->Top &= ~(1 << (pos - 64)); + data->Top &= ~(1UL << (pos - 64)); return true; } else if (pos > 31) { if (value) - data->Mid |= (1 << (pos - 32)); + data->Mid |= (1UL << (pos - 32)); else - data->Mid &= ~(1 << (pos - 32)); + data->Mid &= ~(1UL << (pos - 32)); return true; } else { if (value) - data->Bot |= (1 << pos); + data->Bot |= (1UL << pos); else - data->Bot &= ~(1 << pos); + data->Bot &= ~(1UL << pos); return true; } } From a24c7334cfe84fd1651b0810ebb48ffba1fbddb0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 13:20:50 +0100 Subject: [PATCH 211/298] cppchecker - invalidprintf --- tools/hitag2crack/crack3/ht2crack3.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/hitag2crack/crack3/ht2crack3.c b/tools/hitag2crack/crack3/ht2crack3.c index da35bbd14..9e39a8e09 100644 --- a/tools/hitag2crack/crack3/ht2crack3.c +++ b/tools/hitag2crack/crack3/ht2crack3.c @@ -214,15 +214,15 @@ void *crack(void *d) { uint64_t y; uint64_t ytmp; uint64_t klowery; - unsigned int count = 0; + unsigned int count; uint64_t bit; uint64_t b; uint64_t z; uint64_t foundkey; uint64_t revkey; int ret; - unsigned int found = 0; - unsigned int badguess = 0; + unsigned int found; + unsigned int badguess; struct Tklower *Tk = NULL; @@ -312,7 +312,7 @@ void *crack(void *d) { // normalise foundkey revkey = rev64(foundkey); foundkey = ((revkey >> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000); - printf("\n\nSuccess - key = %012lX\n", foundkey); + printf("\n\nSuccess - key = %012"PRIx64"\n", foundkey); exit(0); return (void *)foundkey; @@ -446,7 +446,7 @@ int main(int argc, char *argv[]) { } printf("thread %i finished\n", i); if (status) { - printf("Key = %012lX\n", (uint64_t)status); + printf("Key = %012"PRIx64"\n", (uint64_t)status); exit(0); } } From 20547d773b8e1c940fcfd34d35ea4f13edf1048e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 13:27:33 +0100 Subject: [PATCH 212/298] cppchecker - buffer overflow --- armsrc/mifaredesfire.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index 06a3f3f8c..5b8ed289e 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -134,7 +134,7 @@ void MifareDesfireGetInformation() { return; } // add uid. - memcpy(payload.uid, card.uid, sizeof(card.uid)); + memcpy(payload.uid, card.uid, sizeof(payload.uid)); LED_A_ON(); uint8_t cmd[] = {GET_VERSION, 0x00, 0x00, 0x00}; From 0033715a595d34e1e603a144c8af35c21587a9fb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Mar 2020 13:35:33 +0100 Subject: [PATCH 213/298] cppchecker --- client/tinycbor/cborpretty.c | 4 ++-- client/tinycbor/cbortojson.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/tinycbor/cborpretty.c b/client/tinycbor/cborpretty.c index 775d90925..71f05522f 100644 --- a/client/tinycbor/cborpretty.c +++ b/client/tinycbor/cborpretty.c @@ -488,14 +488,14 @@ static CborError value_to_pretty(CborStreamFunction stream, void *out, CborValue case CborFloatType: cbor_value_get_float(it, &f); val = f; - suffix = flags & CborPrettyNumericEncodingIndicators ? "_2" : "f"; + suffix = (flags & CborPrettyNumericEncodingIndicators) ? "_2" : "f"; } else if (false) { uint16_t f16; case CborHalfFloatType: #ifndef CBOR_NO_HALF_FLOAT_TYPE cbor_value_get_half_float(it, &f16); val = decode_half(f16); - suffix = flags & CborPrettyNumericEncodingIndicators ? "_1" : "f16"; + suffix = (flags & CborPrettyNumericEncodingIndicators) ? "_1" : "f16"; #else (void)f16; err = CborErrorUnsupportedType; diff --git a/client/tinycbor/cbortojson.c b/client/tinycbor/cbortojson.c index 3ea90cee8..8d39303bc 100644 --- a/client/tinycbor/cbortojson.c +++ b/client/tinycbor/cbortojson.c @@ -146,7 +146,7 @@ * the keys for the metadata clash with existing keys in the JSON map. */ -extern FILE *open_memstream(char **bufptr, size_t *sizeptr); +extern FILE *open_memstream(char **bufptr, size_t *lenptr); enum ConversionStatusFlags { TypeWasNotNative = 0x100, /* anything but strings, boolean, null, arrays and maps */ From f593efebf4b6fc5e3e7522d7d1a002574fea5ffe Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Tue, 24 Mar 2020 09:18:16 -0700 Subject: [PATCH 214/298] Re-added `teslaStore` AID, also added `TeslaDAP` AID --- client/resources/aidlist.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/client/resources/aidlist.json b/client/resources/aidlist.json index ddf844023..e427e34bf 100644 --- a/client/resources/aidlist.json +++ b/client/resources/aidlist.json @@ -2127,6 +2127,14 @@ "Description": "Brazilian Bank Banco Bradesco", "Type": "EMV" }, + { + "AID": "7465736C6153746F7265", + "Vendor": "Tesla", + "Country": "", + "Name": "teslaStore", + "Description": "Undocumented AID associated with official Tesla Key Cards", + "Type": "Tesla" + }, { "AID": "7465736C614C6F6769633", "Vendor": "Tesla", @@ -2142,5 +2150,13 @@ "Name": "teslaLogic (Alternate AID)", "Description": "Key for Tesla vehicles", "Type": "Tesla" + }, + { + "AID": "5465736c61444150", + "Vendor": "Tesla", + "Country": "", + "Name": "TeslaDAP", + "Description": "Undocumented AID associated with official Tesla BTLE Key Fobs", + "Type": "Tesla" } ] From 0c25f85c9f93269e7cf68ad5b5d4bfbc3d075c32 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 25 Mar 2020 11:19:20 +0100 Subject: [PATCH 215/298] empty string. --- client/scripting.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/scripting.c b/client/scripting.c index 7ba38ee8b..756799626 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -790,6 +790,7 @@ static int l_reveng_runmodel(lua_State *L) { // l = little endian input and output, L = little endian output only, t = left justified} //result = calculated crc hex string char result[50]; + memset(result, 0x00, sizeof(result)); const char *inModel = luaL_checkstring(L, 1); const char *inHexStr = luaL_checkstring(L, 2); @@ -800,7 +801,7 @@ static int l_reveng_runmodel(lua_State *L) { if (!ans) return returnToLuaWithError(L, "Reveng failed"); - lua_pushstring(L, (const char *)result); + lua_pushstring(L, result); return 1; } From dc4bd2c1f70cc5b50a88e3af2d9ebae0b79e15a5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 25 Mar 2020 11:20:35 +0100 Subject: [PATCH 216/298] fix: bizarr behavior in Proxspace lua, where io.read("*l") default behavior swaps to io.read("*L") . So lets make *L default a strip away all newlines... --- client/lualibs/utils.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua index c265a5d8c..2f27b6c38 100644 --- a/client/lualibs/utils.lua +++ b/client/lualibs/utils.lua @@ -20,17 +20,17 @@ local Utils = end, --- -- Asks the user for input - input = function (message , default) - local answer + input = function (message, default) + local answer = '' if default ~= nil then message = message .. " (default: ".. default.. " )" end - message = message .." \n > " - io.write(message) + io.write(message, "\n > ") io.flush() - answer = io.read() - if answer == '' then answer = default end - + answer = io.read("*L") + answer = string.gsub(answer, "\r\n", "") + answer = string.gsub(answer, "\n", "") + if answer == '' or answer == nil then answer = default end return answer end, From 6e49d94a821addf9b158be3232dfe2dab6f4d2ac Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 25 Mar 2020 16:35:31 +0100 Subject: [PATCH 217/298] fix coverity 205241 --- client/cliparser/argtable3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c index 3acbce48e..b8644dd86 100644 --- a/client/cliparser/argtable3.c +++ b/client/cliparser/argtable3.c @@ -250,7 +250,7 @@ const char *optarg; /* argument associated with option */ #define BADARG ((*options == ':') ? (int)':' : (int)'?') #define INORDER (int)1 -#define EMSG "" +#define EMSG " " static int getopt_internal(int, char *const *, const char *, const struct option *, int *, int); From a9571d26b02e2a74c44878f6d579f580d6b390c1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 25 Mar 2020 16:49:19 +0100 Subject: [PATCH 218/298] fix coverity 274113 --- client/cmdhficlass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 1dccaef5c..b7ebdca9f 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -867,7 +867,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { uint32_t limit = MIN(applimit, decryptedlen / 8); if (decryptedlen / 8 != applimit) { - PrintAndLogEx(WARNING, "Actual file len " _YELLOW_("%u") "vs HID app-limit len " _YELLOW_("%u"), decryptedlen, applimit * 8); + PrintAndLogEx(WARNING, "Actual file len " _YELLOW_("%zu") "vs HID app-limit len " _YELLOW_("%u"), decryptedlen, applimit * 8); PrintAndLogEx(INFO, "Setting limit to " _GREEN_("%u"), limit * 8); } uint8_t numblocks4userid = GetNumberBlocksForUserId(decrypted + (6 * 8)); From b0b5bcda762a3fcf74e4ef776219f18c34f97644 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 25 Mar 2020 17:27:19 +0100 Subject: [PATCH 219/298] textual --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e48802b81..6192c23cd 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,9 @@ On the software side: quite a lot, see the [Changelog file](CHANGELOG.md). > ⚠ **Note**: This is a bleeding edge repository. The maintainers actively is working out of this repository and will be periodically re-structuring the code to make it easier to comprehend, navigate, build, test, and contribute to, so **DO expect significant changes to code layout on a regular basis**. This repo compiles nicely on - - Proxspace v3.2 + - Proxspace v3.x - Windows/mingw environment with Qt5.6.1 & GCC 4.8 - - Ubuntu 1404, 1510, 1604, 1804, 1904 + - Ubuntu 1604, 1804, 1904 - Mac OS X / Homebrew - ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora - WSL, WSL2 (Windows subsystem linux) on Windows 10 From 5e21566201d6bc57a1d9a944acbaa6e671387bae Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 25 Mar 2020 17:41:10 +0100 Subject: [PATCH 220/298] coverity 274112 - unintended sign extension --- armsrc/hitagS.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 07b445434..78009496e 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -888,8 +888,8 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { // use the last read tag } - tag.uid = (tag.pages[0][3] << 24 | tag.pages[0][2] << 16 | tag.pages[0][1] << 8 | tag.pages[0][0]); - tag.key = (tag.pages[3][3] << 24 | tag.pages[3][2] << 16 | tag.pages[3][1] << 8 | tag.pages[3][0]); + tag.uid = ((tag.pages[0][3]) << 24) | ((tag.pages[0][2]) << 16) | ((tag.pages[0][1]) << 8) | tag.pages[0][0]; + tag.key = ((tag.pages[3][3]) << 24) | ((tag.pages[3][2]) << 16) | ((tag.pages[3][1]) << 8) | tag.pages[3][0]; tag.key <<= 16; tag.key += ((tag.pages[2][3]) << 8) + tag.pages[2][2]; tag.pwdl0 = tag.pages[2][0]; From 15726268bf5478bb5b40d4022b5b4b5a047cfc48 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Mar 2020 09:30:59 +0100 Subject: [PATCH 221/298] fix: hf mf fchk - exit on button press --- armsrc/mifarecmd.c | 70 +++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 0136ed6c9..a8f829144 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -82,22 +82,22 @@ void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain) { while (true) { if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); break; }; if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - if (DBGLEVEL >= 1) Dbprintf("Auth error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error"); break; }; if (mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) { - if (DBGLEVEL >= 1) Dbprintf("Read block error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Read block error"); break; }; if (mifare_classic_halt(pcs, cuid)) { - if (DBGLEVEL >= 1) Dbprintf("Halt error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error"); break; }; @@ -243,25 +243,25 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain) { isOK = 1; if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { isOK = 0; - if (DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); } if (isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { isOK = 0; - if (DBGLEVEL >= 1) Dbprintf("Auth error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error"); } for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) { isOK = 0; - if (DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo); break; } } if (mifare_classic_halt(pcs, cuid)) { - if (DBGLEVEL >= 1) Dbprintf("Halt error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error"); } if (DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED"); @@ -409,22 +409,22 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { while (true) { if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); break; }; if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - if (DBGLEVEL >= 1) Dbprintf("Auth error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Auth error"); break; }; if (mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) { - if (DBGLEVEL >= 1) Dbprintf("Write block error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error"); break; }; if (mifare_classic_halt(pcs, cuid)) { - if (DBGLEVEL >= 1) Dbprintf("Halt error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error"); break; }; @@ -460,18 +460,18 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); if(!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) { - if (DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); OnError(0); return; }; if(mifare_ultra_writeblock_compat(blockNo, blockdata)) { - if (DBGLEVEL >= 1) Dbprintf("Write block error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error"); OnError(0); return; }; if(mifare_ultra_halt()) { - if (DBGLEVEL >= 1) Dbprintf("Halt error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error"); OnError(0); return; }; @@ -506,7 +506,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { set_tracing(true); if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { - if (DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); OnError(0); return; }; @@ -534,13 +534,13 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { } if (mifare_ultra_writeblock(blockNo, blockdata)) { - if (DBGLEVEL >= 1) Dbprintf("Write block error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error"); OnError(0); return; }; if (mifare_ultra_halt()) { - if (DBGLEVEL >= 1) Dbprintf("Halt error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error"); OnError(0); return; }; @@ -569,7 +569,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain) { set_tracing(true); if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { - if (DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); OnError(0); return; }; @@ -579,7 +579,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain) { blockdata[2] = pwd[5]; blockdata[3] = pwd[4]; if (mifare_ultra_writeblock(44, blockdata)) { - if (DBGLEVEL >= 1) Dbprintf("Write block error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error"); OnError(44); return; }; @@ -589,7 +589,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain) { blockdata[2] = pwd[1]; blockdata[3] = pwd[0]; if (mifare_ultra_writeblock(45, blockdata)) { - if (DBGLEVEL >= 1) Dbprintf("Write block error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error"); OnError(45); return; }; @@ -599,7 +599,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain) { blockdata[2] = pwd[13]; blockdata[3] = pwd[12]; if (mifare_ultra_writeblock(46, blockdata)) { - if (DBGLEVEL >= 1) Dbprintf("Write block error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error"); OnError(46); return; }; @@ -609,13 +609,13 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain) { blockdata[2] = pwd[9]; blockdata[3] = pwd[8]; if (mifare_ultra_writeblock(47, blockdata)) { - if (DBGLEVEL >= 1) Dbprintf("Write block error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error"); OnError(47); return; }; if (mifare_ultra_halt()) { - if (DBGLEVEL >= 1) Dbprintf("Halt error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error"); OnError(0); return; }; @@ -674,7 +674,7 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t flags) { if (!have_uid) { // need a full select cycle to get the uid first iso14a_card_select_t card_info; if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireNonces: Can't select card (ALL)"); continue; } switch (card_info.uidlen) { @@ -693,7 +693,7 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t flags) { have_uid = true; } else { // no need for anticollision. We can directly select the card if (!iso14443a_fast_select_card(uid, cascade_levels)) { - if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireNonces: Can't select card (UID)"); continue; } } @@ -792,7 +792,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, if (!have_uid) { // need a full select cycle to get the uid first iso14a_card_select_t card_info; if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireNonces: Can't select card (ALL)"); continue; } switch (card_info.uidlen) { @@ -811,7 +811,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, have_uid = true; } else { // no need for anticollision. We can directly select the card if (!iso14443a_fast_select_card(uid, cascade_levels)) { - if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireNonces: Can't select card (UID)"); continue; } } @@ -821,7 +821,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint32_t nt1; if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) { - if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireNonces: Auth1 error"); continue; } @@ -832,7 +832,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, CHK_TIMEOUT(); if (len != 4) { - if (DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("AcquireNonces: Auth2 error len=%d", len); continue; } @@ -1422,7 +1422,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da iso14a_card_select_t card_info; if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (DBGLEVEL >= 1) Dbprintf("ChkKeys_fast: Can't select card (ALL)"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("ChkKeys_fast: Can't select card (ALL)"); goto OUT; } @@ -1470,7 +1470,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da for (uint16_t i = s_point; i < keyCount; ++i) { // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && data_available()) { + if (BUTTON_PRESS() || data_available()) { goto OUT; } @@ -1562,7 +1562,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da for (uint16_t i = 0; i < keyCount; i++) { // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && data_available()) break; + if (BUTTON_PRESS() || data_available()) break; // found all keys? if (foundkeys == allkeys) @@ -1731,7 +1731,7 @@ void MifareChkKeys(uint8_t *datain) { if (!have_uid) { // need a full select cycle to get the uid first iso14a_card_select_t card_info; if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (ALL)"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("ChkKeys: Can't select card (ALL)"); --i; // try same key once again continue; } @@ -1751,7 +1751,7 @@ void MifareChkKeys(uint8_t *datain) { have_uid = true; } else { // no need for anticollision. We can directly select the card if (!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) { - if (DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)"); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("ChkKeys: Can't select card (UID)"); --i; // try same key once again continue; } From 063b393eba57df3810cdce3808f159305b437a7a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Mar 2020 20:36:38 +0100 Subject: [PATCH 222/298] textual --- client/cmdhfmfp.c | 25 ++++++++++++------------ client/dictionaries/mfp_default_keys.dic | 3 +++ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 2a1533344..ff1b87cf5 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -42,7 +42,7 @@ static int CmdHFMFPInfo(const char *Cmd) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-- Mifare Plus Tag Information ------------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); - + // info about 14a part infoHF14A(false, false, false); @@ -61,13 +61,12 @@ static int CmdHFMFPInfo(const char *Cmd) { PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, " Fingerprint"); - + // MIFARE Type Identification Procedure // https://www.nxp.com/docs/en/application-note/AN10833.pdf uint16_t ATQA = card.atqa[0] + (card.atqa[1] << 8); - bool isPlus = false; - + if (ATQA == 0x0004) { PrintAndLogEx(INFO, " ATQA - " _GREEN_("Mifare Plus 2K") " (4b UID)"); isPlus = true; @@ -131,25 +130,25 @@ static int CmdHFMFPInfo(const char *Cmd) { } } -// How do we detect SL0 / SL1 / SL2 / SL3 modes?!? + // How do we detect SL0 / SL1 / SL2 / SL3 modes?!? PrintAndLogEx(INFO, "Security Level (SL)"); switch(SLmode) { - case 0: + case 0: PrintAndLogEx(INFO, "SL 0: initial delivery configuration, used for card personalization"); break; case 1: PrintAndLogEx(INFO, "SL 1: backwards functional compatibility mode (with MIFARE Classic 1K / 4K) with an optional AES authentication"); break; - case 2: + case 2: PrintAndLogEx(INFO, "SL 2: 3-Pass Authentication based on AES followed by MIFARE CRYPTO1 authentication, communication secured by MIFARE CRYPTO1"); break; - case 3: + case 3: PrintAndLogEx(INFO, "SL 3: 3-Pass authentication based on AES, data manipulation commands secured by AES encryption and an AES based MACing method."); break; - default: + default: break; } - + if (SLmode != 0xFF) PrintAndLogEx(SUCCESS, "\tMifare Plus SL mode: " _YELLOW_("SL%d"), SLmode); else @@ -966,9 +965,9 @@ static int CmdHFMFPChk(const char *Cmd) { if (foundKeys[0][sector][0] || foundKeys[1][sector][0]) { if (!printedHeader) { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, ".------.--------------------------------.--------------------------------."); + PrintAndLogEx(INFO, "-------+--------------------------------+---------------------------------"); PrintAndLogEx(INFO, "|sector| key A | key B |"); - PrintAndLogEx(INFO, "|------|--------------------------------|--------------------------------|"); + PrintAndLogEx(INFO, "|------+--------------------------------+--------------------------------|"); printedHeader = true; } PrintAndLogEx(INFO, "| %02d |%32s|%32s|", @@ -980,7 +979,7 @@ static int CmdHFMFPChk(const char *Cmd) { if (!printedHeader) PrintAndLogEx(INFO, "No keys found("); else - PrintAndLogEx(INFO, "'------'--------------------------------'--------------------------------'\n"); + PrintAndLogEx(INFO, "'------+--------------------------------+--------------------------------'\n"); // save keys to json if ((jsonnamelen > 0) && printedHeader) { diff --git a/client/dictionaries/mfp_default_keys.dic b/client/dictionaries/mfp_default_keys.dic index 0f20b69bf..e492e2686 100644 --- a/client/dictionaries/mfp_default_keys.dic +++ b/client/dictionaries/mfp_default_keys.dic @@ -25,3 +25,6 @@ eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 15141312111009080706050403020100 0f0e0d0c0b0a09080706050403020100 100f0e0d0c0b0a090807060504030201 +404142434445464748494a4b4c4d4e4f +303132333435363738393a3b3c3d3e3f + From ffb8ad98737372db3c7b8d1bcc8a294cb995c3cb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Mar 2020 21:04:58 +0100 Subject: [PATCH 223/298] defaults --- client/mifare/mifaredefault.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/mifare/mifaredefault.c b/client/mifare/mifaredefault.c index b41859f09..8c9a26071 100644 --- a/client/mifare/mifaredefault.c +++ b/client/mifare/mifaredefault.c @@ -34,6 +34,8 @@ const char *g_mifare_plus_default_keys[] = { "000102030405060708090a0b0c0d0e0f", "0102030405060708090a0b0c0d0e0f10", "00010203040506070809101112131415", - "01020304050607080910111213141516" + "01020304050607080910111213141516", + "404142434445464748494a4b4c4d4e4f", + "303132333435363738393a3b3c3d3e3f", }; size_t g_mifare_plus_default_keys_len = ARRAYLEN(g_mifare_plus_default_keys); From 82d99522b4858251952773215ff48d8e08c91fc5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 27 Mar 2020 11:56:47 +0100 Subject: [PATCH 224/298] textual --- client/cmdhficlass.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index b7ebdca9f..f4a62b6c1 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -122,9 +122,9 @@ static int usage_hf_iclass_clone(void) { PrintAndLogEx(NORMAL, "Usage: hf iclass clone f b l k c e|r"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " f : specify a filename to clone from"); - PrintAndLogEx(NORMAL, " b : The first block to clone as 2 hex symbols"); - PrintAndLogEx(NORMAL, " l : Set the Data to write as 16 hex symbols"); - PrintAndLogEx(NORMAL, " k : Access Key as 16 hex symbols or 1 hex to select key from memory"); + PrintAndLogEx(NORMAL, " b : The first block to clone as 2 hex symbols"); + PrintAndLogEx(NORMAL, " l : Set the Data to write as 16 hex symbols"); + PrintAndLogEx(NORMAL, " k : Access Key as 16 hex symbols or 1 hex to select key from memory"); PrintAndLogEx(NORMAL, " c : If 'c' is specified, the key set is assumed to be the credit key\n"); PrintAndLogEx(NORMAL, " e : If 'e' is specified, elite computations applied to key"); PrintAndLogEx(NORMAL, " r : If 'r' is specified, no computations applied to key"); @@ -135,18 +135,18 @@ static int usage_hf_iclass_clone(void) { return PM3_SUCCESS; } static int usage_hf_iclass_writeblock(void) { - PrintAndLogEx(NORMAL, "Usage: hf iclass writeblk b d k [c|e|r|v]\n"); + PrintAndLogEx(NORMAL, "Usage: hf iclass wrbl b d k [c|e|r|v]\n"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " b : The block number as 2 hex symbols"); + PrintAndLogEx(NORMAL, " b : The block number as 2 hex symbols"); PrintAndLogEx(NORMAL, " d : set the Data to write as 16 hex symbols"); - PrintAndLogEx(NORMAL, " k : access Key as 16 hex symbols or 1 hex to select key from memory"); + PrintAndLogEx(NORMAL, " k : access Key as 16 hex symbols or 1 hex to select key from memory"); PrintAndLogEx(NORMAL, " c : credit key assumed\n"); PrintAndLogEx(NORMAL, " e : elite computations applied to key"); PrintAndLogEx(NORMAL, " r : raw, no computations applied to key"); PrintAndLogEx(NORMAL, " v : verbose output"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B"); - PrintAndLogEx(NORMAL, " hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c"); + PrintAndLogEx(NORMAL, " hf iclass wrbl b 0A d AAAAAAAAAAAAAAAA k 001122334455667B"); + PrintAndLogEx(NORMAL, " hf iclass wrbl b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c"); return PM3_SUCCESS; } static int usage_hf_iclass_readblock(void) { From 8c8a86cb835b6363e142e924d12fa4777b86b302 Mon Sep 17 00:00:00 2001 From: Uli Heilmeier Date: Tue, 25 Feb 2020 22:24:16 +0100 Subject: [PATCH 225/298] Standalone mode: Adding Legic Prime read/sim run This commit adds a standalone mode for Legic Prime. It reads and simulates a Legic tag. Tested with MIM1024 tags. MIM256 and MIM512 should work to. We just read the data and for simulating we pretend to be a MIM1024 card. Co-authored-by: Stefanie Hofmann <> --- armsrc/Standalone/Makefile.hal | 2 +- armsrc/Standalone/Makefile.inc | 6 ++- armsrc/Standalone/hf_legic.c | 81 ++++++++++++++++++++++++++++++++++ armsrc/legicrf.c | 5 +++ armsrc/legicrf.h | 2 +- 5 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 armsrc/Standalone/hf_legic.c diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index 5c2352aaf..bd018e15b 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -50,7 +50,7 @@ define KNOWN_STANDALONE_DEFINITIONS endef STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_ICEHID LF_EM4100EMUL LF_EM4100RWC -STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG HF_14ASNIFF +STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG HF_14ASNIFF HF_LEGIC STANDALONE_MODES_REQ_SMARTCARD := STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG HF_14ASNIFF LF_ICEHID ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index e5a3304a8..4b480ad3a 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -48,4 +48,8 @@ endif # WITH_STANDALONE_LF_EM4100RWC ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RWC,$(APP_CFLAGS))) SRC_STANDALONE = lf_em4100rwc.c -endif \ No newline at end of file +endif +# WITH_STANDALONE_HF_LEGIC +ifneq (,$(findstring WITH_STANDALONE_HF_LEGIC,$(APP_CFLAGS))) + SRC_STANDALONE = hf_legic.c +endif diff --git a/armsrc/Standalone/hf_legic.c b/armsrc/Standalone/hf_legic.c new file mode 100644 index 000000000..f4a395737 --- /dev/null +++ b/armsrc/Standalone/hf_legic.c @@ -0,0 +1,81 @@ +//----------------------------------------------------------------------------- +// Stefanie Hofmann, 2020 +// Uli Heilmeier, 2020 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// main code for Legic Prime read/sim +//----------------------------------------------------------------------------- +#include "standalone.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" + +#include "legicrf.h" +#include "legicrfsim.h" + +void ModInfo(void) { + DbpString(" HF Legic Prime standalone "); +} + +// Searching for Legic card until found and read. +// Simulating recorded Legic Prime card. +// C = Searching +// A, B, C = Reading +// A, D = Simulating + +void RunMod(){ + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + Dbprintf(">> HF Legic Prime Read/Simulate Started <<"); + + int read_success; + for(;;){ + WDT_HIT(); + + //exit from hf_legic, send usbcommand + if(data_available()) break; + + //Was our button held down or pressed? + int button_pressed = BUTTON_HELD(280); + if(button_pressed != BUTTON_HOLD) continue; + + LED_A_OFF(); + LED_B_OFF(); + LED_C_ON(); + LED_D_OFF(); + + WAIT_BUTTON_RELEASED(); + + //record + DbpString("[=] start recording"); + + //search for legic card until reading successfull or button pressed + do{ + LED_C_ON(); + SpinDelay(1000); + // We don't care if we read a MIM256, MIM512 or MIM1024 + // we just read 1024 bytes + LegicRfReader(0, 1024, 0x55); + read_success = check_success(); + }while(read_success == 0 && !BUTTON_PRESS()); + + //simulate if read successfully + if(read_success == 1){ + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_ON(); + // The read data is migrated to a MIM1024 card + LegicRfSimulate(2); + }else{ + LEDsoff(); + WAIT_BUTTON_RELEASED(); + } + } +} diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 0665705b6..78e6e19b4 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -28,6 +28,7 @@ static uint8_t *legic_mem; /* card memory, used for read, write */ static legic_card_select_t card;/* metadata of currently selected card */ static crc_t legic_crc; +int read_success = 0; //----------------------------------------------------------------------------- // Frame timing and pseudorandom number generator @@ -444,6 +445,7 @@ OUT: void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { // configure ARM and FPGA init_reader(false); + read_success = 0; // establish shared secret and detect card type uint8_t card_type = setup_phase(iv); @@ -467,6 +469,7 @@ void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { } // OK + read_success = 1; reply_old(CMD_ACK, 1, len, 0, legic_mem, len); OUT: @@ -512,3 +515,5 @@ OUT: switch_off(); StopTicks(); } + +int check_success(void){return read_success;} diff --git a/armsrc/legicrf.h b/armsrc/legicrf.h index 47a7f89d6..77233406d 100644 --- a/armsrc/legicrf.h +++ b/armsrc/legicrf.h @@ -17,5 +17,5 @@ void LegicRfInfo(void); void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data); - +int check_success(void); #endif /* __LEGICRF_H */ From efeff2d0f68e209597e8dae07c70b029cbdf156f Mon Sep 17 00:00:00 2001 From: Iceman Date: Sat, 28 Mar 2020 15:05:52 +0100 Subject: [PATCH 226/298] Update cheatsheet.md --- doc/cheatsheet.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index a3e0a220c..74a061b10 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -60,7 +60,7 @@ Dump iClass card contents ``` Options --- -k : *Access Key as 16 hex symbols or 1 hex to select key from memory +k : *Access Key as 16 hex symbols or 1 hex to select key from memory m3 --> hf iclass dump k 0 ``` @@ -69,8 +69,8 @@ Read iClass Block ``` Options --- -b : The block number as 2 hex symbols -k : Access Key as 16 hex symbols or 1 hex to select key from memory +b : The block number as 2 hex symbols +k : Access Key as 16 hex symbols or 1 hex to select key from memory pm3 --> hf iclass rdbl b 7 k 0 ``` @@ -79,9 +79,9 @@ Write to iClass Block ``` Options --- -b : The block number as 2 hex symbols +b : The block number as 2 hex symbols d : Set the Data to write as 16 hex symbols -k : Access Key as 16 hex symbols or 1 hex to select key from memory +k : Access Key as 16 hex symbols or 1 hex to select key from memory pm3 --> hf iclass wrbl b 07 d 6ce099fe7e614fd0 k 0 ``` @@ -102,7 +102,7 @@ Options n : specify the keyNbr to set in memory k : set a key in memory -pm3 --> hf iclass managekeys n 0 k AFA785A7DAB33378 +pm3 --> hf iclass managekeys n 3 k AFA785A7DAB33378 ``` Encrypt iClass Block @@ -124,9 +124,10 @@ Simulate iClass Options --- 0 simulate the given CSN -2 Runs part 1 of LOCLASS attack 1 simulate default CSN +2 Runs online part of LOCLASS attack 3 Full simulation using emulator memory (see 'hf iclass eload') +4 Runs online part of LOCLASS attack against reader in keyroll mode pm3 --> hf iclass sim 3 ``` @@ -149,7 +150,7 @@ Extract custom iClass key (loclass attack) Options --- f : specify a filename to clone from -k : Access Key as 16 hex symbols or 1 hex to select key from memory +k : Access Key as 16 hex symbols or 1 hex to select key from memory e : If 'e' is specified, elite computations applied to key pm3 --> hf iclass sim 2 From 9356549bc6592d391f72c6f623553ac912c4b75f Mon Sep 17 00:00:00 2001 From: Winds <60715874+Windslab@users.noreply.github.com> Date: Sat, 28 Mar 2020 18:23:05 +0300 Subject: [PATCH 227/298] textual Correcting a script name --- client/luascripts/{hf-writer.lua => hf_writer.lua} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename client/luascripts/{hf-writer.lua => hf_writer.lua} (100%) diff --git a/client/luascripts/hf-writer.lua b/client/luascripts/hf_writer.lua similarity index 100% rename from client/luascripts/hf-writer.lua rename to client/luascripts/hf_writer.lua From a79a11256a887e6c435bee8aa1b4dbffe35be700 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 29 Mar 2020 07:48:01 +0200 Subject: [PATCH 228/298] revert --- client/cliparser/argtable3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c index b8644dd86..3acbce48e 100644 --- a/client/cliparser/argtable3.c +++ b/client/cliparser/argtable3.c @@ -250,7 +250,7 @@ const char *optarg; /* argument associated with option */ #define BADARG ((*options == ':') ? (int)':' : (int)'?') #define INORDER (int)1 -#define EMSG " " +#define EMSG "" static int getopt_internal(int, char *const *, const char *, const struct option *, int *, int); From db02a1f3065583804ad1f8e404fd3c7ebd4dd946 Mon Sep 17 00:00:00 2001 From: Uli Heilmeier Date: Mon, 30 Mar 2020 10:22:45 +0200 Subject: [PATCH 229/298] HF_Legic: remove global variable and cleanup As requested by @iceman1001: * removed global variable * updated according to make style * added entry in CHANGELOG.md --- CHANGELOG.md | 1 + armsrc/Standalone/hf_legic.c | 81 ++++++++++++++++++------------------ armsrc/legicrf.c | 8 ++-- armsrc/legicrf.h | 3 +- 4 files changed, 45 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6192b8068..3032b04fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added `HF_LEGIC` standalone mode to read and simulate a Legic prime tag (@Pizza_4u) - Added keri MS decode/encode and update 'lf keri clone' to support MS fc/cid cloning. (@mwalker33) - Fix 'hf mfdes enum' - now actually manages to enumerate files under all AID's. :smiley: (@iceman1001) - Fix 'hf mfdes info' - now detects DESFire light and work properly Wrapped commands :+1: (@iceman1001) diff --git a/armsrc/Standalone/hf_legic.c b/armsrc/Standalone/hf_legic.c index f4a395737..1e7aa7114 100644 --- a/armsrc/Standalone/hf_legic.c +++ b/armsrc/Standalone/hf_legic.c @@ -20,7 +20,7 @@ #include "legicrfsim.h" void ModInfo(void) { - DbpString(" HF Legic Prime standalone "); + DbpString(" HF Legic Prime standalone "); } // Searching for Legic card until found and read. @@ -29,53 +29,52 @@ void ModInfo(void) { // A, B, C = Reading // A, D = Simulating -void RunMod(){ - StandAloneMode(); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - Dbprintf(">> HF Legic Prime Read/Simulate Started <<"); +void RunMod() { + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + Dbprintf(">> HF Legic Prime Read/Simulate Started <<"); - int read_success; - for(;;){ - WDT_HIT(); + int read_success; + for (;;) { + WDT_HIT(); - //exit from hf_legic, send usbcommand - if(data_available()) break; + //exit from hf_legic, send usbcommand + if (data_available()) break; - //Was our button held down or pressed? - int button_pressed = BUTTON_HELD(280); - if(button_pressed != BUTTON_HOLD) continue; + //Was our button held down or pressed? + int button_pressed = BUTTON_HELD(280); + if (button_pressed != BUTTON_HOLD) continue; - LED_A_OFF(); - LED_B_OFF(); - LED_C_ON(); - LED_D_OFF(); + LED_A_OFF(); + LED_B_OFF(); + LED_C_ON(); + LED_D_OFF(); - WAIT_BUTTON_RELEASED(); + WAIT_BUTTON_RELEASED(); - //record - DbpString("[=] start recording"); + //record + DbpString("[=] start recording"); - //search for legic card until reading successfull or button pressed - do{ - LED_C_ON(); - SpinDelay(1000); - // We don't care if we read a MIM256, MIM512 or MIM1024 - // we just read 1024 bytes - LegicRfReader(0, 1024, 0x55); - read_success = check_success(); - }while(read_success == 0 && !BUTTON_PRESS()); + //search for legic card until reading successfull or button pressed + do { + LED_C_ON(); + SpinDelay(1000); + // We don't care if we read a MIM256, MIM512 or MIM1024 + // we just read 1024 bytes + read_success = LegicRfReader(0, 1024, 0x55); + } while (read_success == 0 && !BUTTON_PRESS()); - //simulate if read successfully - if(read_success == 1){ - LED_A_OFF(); - LED_B_OFF(); - LED_C_OFF(); - LED_D_ON(); - // The read data is migrated to a MIM1024 card - LegicRfSimulate(2); - }else{ - LEDsoff(); - WAIT_BUTTON_RELEASED(); + //simulate if read successfully + if (read_success == 1) { + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_ON(); + // The read data is migrated to a MIM1024 card + LegicRfSimulate(2); + } else { + LEDsoff(); + WAIT_BUTTON_RELEASED(); + } } - } } diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 78e6e19b4..313b38fc5 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -28,7 +28,6 @@ static uint8_t *legic_mem; /* card memory, used for read, write */ static legic_card_select_t card;/* metadata of currently selected card */ static crc_t legic_crc; -int read_success = 0; //----------------------------------------------------------------------------- // Frame timing and pseudorandom number generator @@ -442,10 +441,10 @@ OUT: StopTicks(); } -void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { +int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { + int read_success = 0; // configure ARM and FPGA init_reader(false); - read_success = 0; // establish shared secret and detect card type uint8_t card_type = setup_phase(iv); @@ -475,6 +474,7 @@ void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { OUT: switch_off(); StopTicks(); + return read_success; } void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) { @@ -515,5 +515,3 @@ OUT: switch_off(); StopTicks(); } - -int check_success(void){return read_success;} diff --git a/armsrc/legicrf.h b/armsrc/legicrf.h index 77233406d..6e59f4ca7 100644 --- a/armsrc/legicrf.h +++ b/armsrc/legicrf.h @@ -15,7 +15,6 @@ #include "common.h" void LegicRfInfo(void); -void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); +int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data); -int check_success(void); #endif /* __LEGICRF_H */ From 0733310300dcb80f79e0ae0c99b3fd8865ece616 Mon Sep 17 00:00:00 2001 From: Uli Heilmeier Date: Mon, 30 Mar 2020 11:03:43 +0200 Subject: [PATCH 230/298] Makefile: target checks for macOS recode is missing on macOS by default. grep on macOS is BSD grep by default. --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index 783b5fa27..5c7947fc5 100644 --- a/Makefile +++ b/Makefile @@ -210,13 +210,20 @@ style: # Detecting weird codepages and tabs. checks: + # Make sure recode is installed + @which recode >/dev/null || ( echo "Please install 'recode' package first" ; exit 1 ) @echo "Files with suspicious chars:" @find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" -or -name "*.v" \) \ -exec sh -c "cat {} |recode utf8.. >/dev/null || echo {}" \; @echo "Files with tabs:" # to remove tabs within lines, one can try with: vi $file -c ':set tabstop=4' -c ':set et|retab' -c ':wq' +ifeq ($(platform),Darwin) + @find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \ + -exec egrep -l '\t' {} \; +else @find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \ -exec grep -lP '\t' {} \; +endif # @echo "Files with printf \\\\t:" # @find . \( -name "*.[ch]" -or \( -name "*.cpp" -and -not -name "*.moc.cpp" \) -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "*.md" -or -name "*.txt" -or -name "*.awk" -or -name "*.v" \) \ # -exec grep -lP '\\t' {} \; From c8b51ccf255166537c640272201c6df73aab9e8c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Mar 2020 15:11:48 +0200 Subject: [PATCH 231/298] chg: legic standalone - now saves read cards to flashmemory (RDV4)\n also simulates correct cardtype.\n It goes direct into recording / reading a tag. Once a complete dump is done, it starts to simulate --- armsrc/Standalone/hf_legic.c | 147 ++++++++++++++++++++++++++++------- armsrc/legicrf.c | 51 +++++++++++- armsrc/legicrf.h | 7 +- armsrc/legicrfsim.c | 6 +- 4 files changed, 176 insertions(+), 35 deletions(-) diff --git a/armsrc/Standalone/hf_legic.c b/armsrc/Standalone/hf_legic.c index 1e7aa7114..2b826528f 100644 --- a/armsrc/Standalone/hf_legic.c +++ b/armsrc/Standalone/hf_legic.c @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- -// Stefanie Hofmann, 2020 -// Uli Heilmeier, 2020 +// (c) Stefanie Hofmann, 2020 +// (c) Uli Heilmeier, 2020 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -8,19 +8,89 @@ //----------------------------------------------------------------------------- // main code for Legic Prime read/sim //----------------------------------------------------------------------------- + #include "standalone.h" #include "proxmark3_arm.h" +#include "BigBuf.h" #include "appmain.h" #include "fpgaloader.h" #include "util.h" #include "dbprint.h" #include "ticks.h" - #include "legicrf.h" #include "legicrfsim.h" +#include "legic.h" // legic_card_select_t struct +#include "spiffs.h" // flashmem + + +/* + * To list all dump files from flash: + * + * 1. mem spiffs tree + * + * + * To retrieve dump files from flash: + * + * 1. mem spiffs dump o hf-legic-XXYYZZWW-dump.bin f hf-legic-XXYYZZWW-dump.bin + * Copies log file from flash to your client. + * + * + * This module emits debug strings during normal operation -- so try it out in + * the lab connected to PM3 client before taking it into the field. + * + * To delete a dump file from flash: + * + * 1. mem spiffs remove hf-legic-XXYYZZWW-dump.bin + * +*/ + +void DownloadLogInstructions() { + Dbprintf(""); + Dbprintf("[=] List all dumps from flash:"); + Dbprintf("[=] " _YELLOW_("-") "mem spiffs tree"); + Dbprintf(""); + Dbprintf("[=] To save a dump file from flash to client:"); + Dbprintf("[=] " _YELLOW_("-") "mem spiffs dump o hf-legic-UID-dump.bin f hf-legic-UID-dump.bin"); +} + +void save_dump_to_file(legic_card_select_t *p_card) { + +#ifdef WITH_FLASH + + // legic functions puts it memory in Emulator reserved memory. + uint8_t *mem = BigBuf_get_EM_addr(); + + char *preferredName = (char*)BigBuf_malloc(30); + if (preferredName == NULL) { + goto OUT; + } + + sprintf(preferredName, "hf-legic-%02X%02X%02X%02X-dump", p_card->uid[0], p_card->uid[1], p_card->uid[2], p_card->uid[3]); + uint16_t preferredNameLen = strlen(preferredName); + + char *filename = (char*)BigBuf_malloc(preferredNameLen + 4 + 1 + 10); + if (filename == NULL) { + goto OUT; + } + + sprintf(filename, "%.*s%s", preferredNameLen, preferredName, ".bin"); + uint16_t num = 1; + while (exists_in_spiffs(filename)) { + sprintf(filename, "%.*s-%d%s", preferredNameLen, preferredName, num, ".bin"); + num++; + } + + rdv40_spiffs_write(filename, mem, p_card->cardsize, RDV40_SPIFFS_SAFETY_SAFE); + + Dbprintf("[=] saved card dump to flashmem::" _YELLOW_("%s"), filename); +OUT: + BigBuf_free_keep_EM(); +#endif + +} void ModInfo(void) { - DbpString(" HF Legic Prime standalone "); + DbpString(" HF Legic Prime standalone"); } // Searching for Legic card until found and read. @@ -32,49 +102,72 @@ void ModInfo(void) { void RunMod() { StandAloneMode(); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - Dbprintf(">> HF Legic Prime Read/Simulate Started <<"); - - int read_success; + Dbprintf("[=] >> HF Legic Prime Read/Simulate Started <<"); + DbpString("[=] press and HOLD button to exit standalone mode"); for (;;) { WDT_HIT(); - + //exit from hf_legic, send usbcommand if (data_available()) break; //Was our button held down or pressed? int button_pressed = BUTTON_HELD(280); - if (button_pressed != BUTTON_HOLD) continue; + if (button_pressed == BUTTON_HOLD) { + break; + } - LED_A_OFF(); - LED_B_OFF(); + LEDsoff(); LED_C_ON(); - LED_D_OFF(); - WAIT_BUTTON_RELEASED(); - - //record - DbpString("[=] start recording"); + DbpString("[=] looking for tags"); + int read_success = PM3_ESOFT; //search for legic card until reading successfull or button pressed do { LED_C_ON(); - SpinDelay(1000); + SpinDelay(500); // We don't care if we read a MIM256, MIM512 or MIM1024 // we just read 1024 bytes - read_success = LegicRfReader(0, 1024, 0x55); - } while (read_success == 0 && !BUTTON_PRESS()); + read_success = LegicRfReaderEx(0, 1024, 0x55); + + } while (read_success == PM3_ESOFT && !BUTTON_PRESS()); + + LEDsoff(); //simulate if read successfully - if (read_success == 1) { - LED_A_OFF(); - LED_B_OFF(); - LED_C_OFF(); + if (read_success != PM3_ESOFT) { + + legic_card_select_t *p_card; + p_card = getLegicCardInfo(); + if (p_card->cardsize == 0) + continue; + + save_dump_to_file(p_card); + LED_D_ON(); + uint8_t ct; + switch(p_card->tagtype) { + case 0x0D: + ct = 0; + break; + case 0x1D: + ct = 1; + break; + case 0x3D: + ct = 2; + break; + default: + continue; + } + // The read data is migrated to a MIM1024 card - LegicRfSimulate(2); - } else { - LEDsoff(); - WAIT_BUTTON_RELEASED(); + LegicRfSimulate(ct); } } + + LEDsoff(); +#ifdef WITH_FLASH + DownloadLogInstructions(); +#endif + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); } diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 313b38fc5..35b638298 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -404,6 +404,10 @@ bool write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz) { // // Only this functions are public / called from appmain.c //----------------------------------------------------------------------------- +legic_card_select_t* getLegicCardInfo(void) { + return &card; +} + void LegicRfInfo(void) { // configure ARM and FPGA init_reader(false); @@ -441,8 +445,45 @@ OUT: StopTicks(); } -int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { - int read_success = 0; +int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv) { + + int res = PM3_SUCCESS; + + // configure ARM and FPGA + init_reader(false); + + // establish shared secret and detect card type + uint8_t card_type = setup_phase(iv); + if (init_card(card_type, &card) != 0) { + res = PM3_ESOFT; + goto OUT; + } + + // do not read beyond card memory + if (len + offset > card.cardsize) { + len = card.cardsize - offset; + } + + for (uint16_t i = 0; i < len; ++i) { + int16_t byte = read_byte(offset + i, card.cmdsize); + if (byte == -1) { + res = PM3_EOVFLOW; + goto OUT; + } + legic_mem[i] = byte; + + if (i < 4) { + card.uid[i] = byte; + } + } + +OUT: + switch_off(); + StopTicks(); + return res; +} + +void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { // configure ARM and FPGA init_reader(false); @@ -465,16 +506,18 @@ int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { goto OUT; } legic_mem[i] = byte; + + if (i < 4) { + card.uid[i] = byte; + } } // OK - read_success = 1; reply_old(CMD_ACK, 1, len, 0, legic_mem, len); OUT: switch_off(); StopTicks(); - return read_success; } void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) { diff --git a/armsrc/legicrf.h b/armsrc/legicrf.h index 6e59f4ca7..ae4c78cdc 100644 --- a/armsrc/legicrf.h +++ b/armsrc/legicrf.h @@ -1,6 +1,7 @@ //----------------------------------------------------------------------------- // (c) 2009 Henryk Plötz // 2018 AntiCat +// 2020 iceman // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -13,8 +14,12 @@ #define __LEGICRF_H #include "common.h" +#include "legic.h" /* legic_card_select_t struct */ void LegicRfInfo(void); -int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); +int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv); +void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data); + +legic_card_select_t* getLegicCardInfo(void); #endif /* __LEGICRF_H */ diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index 34f8458ce..bbec86fa5 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -460,12 +460,12 @@ void LegicRfSimulate(uint8_t cardtype) { // verify command line input if (init_card(cardtype, &card) != 0) { - DbpString("Unknown tagtype."); + DbpString("[!] Unknown tagtype."); goto OUT; } LED_A_ON(); - DbpString("Starting Legic emulator, press button to end"); + DbpString("[=] Starting Legic emulator, press " _YELLOW_("button") "to end"); while (!BUTTON_PRESS() && !data_available()) { WDT_HIT(); @@ -486,7 +486,7 @@ void LegicRfSimulate(uint8_t cardtype) { } OUT: - DbpString("Stopped"); + DbpString("[=] Sim stopped"); switch_off(); StopTicks(); } From 924ad84c59d90f6685a26c3faea665c04db68995 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Mar 2020 15:12:06 +0200 Subject: [PATCH 232/298] textual --- armsrc/Standalone/lf_icehid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index 34d4439a0..33d4ed764 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -37,7 +37,7 @@ * To retrieve log file from flash: * * 1. mem spiffs dump o lf_hidcollect.log f lf_hidcollect.log - * Copies log file from flash to your PC. + * Copies log file from flash to your client. * * 2. exit the Proxmark3 client * From 83a5ffbb1084f010ce60b96294c25ebf37220877 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Mar 2020 15:12:37 +0200 Subject: [PATCH 233/298] textual --- armsrc/Standalone/lf_em4100rwc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/armsrc/Standalone/lf_em4100rwc.c b/armsrc/Standalone/lf_em4100rwc.c index a2414a6fa..02366d0a6 100644 --- a/armsrc/Standalone/lf_em4100rwc.c +++ b/armsrc/Standalone/lf_em4100rwc.c @@ -121,6 +121,8 @@ void SaveIDtoFlash(int addr, uint64_t id) { void RunMod() { StandAloneMode(); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + Dbprintf("[=] >> LF EM4100 read/write/clone started <<"); + int selected = 0; //state 0 - select slot // 1 - read tag to selected slot, From 690a2b89e08779ee97095d7b85372769be6b2044 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Mar 2020 15:16:11 +0200 Subject: [PATCH 234/298] textual --- armsrc/Standalone/lf_em4100emul.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/armsrc/Standalone/lf_em4100emul.c b/armsrc/Standalone/lf_em4100emul.c index f3939f923..7b38133bc 100644 --- a/armsrc/Standalone/lf_em4100emul.c +++ b/armsrc/Standalone/lf_em4100emul.c @@ -82,6 +82,8 @@ void LED_Slot(int i) { void RunMod() { StandAloneMode(); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + Dbprintf("[=] >> LF EM4100 simulator started <<"); + int selected = 0; //selected slot after start slots_count = sizeof(low) / sizeof(low[0]); bba = BigBuf_get_addr(); From 41780175366c08ff50b4381de4cfb1a5dd4892e1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Mar 2020 15:18:25 +0200 Subject: [PATCH 235/298] chg: hf legic dump - change filename template --- client/cmdhflegic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 022857584..2060b64e2 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -948,7 +948,7 @@ static int CmdLegicDump(const char *Cmd) { // user supplied filename? if (fileNlen < 1) - sprintf(fnameptr, "%02X%02X%02X%02X.bin", data[0], data[1], data[2], data[3]); + sprintf(fnameptr, "hf-legic-%02X%02X%02X%02X-dump.bin", data[0], data[1], data[2], data[3]); else sprintf(fnameptr + fileNlen, ".bin"); From 9ca14acf5e858a323178912cc27c3db5c97b82a3 Mon Sep 17 00:00:00 2001 From: Iceman Date: Mon, 30 Mar 2020 15:27:32 +0200 Subject: [PATCH 236/298] Update Mac-OS-X-Homebrew-Installation-Instructions.md --- .../Mac-OS-X-Homebrew-Installation-Instructions.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md index 6ce8b5990..367452454 100644 --- a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md @@ -85,6 +85,12 @@ These instructions will show how to setup the environment on OSX to the point wh brew install readline qt5 pkgconfig brew install RfidResearchGroup/proxmark3/arm-none-eabi-gcc ``` +3. (optional) Install makefile dependencies: +``` +brew install recode +brew install astyle +``` + ## Compile and use the project From 4920bd8ab055f07b8c035167018c83d0f4e90351 Mon Sep 17 00:00:00 2001 From: Iceman Date: Mon, 30 Mar 2020 16:31:54 +0200 Subject: [PATCH 237/298] Update Makefile.hal --- armsrc/Standalone/Makefile.hal | 3 +++ 1 file changed, 3 insertions(+) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index bd018e15b..e3ad8accb 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -47,6 +47,9 @@ define KNOWN_STANDALONE_DEFINITIONS | LF_EM4100RWC | Read/simulate em4100 tags & clone it | | | to T555x tags | +----------------------------------------------------------+ +| HF_LEGIC | Read/simulate Legic Prime tags | +| | storing in flashmem | ++----------------------------------------------------------+ endef STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_ICEHID LF_EM4100EMUL LF_EM4100RWC From 09d96888006b633fc2bd2df7ba797c3ffa332eb3 Mon Sep 17 00:00:00 2001 From: Iceman Date: Mon, 30 Mar 2020 16:36:05 +0200 Subject: [PATCH 238/298] Update 4_Advanced-compilation-parameters.md --- doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index 01b7d083a..561cae95d 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -82,6 +82,9 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo | HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth storing in flashmem - Bogito | HF_14ASNIFF | 14a sniff storing to flashmem - Micolous | LF_ICEHID | LF HID collector to flashmem - Iceman +| LF_EM4100EMUL | LF EM4100 simulator standalone mode - temskiy +| LF_EM4100RWC | LF EM4100 read/write/clone mode - temskiy +| HF_LEGIC | HF Legic Prime standalone - uhei By default `STANDALONE=LF_SAMYRUN`. From 8eef5d188c30a5c70fe3af87cc96fe8d1f8e54f2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Mar 2020 22:25:00 +0200 Subject: [PATCH 239/298] fix coverity 226432 --- client/emv/cmdemv.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index e3c88c3e3..baef18d04 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -662,10 +662,7 @@ static void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, } //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4 - const char *qVSDC = "\x26\x00\x00\x00"; - if (GenACGPO) { - qVSDC = "\x26\x80\x00\x00"; - } + switch (TrType) { case TT_MSD: TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD @@ -675,10 +672,20 @@ static void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC break; case TT_QVSDCMCHIP: - TLV_ADD(0x9F66, qVSDC); // qVSDC + // qVSDC + if (GenACGPO) { + TLV_ADD(0x9F66, "\x26\x80\x00\x00"); + } else { + TLV_ADD(0x9F66, "\x26\x00\x00\x00"); + } break; case TT_CDA: - TLV_ADD(0x9F66, qVSDC); // qVSDC (VISA CDA not enabled) + // qVSDC (VISA CDA not enabled) + if (GenACGPO) { + TLV_ADD(0x9F66, "\x26\x80\x00\x00"); + } else { + TLV_ADD(0x9F66, "\x26\x00\x00\x00"); + } break; default: break; From 978dde98a976bac379b98aa21af31664da57ee52 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Mar 2020 08:06:45 +0200 Subject: [PATCH 240/298] added more sigs --- client/mifare/ndef.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 392a550af..e359e03fa 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -32,16 +32,24 @@ static const char *TypeNameFormat_s[] = { static const char *ndefSigType_s[] = { "Not present", // No signature present - "RSASSA_PSS_SHA_1", // PKCS_1 - "RSASSA_PKCS1_v1_5_WITH_SHA_1", // PKCS_1 - "DSA", - "ECDSA", + "RSASSA_PSS_SHA_1 (1024)", // PKCS_1 + "RSASSA_PKCS1_v1_5_WITH_SHA_1 (1024)", // PKCS_1 + "DSA-1024", + "ECDSA-P192", + "RSASSA-PSS-2048", + "RSASSA-PKCS1-v1_5-2048", + "DSA-2048", + "ECDSA-P224", + "ECDSA-K233", + "ECDSA-B233", + "ECDSA-P256", "n/a" + }; static const char *ndefCertificateFormat_s[] = { "X_509", - "X9_68", + "X9_68 (M2M)", "n/a" }; From e13a25902fcb50fc7fb6e0344addde1c497981f0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Mar 2020 08:11:27 +0200 Subject: [PATCH 241/298] added more sigs --- client/mifare/ndef.c | 2 +- client/mifare/ndef.h | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index e359e03fa..df8264330 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -177,7 +177,7 @@ static int ndefDecodeSig(uint8_t *sig, size_t siglen) { size_t intsiglen = (sig[indx + 1] << 8) + sig[indx + 2]; // ecdsa 0x04 - if (sigType == stECDSA) { + if (sigType == stECDSA_P192) { indx += 3; PrintAndLogEx(NORMAL, "\tsignature [%zu]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); diff --git a/client/mifare/ndef.h b/client/mifare/ndef.h index 7d9ca2fbf..71afda2ee 100644 --- a/client/mifare/ndef.h +++ b/client/mifare/ndef.h @@ -24,12 +24,19 @@ typedef enum { } TypeNameFormat_t; typedef enum { - stNotPresent = 0x00, - stRSASSA_PSS_SHA_1 = 0x01, + stNotPresent = 0x00, + stRSASSA_PSS_SHA_1 = 0x01, stRSASSA_PKCS1_v1_5_WITH_SHA_1 = 0x02, - stDSA = 0x03, - stECDSA = 0x04, - stNA = 0x05 + stDSA_1024 = 0x03, + stECDSA_P192 = 0x04, + stRSASSA_PSS_2048 = 0x05, + stRSASSA_PKCS1_v1_5_2048 = 0x06, + stDSA_2048 = 0x07, + stECDSA_P224 = 0x08, + stECDSA_K233 = 0x09, + stECDSA_B233 = 0x0a, + stECDSA_P256 = 0x0b, + stNA = 0x0c } ndefSigType_t; typedef enum { From 392da6400ae1d3e9882919d3193d47f723a16f3d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Mar 2020 09:44:36 +0200 Subject: [PATCH 242/298] chg: waiting for shiftregisters (@pwpiwi) --- common_arm/usb_cdc.c | 82 ++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/common_arm/usb_cdc.c b/common_arm/usb_cdc.c index b146715a1..ca2c1986a 100644 --- a/common_arm/usb_cdc.c +++ b/common_arm/usb_cdc.c @@ -289,7 +289,7 @@ static const char CompatIDFeatureDescriptor[] = { MS_EXTENDED_COMPAT_ID, 0x00, // Compatibility ID Descriptor Index 0x0004 0x01, // Number of sections. 0x1 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved (7bytes) - //-----function section 1------ + // -----function section 1------ 0x00, // Interface Number #0 0x01, // reserved (0x1) 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, // Compatible ID ('WINUSB\0\0') (8bytes) @@ -310,7 +310,7 @@ static const char OSprop[] = { // u16 wCount -- three section 3, 0, - //-----property section 1------ + // -----property section 1------ // u32 size ( 14+40+78 == 132) 132, 0, 0, 0, // u32 type @@ -326,7 +326,7 @@ static const char OSprop[] = { '-',0,'1',0,'1',0,'c',0,'e',0,'-',0,'b',0,'f',0,'c',0,'1',0,'-',0,'0',0,'8',0,'0',0, '0',0,'2',0,'b',0,'e',0,'1',0,'0',0,'3',0,'1',0,'8',0,'}',0,0,0, - //-----property section 2------ + // -----property section 2------ // u32 size ( 14+12+38 == 64) 64, 0, 0, 0, // u32 type @@ -340,7 +340,7 @@ static const char OSprop[] = { // data 'Awesome PM3 Device' 'A',0,'w',0,'e',0,'s',0,'o',0,'m',0,'e',0,' ',0,'P',0,'M',0,'3',0,' ',0,'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,0,0, - //-----property section 3------ + // -----property section 3------ // u32 size ( 14+12+76 == 102) 102, 0, 0, 0, // u32 type @@ -473,10 +473,12 @@ static void SpinDelayUs(int us) { } } -//*---------------------------------------------------------------------------- -//* \fn usb_disable -//* \brief This function deactivates the USB device -//*---------------------------------------------------------------------------- +/* + *---------------------------------------------------------------------------- + * \fn usb_disable + * \brief This function deactivates the USB device + *---------------------------------------------------------------------------- +*/ void usb_disable() { // Disconnect the USB device AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU; @@ -487,10 +489,12 @@ void usb_disable() { } } -//*---------------------------------------------------------------------------- -//* \fn usb_enable -//* \brief This function Activates the USB device -//*---------------------------------------------------------------------------- +/* + *---------------------------------------------------------------------------- + * \fn usb_enable + * \brief This function Activates the USB device + *---------------------------------------------------------------------------- +*/ void usb_enable() { // Set the PLL USB Divider AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ; @@ -523,10 +527,12 @@ void usb_enable() { AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; } -//*---------------------------------------------------------------------------- -//* \fn usb_check -//* \brief Test if the device is configured and handle enumeration -//*---------------------------------------------------------------------------- +/* + *---------------------------------------------------------------------------- + * \fn usb_check + * \brief Test if the device is configured and handle enumeration + *---------------------------------------------------------------------------- +*/ static int usb_reconnect = 0; static int usb_configured = 0; void SetUSBreconnect(int value) { @@ -612,10 +618,12 @@ bool usb_poll_validate_length() { return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0; } -//*---------------------------------------------------------------------------- -//* \fn usb_read -//* \brief Read available data from Endpoint 1 OUT (host to device) -//*---------------------------------------------------------------------------- +/* + *---------------------------------------------------------------------------- + * \fn usb_read + * \brief Read available data from Endpoint 1 OUT (host to device) + *---------------------------------------------------------------------------- +*/ uint32_t usb_read(uint8_t *data, size_t len) { if (len == 0) return 0; @@ -709,10 +717,12 @@ uint32_t usb_read_ng(uint8_t *data, size_t len) { return nbBytesRcv; } -//*---------------------------------------------------------------------------- -//* \fn usb_write -//* \brief Send through endpoint 2 (device to host) -//*---------------------------------------------------------------------------- +/* + *---------------------------------------------------------------------------- + * \fn usb_write + * \brief Send through endpoint 2 (device to host) + *---------------------------------------------------------------------------- +*/ int usb_write(const uint8_t *data, const size_t len) { if (!len) return PM3_EINVARG; @@ -733,6 +743,7 @@ int usb_write(const uint8_t *data, const size_t len) { } UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {}; while (length) { // Send next chunk @@ -750,8 +761,9 @@ int usb_write(const uint8_t *data, const size_t len) { UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {}; - UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {}; } // Wait for the end of transfer @@ -762,13 +774,25 @@ int usb_write(const uint8_t *data, const size_t len) { UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {}; + + if (len % AT91C_EP_IN_SIZE == 0) { + + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {}; + + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {}; + } + return PM3_SUCCESS; } -//*---------------------------------------------------------------------------- -//* \fn AT91F_USB_SendData -//* \brief Send Data through the control endpoint -//*---------------------------------------------------------------------------- +/* + *---------------------------------------------------------------------------- + * \fn AT91F_USB_SendData + * \brief Send Data through the control endpoint + *---------------------------------------------------------------------------- +*/ void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) { AT91_REG csr; From 6eb36c54386ec3fd8c90334855ea2ca038549ff4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Mar 2020 15:33:07 +0200 Subject: [PATCH 243/298] added new command 'data ndef' - for easy decoding of NDEF messages inside pm3 client --- client/cmddata.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/client/cmddata.c b/client/cmddata.c index 14f8ac259..af82e7a4b 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -26,6 +26,8 @@ #include "loclass/cipherutils.h" // for decimating samples in getsamples #include "cmdlfem4x.h" // askem410xdecode #include "fileutils.h" // searchFile +#include "mifare/ndef.h" +#include "cliparser/cliparser.h" uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; size_t DemodBufferLen = 0; @@ -2289,6 +2291,35 @@ static int CmdDataIIR(const char *Cmd) { return PM3_SUCCESS; } +static int CmdDataNDEF(const char *Cmd) { + +#ifndef MAX_NDEF_LEN +#define MAX_NDEF_LEN 2048 +#endif + + CLIParserInit("data ndef", + "Prints NFC Data Exchange Format (NDEF)", + "Usage:\n\tdata ndef -d 9101085402656e48656c6c6f5101085402656e576f726c64\n"); + + void *argtable[] = { + arg_param_begin, + arg_strx0("dD", "data", "", "NDEF data to decode"), + arg_param_end + }; + CLIExecWithReturn(Cmd, argtable, true); + + int datalen = 0; + uint8_t data[MAX_NDEF_LEN] = {0}; + CLIGetHexWithReturn(1, data, &datalen); + + CLIParserFree(); + + PrintAndLogEx(NORMAL, "ice: %s", sprint_hex(data, datalen)); + + NDEFDecodeAndPrint(data, datalen, true); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"askedgedetect", CmdAskEdgeDetect, AlwaysAvailable, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"}, @@ -2327,6 +2358,7 @@ static command_t CommandTable[] = { {"undec", CmdUndec, AlwaysAvailable, "Un-decimate samples by 2"}, {"zerocrossings", CmdZerocrossings, AlwaysAvailable, "Count time between zero-crossings"}, {"iir", CmdDataIIR, AlwaysAvailable, "apply IIR buttersworth filter on plotdata"}, + {"ndef", CmdDataNDEF, AlwaysAvailable, "Decode NDEF records"}, {NULL, NULL, NULL, NULL} }; From 160f150dce50bb17e687c7b285daadb0a7ce4def Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Mar 2020 15:47:33 +0200 Subject: [PATCH 244/298] fixing NDEF --- client/cmddata.c | 20 ++++++++------------ client/mifare/ndef.c | 38 +++++++++++++++++++------------------- client/mifare/ndef.h | 1 + 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index af82e7a4b..52d3df314 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -10,22 +10,20 @@ // Data and Graph commands //----------------------------------------------------------------------------- #include "cmddata.h" - #include #include #include // for CmdNorm INT_MIN && INT_MAX #include // pow #include // tolower - -#include "commonutil.h" // ARRAYLEN -#include "cmdparser.h" // for command_t -#include "ui.h" // for show graph controls -#include "graph.h" // for graph data +#include "commonutil.h" // ARRAYLEN +#include "cmdparser.h" // for command_t +#include "ui.h" // for show graph controls +#include "graph.h" // for graph data #include "comms.h" -#include "lfdemod.h" // for demod code +#include "lfdemod.h" // for demod code #include "loclass/cipherutils.h" // for decimating samples in getsamples -#include "cmdlfem4x.h" // askem410xdecode -#include "fileutils.h" // searchFile +#include "cmdlfem4x.h" // askem410xdecode +#include "fileutils.h" // searchFile #include "mifare/ndef.h" #include "cliparser/cliparser.h" @@ -2314,9 +2312,7 @@ static int CmdDataNDEF(const char *Cmd) { CLIParserFree(); - PrintAndLogEx(NORMAL, "ice: %s", sprint_hex(data, datalen)); - - NDEFDecodeAndPrint(data, datalen, true); + NDEFRecordsDecodeAndPrint(data, datalen); return PM3_SUCCESS; } diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index df8264330..844c7ccd0 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -16,6 +16,7 @@ #include "util.h" // sprint_hex... #include "emv/dump.h" #include "crypto/asn1utils.h" +#include "pm3_cmd.h" #define STRBOOL(p) ((p) ? "+" : "-") @@ -118,7 +119,7 @@ static int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) header->TypeNameFormat = data[0] & 0x07; header->len = 1 + 1 + (header->ShortRecordBit ? 1 : 4) + (header->IDLenPresent ? 1 : 0); // header + typelen + payloadlen + idlen if (header->len > datalen) - return 1; + return PM3_ESOFT; header->TypeLen = data[1]; header->Type = data + header->len; @@ -138,7 +139,7 @@ static int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) if (header->RecLen > datalen) return 3; - return 0; + return PM3_SUCCESS; } static int ndefPrintHeader(NDEFHeader_t *header) { @@ -156,8 +157,7 @@ static int ndefPrintHeader(NDEFHeader_t *header) { PrintAndLogEx(NORMAL, "\tPayload length : %zu", header->PayloadLen); PrintAndLogEx(NORMAL, "\tID length : %zu", header->IDLen); PrintAndLogEx(NORMAL, "\tRecord length : %zu", header->RecLen); - - return 0; + return PM3_SUCCESS; } static int ndefDecodeSig(uint8_t *sig, size_t siglen) { @@ -165,7 +165,7 @@ static int ndefDecodeSig(uint8_t *sig, size_t siglen) { PrintAndLogEx(NORMAL, "\tsignature version: 0x%02x", sig[0]); if (sig[0] != 0x01) { PrintAndLogEx(ERR, "signature version unknown."); - return 1; + return PM3_ESOFT; } indx++; @@ -222,7 +222,7 @@ static int ndefDecodeSig(uint8_t *sig, size_t siglen) { PrintAndLogEx(NORMAL, "\tcertificate uri [%zu]: %.*s", inturilen, (int)inturilen, &sig[indx]); } - return 0; + return PM3_SUCCESS; }; static int ndefDecodePayload(NDEFHeader_t *ndef) { @@ -262,13 +262,13 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) { case tnfUnknownRecord: break; } - return 0; + return PM3_SUCCESS; } static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { NDEFHeader_t NDEFHeader = {0}; int res = ndefDecodeHeader(ndefRecord, ndefRecordLen, &NDEFHeader); - if (res) + if (res != PM3_SUCCESS) return res; ndefPrintHeader(&NDEFHeader); @@ -288,30 +288,30 @@ static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { ndefDecodePayload(&NDEFHeader); } - return 0; + return PM3_SUCCESS; } -static int ndefRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { +int NDEFRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { bool firstRec = true; size_t len = 0; while (len < ndefRecordLen) { NDEFHeader_t NDEFHeader = {0}; int res = ndefDecodeHeader(&ndefRecord[len], ndefRecordLen - len, &NDEFHeader); - if (res) + if (res != PM3_SUCCESS) return res; if (firstRec) { if (!NDEFHeader.MessageBegin) { PrintAndLogEx(ERR, "NDEF first record have MessageBegin=false!"); - return 1; + return PM3_ESOFT; } firstRec = false; } if (NDEFHeader.MessageEnd && len + NDEFHeader.RecLen != ndefRecordLen) { PrintAndLogEx(ERR, "NDEF records have wrong length. Must be %zu, calculated %zu", ndefRecordLen, len + NDEFHeader.RecLen); - return 1; + return PM3_ESOFT; } ndefRecordDecodeAndPrint(&ndefRecord[len], NDEFHeader.RecLen); @@ -322,7 +322,7 @@ static int ndefRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) break; } - return 0; + return PM3_SUCCESS; } int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { @@ -346,8 +346,8 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); PrintAndLogEx(INFO, "-- NDEF message. len: %d", len); - int res = ndefRecordsDecodeAndPrint(&ndef[indx], len); - if (res) + int res = NDEFRecordsDecodeAndPrint(&ndef[indx], len); + if (res != PM3_SUCCESS) return res; indx += len; @@ -362,13 +362,13 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { } case 0xfe: { PrintAndLogEx(INFO, "-- NDEF Terminator. Done."); - return 0; + return PM3_SUCCESS; } default: { PrintAndLogEx(ERR, "unknown tag 0x%02x", ndef[indx]); - return 1; + return PM3_ESOFT; } } } - return 0; + return PM3_SUCCESS; } diff --git a/client/mifare/ndef.h b/client/mifare/ndef.h index 71afda2ee..12a6646e8 100644 --- a/client/mifare/ndef.h +++ b/client/mifare/ndef.h @@ -63,5 +63,6 @@ typedef struct { } NDEFHeader_t; int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose); +int NDEFRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen); #endif // _NDEF_H_ From 5618f71ac709716cb9aa3dc70d7685b8415f74f7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Mar 2020 15:56:34 +0200 Subject: [PATCH 245/298] textual --- client/cmddata.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 52d3df314..cf6d9b2e6 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -2312,8 +2312,8 @@ static int CmdDataNDEF(const char *Cmd) { CLIParserFree(); - NDEFRecordsDecodeAndPrint(data, datalen); - return PM3_SUCCESS; + PrintAndLogEx(INFO, "Parsed NDEF Records"); + return NDEFRecordsDecodeAndPrint(data, datalen); } static command_t CommandTable[] = { From 63e06e1738515bf0dd9cb108103134c5458c2e95 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Mar 2020 16:05:19 +0200 Subject: [PATCH 246/298] textual --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3032b04fb..d117ab8be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added `data ndef` - decode NDEF messages (@iceman1001) + - Change - usb write's now waits for shiftregisters (@pwpiwi) + - Change - NDEF supports more signatures now (@iceman1001) + - OSX Makefile now supports `make style` and `make checks` (@Pizza_4u) - Added `HF_LEGIC` standalone mode to read and simulate a Legic prime tag (@Pizza_4u) - Added keri MS decode/encode and update 'lf keri clone' to support MS fc/cid cloning. (@mwalker33) - Fix 'hf mfdes enum' - now actually manages to enumerate files under all AID's. :smiley: (@iceman1001) From 8dd19a00c5968ea0008bcaf97261eb05a3f19f41 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Mar 2020 16:11:01 +0200 Subject: [PATCH 247/298] support v2.0 ndef sigs --- client/mifare/ndef.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 844c7ccd0..5870fb1dd 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -163,7 +163,7 @@ static int ndefPrintHeader(NDEFHeader_t *header) { static int ndefDecodeSig(uint8_t *sig, size_t siglen) { size_t indx = 0; PrintAndLogEx(NORMAL, "\tsignature version: 0x%02x", sig[0]); - if (sig[0] != 0x01) { + if (sig[0] != 0x01 && sig[0] != 0x20) { PrintAndLogEx(ERR, "signature version unknown."); return PM3_ESOFT; } From 74243fcb036240f53330c2450193f345cd36d26e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 31 Mar 2020 18:09:41 +0300 Subject: [PATCH 248/298] signatures v1 and v2 --- client/mifare/ndef.c | 89 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 5870fb1dd..dead65a8e 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -160,14 +160,8 @@ static int ndefPrintHeader(NDEFHeader_t *header) { return PM3_SUCCESS; } -static int ndefDecodeSig(uint8_t *sig, size_t siglen) { - size_t indx = 0; - PrintAndLogEx(NORMAL, "\tsignature version: 0x%02x", sig[0]); - if (sig[0] != 0x01 && sig[0] != 0x20) { - PrintAndLogEx(ERR, "signature version unknown."); - return PM3_ESOFT; - } - indx++; +static int ndefDecodeSig1(uint8_t *sig, size_t siglen) { + size_t indx = 1; uint8_t sigType = sig[indx] & 0x7f; bool sigURI = sig[indx] & 0x80; @@ -225,6 +219,85 @@ static int ndefDecodeSig(uint8_t *sig, size_t siglen) { return PM3_SUCCESS; }; +// https://github.com/nfcpy/ndeflib/blob/master/src/ndef/signature.py#L292 +static int ndefDecodeSig2(uint8_t *sig, size_t siglen) { + size_t indx = 1; + + uint8_t sigType = sig[indx] & 0x7f; + bool sigURI = sig[indx] & 0x80; + indx++; + + uint8_t hashType = sig[indx]; + indx++; + + PrintAndLogEx(NORMAL, "\tsignature type: %s", ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA])); + PrintAndLogEx(NORMAL, "\tsignature uri: %s", (sigURI ? "present" : "not present")); + PrintAndLogEx(NORMAL, "\thash type: %s", ((hashType == 0x02) ? "SHA-256" : "unknown"); + + if (sigURI) { + size_t intsigurilen = (sig[indx] << 8) + sig[indx + 1]; + indx += 2; + PrintAndLogEx(NORMAL, "\tsignature uri [%zu]: %.*s", intsigurilen, (int)intsigurilen, &sig[indx]); + indx += intsigurilen; + } +return 0; + /* if (sigType == stECDSA_P192 || sigType == stECDSA_P256) { + indx += 3; + PrintAndLogEx(NORMAL, "\tsignature [%zu]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); + + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); + if (!res) { + PrintAndLogEx(NORMAL, "\t\tr: %s", sprint_hex(rval, 32)); + PrintAndLogEx(NORMAL, "\t\ts: %s", sprint_hex(sval, 32)); + } + } + indx += intsiglen;*/ + + uint8_t certFormat = (sig[indx] >> 4) & 0x07; + uint8_t certCount = sig[indx] & 0x0f; + bool certURI = sig[indx] & 0x80; + + PrintAndLogEx(NORMAL, "\tcertificate format: %s", ((certFormat < sfNA) ? ndefCertificateFormat_s[certFormat] : ndefCertificateFormat_s[sfNA])); + PrintAndLogEx(NORMAL, "\tcertificates count: %d", certCount); + + // print certificates + indx++; + for (int i = 0; i < certCount; i++) { + size_t intcertlen = (sig[indx + 1] << 8) + sig[indx + 2]; + indx += 2; + + PrintAndLogEx(NORMAL, "\tcertificate %d [%zu]: %s", i + 1, intcertlen, sprint_hex_inrow(&sig[indx], intcertlen)); + indx += intcertlen; + } + + // have certificate uri + if ((indx <= siglen) && certURI) { + size_t inturilen = (sig[indx] << 8) + sig[indx + 1]; + indx += 2; + PrintAndLogEx(NORMAL, "\tcertificate uri [%zu]: %.*s", inturilen, (int)inturilen, &sig[indx]); + } + + return PM3_SUCCESS; +}; + +static int ndefDecodeSig(uint8_t *sig, size_t siglen) { + PrintAndLogEx(NORMAL, "\tsignature version: 0x%02x", sig[0]); + if (sig[0] != 0x01 && sig[0] != 0x20) { + PrintAndLogEx(ERR, "signature version unknown."); + return PM3_ESOFT; + } + + if (sig[0] == 0x01) + return ndefDecodeSig1(sig, siglen); + + if (sig[0] == 0x20) + return ndefDecodeSig2(sig, siglen); + + return PM3_ESOFT; +} + static int ndefDecodePayload(NDEFHeader_t *ndef) { switch (ndef->TypeNameFormat) { From 38004f9db59cd1d88fed0e69f54956baf1008265 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 31 Mar 2020 18:25:17 +0300 Subject: [PATCH 249/298] decode works --- client/mifare/ndef.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index dead65a8e..66b00a159 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -232,28 +232,33 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) { PrintAndLogEx(NORMAL, "\tsignature type: %s", ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA])); PrintAndLogEx(NORMAL, "\tsignature uri: %s", (sigURI ? "present" : "not present")); - PrintAndLogEx(NORMAL, "\thash type: %s", ((hashType == 0x02) ? "SHA-256" : "unknown"); + PrintAndLogEx(NORMAL, "\thash type: %s", ((hashType == 0x02) ? "SHA-256" : "unknown")); + size_t intsiglen = (sig[indx] << 8) + sig[indx + 1]; + indx += 2; + if (sigURI) { - size_t intsigurilen = (sig[indx] << 8) + sig[indx + 1]; indx += 2; - PrintAndLogEx(NORMAL, "\tsignature uri [%zu]: %.*s", intsigurilen, (int)intsigurilen, &sig[indx]); - indx += intsigurilen; - } -return 0; - /* if (sigType == stECDSA_P192 || sigType == stECDSA_P256) { - indx += 3; + PrintAndLogEx(NORMAL, "\tsignature uri [%zu]: %.*s", intsiglen, (int)intsiglen, &sig[indx]); + indx += intsiglen; + } else { PrintAndLogEx(NORMAL, "\tsignature [%zu]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); - - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; - int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); - if (!res) { - PrintAndLogEx(NORMAL, "\t\tr: %s", sprint_hex(rval, 32)); - PrintAndLogEx(NORMAL, "\t\ts: %s", sprint_hex(sval, 32)); + if (sigType == stECDSA_P192 || sigType == stECDSA_P256) { + PrintAndLogEx(NORMAL, "\tsignature: ECDSA"); + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); + if (!res) { + PrintAndLogEx(NORMAL, "\t\tr: %s", sprint_hex(rval, 32)); + PrintAndLogEx(NORMAL, "\t\ts: %s", sprint_hex(sval, 32)); + } else { + PrintAndLogEx(NORMAL, "\t\error signature decode"); + } + } else { + PrintAndLogEx(NORMAL, "\tsignature: unknown type"); } + indx += intsiglen; } - indx += intsiglen;*/ uint8_t certFormat = (sig[indx] >> 4) & 0x07; uint8_t certCount = sig[indx] & 0x0f; From 5b9c51fb7e3b7157a5cf15f10567952929296562 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 31 Mar 2020 18:30:44 +0300 Subject: [PATCH 250/298] signature decode r and s works --- client/mifare/ndef.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 66b00a159..e2399b0fd 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -244,15 +244,12 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) { } else { PrintAndLogEx(NORMAL, "\tsignature [%zu]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); if (sigType == stECDSA_P192 || sigType == stECDSA_P256) { - PrintAndLogEx(NORMAL, "\tsignature: ECDSA"); - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; - int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); - if (!res) { - PrintAndLogEx(NORMAL, "\t\tr: %s", sprint_hex(rval, 32)); - PrintAndLogEx(NORMAL, "\t\ts: %s", sprint_hex(sval, 32)); - } else { - PrintAndLogEx(NORMAL, "\t\error signature decode"); + int slen = intsiglen / 2; + if (slen == 24 || slen == 32) { + PrintAndLogEx(NORMAL, "\tsignature: ECDSA-%d", slen * 8); + PrintAndLogEx(NORMAL, "\t\tr: %s", sprint_hex(&sig[indx], slen)); + indx += slen; + PrintAndLogEx(NORMAL, "\t\ts: %s", sprint_hex(&sig[indx], slen)); } } else { PrintAndLogEx(NORMAL, "\tsignature: unknown type"); From 0f6a1cd8c3673c6b1050f1af95f32dd52e34d0a6 Mon Sep 17 00:00:00 2001 From: Uli Heilmeier Date: Tue, 31 Mar 2020 17:54:51 +0200 Subject: [PATCH 251/298] Doc: Update trace notes First draft of some informations regarding trace command. --- README.md | 4 +- ...race_wireshark_notes.md => trace_notes.md} | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) rename doc/{trace_wireshark_notes.md => trace_notes.md} (62%) diff --git a/README.md b/README.md index 6192c23cd..d183309b4 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ |[Notes on frame format](/doc/new_frame_format.md)||[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)| |[Notes on external flash](/doc/ext_flash_notes.md)||[EMV](/doc/emv_notes.md)| |[Notes on Termux / Android](/doc/termux_notes.md)||[Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md)| -|[Notes on wireshark / tracedata](/doc/trace_wireshark_notes.md)||[JTAG](/doc/jtag_notes.md)| +|[Notes on tracedata / wireshark](/doc/trace_notes.md)||[JTAG](/doc/jtag_notes.md)| |[Notes on loclass](/doc/loclass_notes.md)||[Complete client command set](/doc/commands.md)| |[Notes on paths](/doc/path_notes.md)||| |[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode) || @@ -67,7 +67,7 @@ We usually merge your contributions fast since we do like the idea of getting a - notes on [external flash](/doc/ext_flash_notes.md) - notes on [standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode) - notes on [Termux / Android](/doc/termux_notes.md) -- notes on [Wireshark / tracedata](/doc/trace_wireshark_notes.md) +- notes on [tracedata / Wireshark](/doc/trace_notes.md) - notes on [loclass](/doc/loclass_notes.md) - notes on [EMV](/doc/emv_notes.md) - notes on [Paths](/doc/path_notes.md) diff --git a/doc/trace_wireshark_notes.md b/doc/trace_notes.md similarity index 62% rename from doc/trace_wireshark_notes.md rename to doc/trace_notes.md index 50dd9d082..a126a238f 100644 --- a/doc/trace_wireshark_notes.md +++ b/doc/trace_notes.md @@ -4,6 +4,43 @@ The `trace` command lists the data exchange by the proxmark3 and a tag or a read With `trace list` a table is shown which gives timing information, the src of the data bytes, the transmitted/received bytes itself, a check if the CRC was correct and some decoding of the command. +## Timing + +The Start and the End coloumn lists timestamps when the transmission of the shown data started (time of first bit) and when it ended (end of last modulation). + +The unit for this time information depends on the protocol in use: + +* ISO14443A and Thinfilm: all times are in carrier periods (1/13.56MHz) +* For Legic timing information depends also on direction: + * Reader Mode: Timings are in ticks (1us == 1.5ticks) + * Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us) +* Hitag1 / Hitag2 / HitagS: Elementary Time Unit (ETU) is 8µs +* iClass, ISO15693, ISO18092 and FeliCa have no accurate timing information at the moment +* For others timing is not available + +By specifing the option ```f``` (e.g. ```trace list 14a f```) the frame delay times are shown. (So you don't have to do the math by your own). + +## Sources + +If the data is marked as a response the source is shown as Tag. Otherwise it is marked as Reader (Rdr). + +## Data + +This coloumn show the raw bytes trasmitted over the air. With option ```c``` CRC bytes are marked in square brackets. + +## CRC + +Marks if the transmitted CRC matches with the calculated CRC. + +## Annotation + +Annotations provide a rough decoding of the transmitted data. For ISO14443A a more detailed decoding is available with Wireshark (s. next chapter) + + +-- + +# Trace and Wireshark + To get a more detailed explanation of the transmitted data for ISO14443A traces the output can be converted to a pcapng file to read it with [Wireshark](https://www.wireshark.org/). To do so From 6d3c13c49acf6ff7bbd9ce2d9db539db7abe427c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 31 Mar 2020 19:13:03 +0300 Subject: [PATCH 252/298] fix mfp behavior in info command --- client/cmdhf14a.c | 1 + client/cmdhfmfp.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 13a5a9213..a3ee49503 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -557,6 +557,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav if (activateField) { PacketResponseNG resp; + responseNum = 0; // Anticollision + SELECT card SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index ff1b87cf5..56963819c 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -47,7 +47,7 @@ static int CmdHFMFPInfo(const char *Cmd) { infoHF14A(false, false, false); // Mifare Plus info - SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); PacketResponseNG resp; WaitForResponse(CMD_ACK, &resp); @@ -115,7 +115,7 @@ static int CmdHFMFPInfo(const char *Cmd) { int datalen = 0; // https://github.com/Proxmark/proxmark3/blob/master/client/luascripts/mifarePlus.lua#L161 uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00}; - int res = ExchangeRAW14a(cmd, sizeof(cmd), false, false, data, sizeof(data), &datalen, false); + int res = ExchangeRAW14a(cmd, sizeof(cmd), true, false, data, sizeof(data), &datalen, false); if (memcmp(data, "\x67\x00", 2) == 0) { PrintAndLogEx(INFO, "\tMost likely a Mifare DESFire tag"); From 737ebf9ab885f4ba3bd87f021d407ee20dec4618 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 31 Mar 2020 19:26:09 +0300 Subject: [PATCH 253/298] ndef signature1 length fix --- client/mifare/ndef.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index e2399b0fd..f1b3e42bd 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -171,16 +171,19 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) { size_t intsiglen = (sig[indx + 1] << 8) + sig[indx + 2]; // ecdsa 0x04 - if (sigType == stECDSA_P192) { + if (sigType == stECDSA_P192 || sigType == stECDSA_P256) { indx += 3; + int slen = 24; + if (sigType == stECDSA_P256) + slen = 32; PrintAndLogEx(NORMAL, "\tsignature [%zu]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); uint8_t rval[300] = {0}; uint8_t sval[300] = {0}; int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); if (!res) { - PrintAndLogEx(NORMAL, "\t\tr: %s", sprint_hex(rval, 32)); - PrintAndLogEx(NORMAL, "\t\ts: %s", sprint_hex(sval, 32)); + PrintAndLogEx(NORMAL, "\t\tr: %s", sprint_hex(rval + 32 - slen, slen)); + PrintAndLogEx(NORMAL, "\t\ts: %s", sprint_hex(sval + 32 - slen, slen)); } } indx += intsiglen; From 83e92c64559bb6b3b2ad718a49fe4a0d77387c8b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Apr 2020 09:25:54 +0200 Subject: [PATCH 254/298] Add: 'hf mfu ndef' - read and parse NDEF type2 records --- client/cmdhfmfu.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index c1cd5d31a..ce2528b89 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -21,6 +21,9 @@ #include "fileutils.h" #include "protocols.h" #include "generator.h" +#include "mifare/ndef.h" +#include "cliparser/cliparser.h" + #define MAX_UL_BLOCKS 0x0F #define MAX_ULC_BLOCKS 0x2B @@ -563,6 +566,22 @@ static int ul_print_default(uint8_t *data) { return PM3_SUCCESS; } +static int ndef_get_maxsize(uint8_t *data) { + // no NDEF message + if (data[0] != 0xE1) + return 0; + + if (data[2] == 0x06) + return 48; + else if (data[2] == 0x12) + return 144; + else if (data[2] == 0x3E) + return 496; + else if (data[2] == 0x6D) + return 872; + return 0; +} + static int ndef_print_CC(uint8_t *data) { // no NDEF message if (data[0] != 0xE1) @@ -2633,6 +2652,100 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14MfuNDEF(const char *Cmd) { + + int keylen; + int maxsize = 16, status; + bool hasAuthKey = false; + bool swapEndian = false; + + iso14a_card_select_t card; + uint8_t data[16] = {0x00}; + uint8_t key[16] = {0x00}; + uint8_t *p_key = key; + uint8_t pack[4] = {0, 0, 0, 0}; + + CLIParserInit("hf mfu ndef", + "Prints NFC Data Exchange Format (NDEF)", + "Usage:\n\thf mfu ndef -> shows NDEF data\n" + "\thf mfu ndef -k ffffffff -> shows NDEF data with key\n"); + + void *argtable[] = { + arg_param_begin, + arg_str0("kK", "key", "replace default key for NDEF", NULL), + arg_lit0("lL", "key", "(optional) swap entered key's endianness"), + arg_param_end + }; + CLIExecWithReturn(Cmd, argtable, true); + + CLIGetHexWithReturn(1, key, &keylen); + swapEndian = arg_get_lit(2); + CLIParserFree(); + + switch(keylen) { + case 0: + break; + case 4: + case 16: + hasAuthKey = true; + break; + default: + PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); + return PM3_EINVARG; + } + + // Get tag type + TagTypeUL_t tagtype = GetHF14AMfU_Type(); + if (tagtype == UL_ERROR) return PM3_ESOFT; + + // Is tag UL/NTAG? + + // Swap endianness + if (swapEndian && hasAuthKey) p_key = SwapEndian64(key, keylen, (keylen == 16) ? 8 : 4); + + // Select and Auth + if (ul_auth_select(&card, tagtype, hasAuthKey, p_key, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + + // read pages 0,1,2,3 (should read 4pages) + status = ul_read(0, data, sizeof(data)); + if (status == -1) { + DropField(); + PrintAndLogEx(ERR, "Error: tag didn't answer to READ"); + return PM3_ESOFT; + } else if (status == 16) { + + status = ndef_print_CC(data + 12); + if (status == PM3_ESOFT) { + DropField(); + PrintAndLogEx(ERR, "Error: tag didn't contain a NDEF Container"); + return PM3_ESOFT; + } + + // max datasize; + maxsize = ndef_get_maxsize(data + 12); + } + + // allocate mem + uint8_t *records = calloc(maxsize, sizeof(uint8_t)); + if (records == NULL) { + DropField(); + return PM3_EMALLOC; + } + + // read NDEF records. + for(uint16_t i = 0, j = 0; i < maxsize; i += 16, j += 4) { + status = ul_read(4 + j, records + i, 16); + if (status == -1) { + DropField(); + PrintAndLogEx(ERR, "Error: tag didn't answer to READ"); + return PM3_ESOFT; + } + } + DropField(); + status = NDEFDecodeAndPrint(records, (size_t)maxsize, true); + free(records); + return status; +} //------------------------------------ // Menu Stuff //------------------------------------ @@ -2651,6 +2764,7 @@ static command_t CommandTable[] = { {"gen", CmdHF14AMfUGenDiverseKeys, AlwaysAvailable, "Generate 3des mifare diversified keys"}, {"pwdgen", CmdHF14AMfUPwdGen, AlwaysAvailable, "Generate pwd from known algos"}, {"otptear", CmdHF14AMfuOtpTearoff, IfPm3Iso14443a, "Tear-off test on OTP bits"}, + {"ndef", CmdHF14MfuNDEF, IfPm3Iso14443a, "Prints NDEF records from card"}, {NULL, NULL, NULL, NULL} }; From d633340a1a49b62fc9abfcb34b3cadff516821ee Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Apr 2020 09:26:39 +0200 Subject: [PATCH 255/298] Chg: 'data ndef' - cleaner output if called with no hex --- client/cmddata.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/cmddata.c b/client/cmddata.c index cf6d9b2e6..74c33da55 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -2309,8 +2309,9 @@ static int CmdDataNDEF(const char *Cmd) { int datalen = 0; uint8_t data[MAX_NDEF_LEN] = {0}; CLIGetHexWithReturn(1, data, &datalen); - CLIParserFree(); + if (datalen == 0) + return PM3_EINVARG; PrintAndLogEx(INFO, "Parsed NDEF Records"); return NDEFRecordsDecodeAndPrint(data, datalen); From 426246178fecb259cde62e8eb06fd8b0c18100e8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Apr 2020 09:27:50 +0200 Subject: [PATCH 256/298] textual --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d117ab8be..1ef686269 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added `hf mfu ndef` - read and decode NDEF Type2 messages (@iceman1001) - Added `data ndef` - decode NDEF messages (@iceman1001) - Change - usb write's now waits for shiftregisters (@pwpiwi) - Change - NDEF supports more signatures now (@iceman1001) From 3f54fdf2528d3f310933d9ccb618ecc2eb43072e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Apr 2020 09:49:11 +0200 Subject: [PATCH 257/298] textual --- client/mifare/ndef.c | 50 ++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index f1b3e42bd..e3ba3997d 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -308,15 +308,15 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) { switch (ndef->TypeNameFormat) { case tnfWellKnownRecord: PrintAndLogEx(INFO, "Well Known Record"); - PrintAndLogEx(NORMAL, "\ttype: %.*s", (int)ndef->TypeLen, ndef->Type); + PrintAndLogEx(INFO, "\ttype : %.*s", (int)ndef->TypeLen, ndef->Type); if (!strncmp((char *)ndef->Type, "T", ndef->TypeLen)) { - PrintAndLogEx(NORMAL, "\ttext : %.*s", (int)ndef->PayloadLen, ndef->Payload); + PrintAndLogEx(INFO, "\ttext : " _GREEN_("%.*s"), (int)ndef->PayloadLen, ndef->Payload); } if (!strncmp((char *)ndef->Type, "U", ndef->TypeLen)) { - PrintAndLogEx(NORMAL - , "\turi : %s%.*s" + PrintAndLogEx(INFO + , "\turi : " _GREEN_("%s%.*s") , (ndef->Payload[0] <= 0x23 ? URI_s[ndef->Payload[0]] : "[err]") , (int)(ndef->PayloadLen - 1) , &ndef->Payload[1] @@ -330,14 +330,28 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) { break; case tnfAbsoluteURIRecord: PrintAndLogEx(INFO, "Absolute URI Record"); - PrintAndLogEx(NORMAL, "\ttype: %.*s", (int)ndef->TypeLen, ndef->Type); - PrintAndLogEx(NORMAL, "\tpayload: %.*s", (int)ndef->PayloadLen, ndef->Payload); + PrintAndLogEx(INFO, "\ttype : %.*s", (int)ndef->TypeLen, ndef->Type); + PrintAndLogEx(INFO, "\tpayload : %.*s", (int)ndef->PayloadLen, ndef->Payload); break; case tnfEmptyRecord: + PrintAndLogEx(INFO, "Empty Record"); + PrintAndLogEx(INFO, "\t -to be impl-"); + break; case tnfMIMEMediaRecord: + PrintAndLogEx(INFO, "MIME Media Record"); + PrintAndLogEx(INFO, "\t -to be impl-"); + break; case tnfExternalRecord: + PrintAndLogEx(INFO, "External Record"); + PrintAndLogEx(INFO, "\t -to be impl-"); + break; case tnfUnchangedRecord: + PrintAndLogEx(INFO, "Unchanged Record"); + PrintAndLogEx(INFO, "\t -to be impl-"); + break; case tnfUnknownRecord: + PrintAndLogEx(INFO, "Unknown Record"); + PrintAndLogEx(INFO, "\t -to be impl-"); break; } return PM3_SUCCESS; @@ -372,8 +386,11 @@ static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { int NDEFRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { bool firstRec = true; size_t len = 0; + size_t counter = 0; while (len < ndefRecordLen) { + counter++; + NDEFHeader_t NDEFHeader = {0}; int res = ndefDecodeHeader(&ndefRecord[len], ndefRecordLen - len, &NDEFHeader); if (res != PM3_SUCCESS) @@ -381,7 +398,7 @@ int NDEFRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { if (firstRec) { if (!NDEFHeader.MessageBegin) { - PrintAndLogEx(ERR, "NDEF first record have MessageBegin=false!"); + PrintAndLogEx(ERR, "NDEF first record have MessageBegin = false!"); return PM3_ESOFT; } firstRec = false; @@ -392,6 +409,9 @@ int NDEFRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { return PM3_ESOFT; } + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Record " _YELLOW_("%zu"), counter); + PrintAndLogEx(INFO, "-----------------------------------------------------"); ndefRecordDecodeAndPrint(&ndefRecord[len], NDEFHeader.RecLen); len += NDEFHeader.RecLen; @@ -407,22 +427,26 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { size_t indx = 0; - PrintAndLogEx(INFO, "NDEF decoding:"); + PrintAndLogEx(INFO, ""); + PrintAndLogEx(INFO, "NDEF parsing"); while (indx < ndefLen) { + + PrintAndLogEx(INFO, "-----------------------------------------------------"); switch (ndef[indx]) { case 0x00: { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); - PrintAndLogEx(INFO, "-- NDEF NULL block."); + + PrintAndLogEx(SUCCESS, "-- NDEF NULL block."); if (len) - PrintAndLogEx(WARNING, "NDEF NULL block size must be 0 instead of %d.", len); + PrintAndLogEx(WARNING, "NDEF NULL block size must be 0, got %d bytes", len); indx += len; break; } case 0x03: { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); - PrintAndLogEx(INFO, "-- NDEF message. len: %d", len); + PrintAndLogEx(SUCCESS, "Found NDEF message (%d bytes)", len); int res = NDEFRecordsDecodeAndPrint(&ndef[indx], len); if (res != PM3_SUCCESS) @@ -434,12 +458,12 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { case 0xfd: { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); - PrintAndLogEx(INFO, "-- NDEF proprietary info. Skipped %d bytes.", len); + PrintAndLogEx(SUCCESS, "-- NDEF proprietary info. Skipped %d bytes.", len); indx += len; break; } case 0xfe: { - PrintAndLogEx(INFO, "-- NDEF Terminator. Done."); + PrintAndLogEx(SUCCESS, "-- NDEF Terminator. Done."); return PM3_SUCCESS; } default: { From 07d16bba51b60a9e4075c032fc80f1b6ed9e58a5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Apr 2020 15:10:50 +0200 Subject: [PATCH 258/298] added some more originality keys --- client/cmdhfmfu.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index ce2528b89..d5a632f8f 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -267,7 +267,7 @@ uint8_t default_pwd_pack[][4] = { // known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier) // ref: AN11350 NTAG 21x Originality Signature Validation // ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation -uint8_t public_keys[2][PUBLIC_ECDA_KEYLEN] = { +uint8_t nxp_mfu_public_keys[6][PUBLIC_ECDA_KEYLEN] = { // UL, NTAG21x and NDEF { 0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c, @@ -281,6 +281,34 @@ uint8_t public_keys[2][PUBLIC_ECDA_KEYLEN] = { 0x4e, 0x25, 0x5e, 0x3d, 0xa5, 0x53, 0x89, 0xa8, 0x27, 0x56, 0x4e, 0x11, 0x71, 0x8e, 0x01, 0x72, 0x92, 0xfa, 0xf2, 0x32, 0x26, 0xa9, 0x66, 0x14, 0xb8 + }, + // unknown. Needs identification + { + 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57, + 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35, + 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2, + 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF + }, + // unknown. Needs identification + { + 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE, + 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1, + 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA, + 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC + }, + // manufacturer public key + { + 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61, + 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C, + 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07, + 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2 + }, + // MIKRON public key. + { + 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8, + 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07, + 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7, + 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2 } }; @@ -891,12 +919,12 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig if (tagtype == UL_EV1_48 || tagtype == UL_EV1_128) { public_key = 1; } - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, public_keys[public_key], uid, 7, signature, signature_len, false); + int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_mfu_public_keys[public_key], uid, 7, signature, signature_len, false); bool is_valid = (res == 0); PrintAndLogEx(INFO, "\n--- Tag Signature"); PrintAndLogEx(INFO, "IC signature public key name : NXP NTAG21x (2013)"); - PrintAndLogEx(INFO, "IC signature public key value : %s", sprint_hex(public_keys[public_key], PUBLIC_ECDA_KEYLEN)); + PrintAndLogEx(INFO, "IC signature public key value : %s", sprint_hex(nxp_mfu_public_keys[public_key], PUBLIC_ECDA_KEYLEN)); PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp128r1"); PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, signature_len)); PrintAndLogEx(SUCCESS, "Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); From cc6fda9b758aedcb40dfb174208ebf6bfe051f04 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Apr 2020 15:54:59 +0200 Subject: [PATCH 259/298] added checks for unknown public keys --- client/cmdhf15.c | 76 ++++++++++++++++++++--- client/cmdhfmfdes.c | 68 +++++++++++++++------ client/cmdhfmfu.c | 146 ++++++++++++++++++++++++++------------------ 3 files changed, 202 insertions(+), 88 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 9b0b8dbf1..2003fd924 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -208,7 +208,8 @@ const productName uidmapping[] = { { 0, 0, "no tag-info available" } // must be the last entry }; -uint8_t nxp_public_keys[][33] = { +#define PUBLIC_ECDA_KEYLEN 33 +uint8_t nxp_15693_public_keys[][PUBLIC_ECDA_KEYLEN] = { // ICODE SLIX2 / DNA { 0x04, 0x88, 0x78, 0xA2, 0xA2, 0xD3, 0xEE, 0xC3, @@ -216,10 +217,67 @@ uint8_t nxp_public_keys[][33] = { 0xF9, 0xBE, 0x11, 0xC4, 0xE2, 0xE8, 0x96, 0x64, 0x8B, 0x32, 0xEF, 0xA5, 0x9C, 0xEA, 0x6E, 0x59, 0xF0 }, + // unknown. Needs identification + { + 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57, + 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35, + 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2, + 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF + }, + // unknown. Needs identification + { + 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE, + 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1, + 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA, + 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC + }, + // manufacturer public key + { + 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61, + 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C, + 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07, + 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2 + }, + // MIKRON public key. + { + 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8, + 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07, + 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7, + 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2 + } }; static int CmdHF15Help(const char *Cmd); +static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) { + + uint8_t i; + int res; + bool is_valid = false; + for (i = 0; i< ARRAYLEN(nxp_15693_public_keys); i++) { + + res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_15693_public_keys[i], uid, 8, signature, 32, false); + + is_valid = (res == 0); + if (is_valid) + break; + } + + PrintAndLogEx(NORMAL, ""); + if (is_valid == false) { + PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed")); + return PM3_ESOFT; + } + + PrintAndLogEx(INFO, "\n--- Tag Signature"); + PrintAndLogEx(INFO, " IC signature public key name : %s", (i == 0)? "NXP ICODE SLIX2 / DNA" : "unknown, post on forum"); + PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_15693_public_keys[i], 33)); + PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp128r1"); + PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, 32)); + PrintAndLogEx(INFO, " Signature verification " _GREEN_("successful")); + return PM3_SUCCESS; +} + // fast method to just read the UID of a tag (collision detection not supported) // *buf should be large enough to fit the 64bit uid // returns 1 if succeeded @@ -796,16 +854,8 @@ static int NxpSysInfo(uint8_t *uid) { uint8_t signature[32] = {0x00}; memcpy(signature, recv + 1, 32); - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_public_keys[0], uid, 8, signature, 32, false); - bool is_valid = (res == 0); + nxp_15693_print_signature(uid, signature); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Tag Signature"); - PrintAndLogEx(NORMAL, " IC signature public key name : NXP ICODE SLIX2 / DNA"); - PrintAndLogEx(NORMAL, " IC signature public key value : %s", sprint_hex(nxp_public_keys[0], 33)); - PrintAndLogEx(NORMAL, " Elliptic curve parameters : NID_secp128r1"); - PrintAndLogEx(NORMAL, " TAG IC Signature : %s", sprint_hex(signature, 32)); - PrintAndLogEx(NORMAL, " Signature verification %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); } } @@ -901,10 +951,16 @@ static int CmdHF15Info(const char *Cmd) { } // Check if SLIX2 and attempt to get NXP System Information + PrintAndLogEx(INFO, "4 & 08 :: %02x 7 == 1 :: %u 8 == 4 :: %u", recv[4], recv[7], recv[8]); if (recv[8] == 0x04 && recv[7] == 0x01 && recv[4] & 0x80) { return NxpSysInfo(uid); } +// if (recv[8] == 0x04 && recv[7] == 0x02 && recv[4] & 0x80) { + return NxpSysInfo(uid); + //} + + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 7209a5a71..d44f3443d 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -12,6 +12,7 @@ #include #include +#include "commonutil.h" // ARRAYLEN #include "cmdparser.h" // command_t #include "comms.h" #include "ui.h" @@ -121,18 +122,10 @@ static int get_desfire_freemem(uint32_t *free_mem) { // --- GET SIGNATURE static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len, desfire_cardtype_t card_type) { - uint8_t public_key; - if (card_type == LIGHT) - public_key = 0; - else if (card_type == EV2) - public_key = 1; - else - return PM3_EINVARG; - #define PUBLIC_DESFIRE_ECDA_KEYLEN 57 // ref: MIFARE Desfire Originality Signature Validation - uint8_t nxp_desfire_keys[2][PUBLIC_DESFIRE_ECDA_KEYLEN] = { + uint8_t nxp_desfire_keys[][PUBLIC_DESFIRE_ECDA_KEYLEN] = { // DESFire Light { 0x04, 0x0E, 0x98, 0xE1, 0x17, 0xAA, 0xA3, 0x64, @@ -143,7 +136,11 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0xD0, 0x25, 0x72, 0x42, 0x7E, 0x5A, 0xE0, 0xA2, 0xDD, 0x36, 0x59, 0x1B, 0x1F, 0xB3, 0x4F, 0xCF, 0x3D }, - // DESFire Ev2 + + // DESFire Ev2 - wanted + // DESFire Ev3 - wanted + + // Unknown - needs identification { 0x04, 0x8A, 0x9B, 0x38, 0x0A, 0xF2, 0xEE, 0x1B, 0x98, 0xDC, 0x41, 0x7F, 0xEC, 0xC2, 0x63, 0xF8, @@ -152,26 +149,59 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0x42, 0x2B, 0x81, 0xEC, 0x20, 0xB6, 0x5A, 0x66, 0xB5, 0x10, 0x2A, 0x61, 0x59, 0x6A, 0xF3, 0x37, 0x92, 0x00, 0x59, 0x93, 0x16, 0xA0, 0x0A, 0x14, 0x10 - } + }, + // Unknown - needs identification + { + 0x04, 0x44, 0x09, 0xAD, 0xC4, 0x2F, 0x91, 0xA8, + 0x39, 0x40, 0x66, 0xBA, 0x83, 0xD8, 0x72, 0xFB, + 0x1D, 0x16, 0x80, 0x37, 0x34, 0xE9, 0x11, 0x17, + 0x04, 0x12, 0xDD, 0xF8, 0xBA, 0xD1, 0xA4, 0xDA, + 0xDF, 0xD0, 0x41, 0x62, 0x91, 0xAF, 0xE1, 0xC7, + 0x48, 0x25, 0x39, 0x25, 0xDA, 0x39, 0xA5, 0xF3, + 0x9A, 0x1C, 0x55, 0x7F, 0xFA, 0xCD, 0x34, 0xC6, 0x2E + } }; + + uint8_t i; + int res; + bool is_valid = false; + for (i = 0; i< ARRAYLEN(nxp_desfire_keys); i++) { + + res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, nxp_desfire_keys[i], uid, 7, signature, signature_len, false); + + is_valid = (res == 0); + if (is_valid) + break; + } + if (is_valid == false) { + PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed")); + return PM3_ESOFT; + } - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, nxp_desfire_keys[public_key], uid, 7, signature, signature_len, false); - bool is_valid = (res == 0); + char *publickeyname; + switch(i) { + case 0: + publickeyname = "NXP DESFire Light"; + break; + default: + publickeyname = "Unknown DESFire, post on forum"; + break; + } PrintAndLogEx(INFO, " Tag Signature"); - PrintAndLogEx(INFO, " IC signature public key name : %s", (card_type == LIGHT) ? "NXP DESFire Light" : "NXP DESFire Ev2"); - PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_desfire_keys[public_key], 16)); - PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 16, 16)); - PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 32, 16)); - PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 48, PUBLIC_DESFIRE_ECDA_KEYLEN - 48)); + PrintAndLogEx(INFO, " IC signature public key name : %s", publickeyname); + PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_desfire_keys[i], 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[i] + 16, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[i] + 32, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[i] + 48, PUBLIC_DESFIRE_ECDA_KEYLEN - 48)); PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp224r1"); PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 16, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 32, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 48, signature_len - 48)); - PrintAndLogEx( (is_valid) ? SUCCESS : WARNING, " Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); + PrintAndLogEx( (is_valid) ? SUCCESS : WARNING, " Signature verified " _GREEN_("successful")); PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; } diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index d5a632f8f..7acf7379b 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -262,57 +262,6 @@ uint8_t default_pwd_pack[][4] = { {0xFF, 0xFF, 0xFF, 0xFF}, // PACK 0x00,0x00 -- factory default }; -#define PUBLIC_ECDA_KEYLEN 33 - -// known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier) -// ref: AN11350 NTAG 21x Originality Signature Validation -// ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation -uint8_t nxp_mfu_public_keys[6][PUBLIC_ECDA_KEYLEN] = { - // UL, NTAG21x and NDEF - { - 0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c, - 0xfe, 0x3d, 0xc1, 0x0e, 0x5d, 0xe6, 0x8a, 0x49, - 0x9b, 0x1c, 0x20, 0x2d, 0xb5, 0xb1, 0x32, 0x39, - 0x3e, 0x89, 0xed, 0x19, 0xfe, 0x5b, 0xe8, 0xbc, 0x61 - }, - // UL EV1 - { - 0x04, 0x90, 0x93, 0x3b, 0xdc, 0xd6, 0xe9, 0x9b, - 0x4e, 0x25, 0x5e, 0x3d, 0xa5, 0x53, 0x89, 0xa8, - 0x27, 0x56, 0x4e, 0x11, 0x71, 0x8e, 0x01, 0x72, - 0x92, 0xfa, 0xf2, 0x32, 0x26, 0xa9, 0x66, 0x14, 0xb8 - }, - // unknown. Needs identification - { - 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57, - 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35, - 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2, - 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF - }, - // unknown. Needs identification - { - 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE, - 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1, - 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA, - 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC - }, - // manufacturer public key - { - 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61, - 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C, - 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07, - 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2 - }, - // MIKRON public key. - { - 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8, - 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07, - 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7, - 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2 - } -}; - - uint32_t UL_TYPES_ARRAY[] = { UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203, NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, @@ -915,19 +864,98 @@ static int ulev1_print_counters() { } static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) { - uint8_t public_key = 0; - if (tagtype == UL_EV1_48 || tagtype == UL_EV1_128) { - public_key = 1; + + #define PUBLIC_ECDA_KEYLEN 33 + + // known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier) + // ref: AN11350 NTAG 21x Originality Signature Validation + // ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation + uint8_t nxp_mfu_public_keys[6][PUBLIC_ECDA_KEYLEN] = { + // UL, NTAG21x and NDEF + { + 0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c, + 0xfe, 0x3d, 0xc1, 0x0e, 0x5d, 0xe6, 0x8a, 0x49, + 0x9b, 0x1c, 0x20, 0x2d, 0xb5, 0xb1, 0x32, 0x39, + 0x3e, 0x89, 0xed, 0x19, 0xfe, 0x5b, 0xe8, 0xbc, 0x61 + }, + // UL EV1 + { + 0x04, 0x90, 0x93, 0x3b, 0xdc, 0xd6, 0xe9, 0x9b, + 0x4e, 0x25, 0x5e, 0x3d, 0xa5, 0x53, 0x89, 0xa8, + 0x27, 0x56, 0x4e, 0x11, 0x71, 0x8e, 0x01, 0x72, + 0x92, 0xfa, 0xf2, 0x32, 0x26, 0xa9, 0x66, 0x14, 0xb8 + }, + // unknown. Needs identification + { + 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57, + 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35, + 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2, + 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF + }, + // unknown. Needs identification + { + 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE, + 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1, + 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA, + 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC + }, + // manufacturer public key + { + 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61, + 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C, + 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07, + 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2 + }, + // MIKRON public key. + { + 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8, + 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07, + 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7, + 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2 + } + }; + + uint8_t i; + int res; + bool is_valid = false; + for (i = 0; i< ARRAYLEN(nxp_mfu_public_keys); i++) { + + res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_mfu_public_keys[i], uid, 7, signature, signature_len, false); + + is_valid = (res == 0); + if (is_valid) + break; + } + if (is_valid == false) { + PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed")); + return PM3_ESOFT; + } + + char *publickeyname; + switch(i) { + case 0: + publickeyname = "NXP NTAG21x (2013)"; + break; + case 1: + publickeyname = "NXP Ev1"; + break; + case 4: + publickeyname = "Manufacturer, post on forum"; + break; + case 5: + publickeyname = "MIKRON"; + break; + default: + publickeyname = "Unknown, post on forum"; + break; } - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_mfu_public_keys[public_key], uid, 7, signature, signature_len, false); - bool is_valid = (res == 0); PrintAndLogEx(INFO, "\n--- Tag Signature"); - PrintAndLogEx(INFO, "IC signature public key name : NXP NTAG21x (2013)"); - PrintAndLogEx(INFO, "IC signature public key value : %s", sprint_hex(nxp_mfu_public_keys[public_key], PUBLIC_ECDA_KEYLEN)); + PrintAndLogEx(INFO, "IC signature public key name : %s", publickeyname); + PrintAndLogEx(INFO, "IC signature public key value : %s", sprint_hex(nxp_mfu_public_keys[i], PUBLIC_ECDA_KEYLEN)); PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp128r1"); PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, signature_len)); - PrintAndLogEx(SUCCESS, "Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); + PrintAndLogEx(SUCCESS, "Signature verified " _GREEN_("successful")); return PM3_SUCCESS; } From d67c55cd2accc065fcac6404360433e93137c18b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Apr 2020 06:38:45 +0200 Subject: [PATCH 260/298] entries from taginfo app\n removed duplicates --- client/dictionaries/mfc_default_keys.dic | 118 ++++++++++++----------- 1 file changed, 63 insertions(+), 55 deletions(-) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 4682ad0e5..6e2a2f4da 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -5,7 +5,8 @@ # ffffffffffff # Defaultkey(firstkeyusedbyprogramifnouserdefinedkey) 000000000000 # Blankkey -a0a1a2a3a4a5 # NFCForumMADkey +a0a1a2a3a4a5 # NFC Forum MADkey +A5A4A3A2A1A0 # MAD access key (reversed) b0b1b2b3b4b5 c0c1c2c3c4c5 d0d1d2d3d4d5 @@ -20,19 +21,49 @@ a0478cc39091 533cb6c723f6 8fd0a4f256e9 # -d2ece8b9395e # lib +d2ece8b9395e # lib / Nat Bieb # NSCP default key 1494E81663D7 # +# Kiev keys +569369c5a0e5 # kiev +632193be1c3c # kiev +644672bd4afe # kiev +8fe644038790 # kiev +9de89e070277 # kiev +b5ff67cba951 # kiev / ov-chipkaart +eff603e1efe9 # kiev +f14ee7cae863 # kiev +# +# RKF +fc00018778f7 # Västtrafiken KeyA, RKF ÖstgötaTrafiken KeyA +0297927c0f77 # Västtrafiken KeyA +54726176656c # Västtrafiken KeyA +00000ffe2488 # Västtrafiken KeyB +776974687573 # Västtrafiken KeyB +ee0042f88840 # Västtrafiken KeyB +26940b21ff5d # RKF SLKeyA +a64598a77478 # RKF SLKeyA +5c598c9c58b5 # RKF SLKeyB +e4d2770a89be # RKF SLKeyB +722bfcc5375f # RKF RejskortDanmark KeyA +f1d83f964314 # RKF RejskortDanmark KeyB +505249564141 # RKF JOJOPRIVAKeyA +505249564142 # RKF JOJOPRIVAKeyB +47524f555041 # RKF JOJOGROUPKeyA +47524f555042 # RKF JOJOGROUPKeyB +434f4d4d4f41 # RKF JOJOGROUPKeyA +434f4d4d4f42 # RKF JOJOGROUPKeyB +# +4b0b20107ccb # TNP3xxx +# # more Keys from mfc_default_keys.lua 000000000001 000000000002 00000000000a 00000000000b -00000ffe2488 # VästtrafikenKeyB 010203040506 0123456789ab -0297927c0f77 # VästtrafikenKeyA 100000000000 111111111111 123456789abc @@ -41,72 +72,39 @@ d2ece8b9395e # lib 1999a3554a55 200000000000 222222222222 -26940b21ff5d # RKFSLKeyA 27dd91f1fcf1 2BA9621E0A36 # DirectoryandeventlogKeyB +4AF9D7ADEBE4 # DirectoryandeventlogKeyA 333333333333 33f974b42769 34d1df9934c5 -434f4d4d4f41 # RKFJOJOGROUPKeyA -434f4d4d4f42 # RKFJOJOGROUPKeyB 43ab19ef5c31 444444444444 -47524f555041 # RKFJOJOGROUPKeyA -47524f555042 # RKFJOJOGROUPKeyB -4AF9D7ADEBE4 # DirectoryandeventlogKeyA -4b0b20107ccb # TNP3xxx -505249564141 # RKFJOJOPRIVAKeyA -505249564142 # RKFJOJOPRIVAKeyB 505249565441 505249565442 -54726176656c # VästtrafikenKeyA 555555555555 55f5a5dd38c9 -569369c5a0e5 # kiev -5c598c9c58b5 # RKFSLKeyB -632193be1c3c # kiev -644672bd4afe # kiev 666666666666 -722bfcc5375f # RKFRejskortDanmarkKeyA -776974687573 # VästtrafikenKeyB 777777777777 888888888888 -8fe644038790 # kiev 999999999999 99c636334433 -9de89e070277 # kiev a00000000000 a053a292a4af -a64598a77478 # RKFSLKeyA a94133013401 aaaaaaaaaaaa abcdef123456 # Keyfromladyada.net b00000000000 b127c6f41436 -b5ff67cba951 # kiev bbbbbbbbbbbb bd493a3962b6 c934fe34d934 cccccccccccc dddddddddddd -e4d2770a89be # RKFSLKeyB -ee0042f88840 # VästtrafikenKeyB eeeeeeeeeeee -eff603e1efe9 # kiev -f14ee7cae863 # kiev f1a97341a9fc -f1d83f964314 # RKFRejskortDanmarkKeyB -fc00018778f7 # VästtrafikenKeyA, RKFÖstgötaTrafikenKeyA 44ab09010845 # hotel system 85fed980ea5a # hotel system -314B49474956 # VIGIK1 A -564c505f4d41 # VIGIK1 B -ba5b895da162 # VIGIK1 B -# Vigik mystery Keys Mifare 1k EV1 (S50) -5c8ff9990da2 # 16 A -75ccb59c9bed # 17 A -d01afeeb890a # 16 B -4b791bea7bcc # 17 B # 43454952534E # ARD (fr) key A 4A2B29111213 # ARD (fr) key B @@ -361,11 +359,29 @@ a56c2df9a26d # 68d3f7307c89 568c9083f71c # Smart Rider. Western Australian Public Transport Cards +# +# +97F5DA640B18 # Bangkok metro key +A8844B0BCA06 # Metro Valencia key +857464D3AAD1 # HTC Eindhoven key +# # Vigik Keys # Various sources : # * https://github.com/DumpDos/Vigik # * http://newffr.com/viewtopic.php?&forum=235&topic=11559 # * Own dumps +# +# French VIGIK +314B49474956 # VIGIK1 A +564c505f4d41 # VIGIK1 B +ba5b895da162 # VIGIK1 B +# +# Vigik mystery Keys Mifare 1k EV1 (S50) +5c8ff9990da2 # 16 A +75ccb59c9bed # 17 A +d01afeeb890a # 16 B +4b791bea7bcc # 17 B +# 021209197591 # BTCINO UNDETERMINED SPREAKD 0x01->0x13 key 2ef720f2af76 414c41524f4e @@ -543,11 +559,13 @@ B66AC040203A 2E641D99AD5B AD4FB33388BF 69FB7B7CD8EE -2A6D9205E7CA +2A6D9205E7CA # Hotel 2a2c13cc242a 27FBC86A00D0 01FA3FC68349 # +13B91C226E56 # Hotel +# 6D44B5AAF464 # Smart Rider. Western Australian Public Transport Cards 1717E34A7A8A # Smart Rider. Western Australian Public Transport Cards # @@ -1044,37 +1062,21 @@ a2a3cca2a3cc # # Granada, ES Transport Card 000000270000 -0172066b2f03 -0172066b2f33 -066b2f230172 -0b0172066b2f 0f385ffb6529 -172066b2f2f0 -2066b2f27017 29173860fc76 -2f130172066b 2fca8492f386 385efa542907 3864fcba5937 -3b0172066b2f 3f3865fccb69 5c8ff9990da2 6291b3860fc8 63fca9492f38 -66b2f1f01720 -6b2f1b017206 -70172066b2f0 -70172066b2f3 -72066b2f2b01 863fcb959373 87291f3861fc 913385ffb752 -b2f170172066 b385efa64290 c9739233861f -f0f0172066b2 f3864fcca693 -f3f0172066b2 fc9839273862 # # various hotel keys @@ -1110,3 +1112,9 @@ fe04ecfe5577 6d9b485a4845 # 5a7a52d5e20d # Bosch Solution 6000 +# +# Found in TagInfo app +8A19D40CF2B5 # Hotel key card key +C1E51C63B8F5 # RATB key +1DB710648A65 +18F34C92A56E # E-GO card key From cd4b44008c0893122ccfa49550ec56694011c14e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Apr 2020 06:41:19 +0200 Subject: [PATCH 261/298] text --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ef686269..2250e33c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change - mfc default keys removed dublicates (@iceman1001) + . Change - mfc default keys got new entries found on TagInfo app (@anon) - Added `hf mfu ndef` - read and decode NDEF Type2 messages (@iceman1001) - Added `data ndef` - decode NDEF messages (@iceman1001) - Change - usb write's now waits for shiftregisters (@pwpiwi) From 1bb9b2b11253f17e6992633b1e0d1e2208d18b2f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Apr 2020 07:55:35 +0200 Subject: [PATCH 262/298] chg: fixed the h param in filename became help bug --- client/cmdflashmemspiffs.c | 133 +++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 59 deletions(-) diff --git a/client/cmdflashmemspiffs.c b/client/cmdflashmemspiffs.c index fa8cdbf16..788851f1a 100644 --- a/client/cmdflashmemspiffs.c +++ b/client/cmdflashmemspiffs.c @@ -18,48 +18,6 @@ static int CmdHelp(const char *Cmd); -static int CmdFlashMemSpiFFSMount(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - clearCommandBuffer(); - SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); - return PM3_SUCCESS; -} - -static int CmdFlashMemSpiFFSUnmount(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - clearCommandBuffer(); - SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); - return PM3_SUCCESS; -} - -static int CmdFlashMemSpiFFSTest(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - clearCommandBuffer(); - SendCommandNG(CMD_SPIFFS_TEST, NULL, 0); - return PM3_SUCCESS; -} - -static int CmdFlashMemSpiFFSCheck(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - clearCommandBuffer(); - SendCommandNG(CMD_SPIFFS_CHECK, NULL, 0); - return PM3_SUCCESS; -} - -static int CmdFlashMemSpiFFSTree(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - clearCommandBuffer(); - SendCommandNG(CMD_SPIFFS_PRINT_TREE, NULL, 0); - return PM3_SUCCESS; -} - -static int CmdFlashMemSpiFFSInfo(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - clearCommandBuffer(); - SendCommandNG(CMD_SPIFFS_PRINT_FSINFO, NULL, 0); - return PM3_SUCCESS; -} - static int usage_flashmemspiffs_remove(void) { PrintAndLogEx(NORMAL, "Remove a file from spiffs filesystem"); PrintAndLogEx(NORMAL, " Usage: mem spiffs remove "); @@ -107,16 +65,64 @@ static int usage_flashmemspiffs_load(void) { return PM3_SUCCESS; } + +static int CmdFlashMemSpiFFSMount(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); + return PM3_SUCCESS; +} + +static int CmdFlashMemSpiFFSUnmount(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); + return PM3_SUCCESS; +} + +static int CmdFlashMemSpiFFSTest(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_TEST, NULL, 0); + return PM3_SUCCESS; +} + +static int CmdFlashMemSpiFFSCheck(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_CHECK, NULL, 0); + return PM3_SUCCESS; +} + +static int CmdFlashMemSpiFFSTree(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_PRINT_TREE, NULL, 0); + return PM3_SUCCESS; +} + +static int CmdFlashMemSpiFFSInfo(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_PRINT_FSINFO, NULL, 0); + return PM3_SUCCESS; +} + static int CmdFlashMemSpiFFSRemove(const char *Cmd) { + int len = strlen(Cmd); + if (len < 1) { + return usage_flashmemspiffs_remove(); + } + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (len == 1 && ctmp == 'h') { + return usage_flashmemspiffs_remove(); + } + char filename[32] = {0}; bool errors = false; - /*char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') { - return usage_flashmemspiffs_remove(); - }*/ - if (param_getstr(Cmd, 0, filename, 32) >= 32) { PrintAndLogEx(FAILED, "Filename too long"); errors = true; @@ -134,15 +140,20 @@ static int CmdFlashMemSpiFFSRemove(const char *Cmd) { static int CmdFlashMemSpiFFSRename(const char *Cmd) { + int len = strlen(Cmd); + if (len < 1) { + return usage_flashmemspiffs_rename(); + } + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (len == 1 && ctmp == 'h') { + return usage_flashmemspiffs_rename(); + } + char srcfilename[32] = {0}; char destfilename[32] = {0}; bool errors = false; - /*char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') { - return usage_flashmemspiffs_rename(); - }*/ - if (param_getstr(Cmd, 0, srcfilename, 32) >= 32) { PrintAndLogEx(FAILED, "Source Filename too long"); errors = true; @@ -174,16 +185,21 @@ static int CmdFlashMemSpiFFSRename(const char *Cmd) { } static int CmdFlashMemSpiFFSCopy(const char *Cmd) { + int len = strlen(Cmd); + if (len < 1) { + return usage_flashmemspiffs_copy(); + } + char ctmp = tolower(param_getchar(Cmd, 0)); + if (len == 1 && ctmp == 'h') { + return usage_flashmemspiffs_copy(); + } + + char srcfilename[32] = {0}; char destfilename[32] = {0}; bool errors = false; - /*char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') { - return usage_flashmemspiffs_copy(); - }*/ - if (param_getstr(Cmd, 0, srcfilename, 32) >= 32) { PrintAndLogEx(FAILED, "Source Filename too long"); errors = true; @@ -441,8 +457,7 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - { - "copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, + {"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS FileSystem in FlashMEM (spiffs)" }, {"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented Filesystem"}, From 761860656eaa6ae5a7cedca1d45abe3d43fe8197 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Apr 2020 08:09:18 +0200 Subject: [PATCH 263/298] more pulic keys (@anon) --- client/cmdhfmfdes.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index d44f3443d..1ec0621f4 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -140,7 +140,7 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign // DESFire Ev2 - wanted // DESFire Ev3 - wanted - // Unknown - needs identification + // NTAG42x 1-3 NTAG 424 DNA TagTamper, NTAG426 TT { 0x04, 0x8A, 0x9B, 0x38, 0x0A, 0xF2, 0xEE, 0x1B, 0x98, 0xDC, 0x41, 0x7F, 0xEC, 0xC2, 0x63, 0xF8, @@ -160,7 +160,29 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0xDF, 0xD0, 0x41, 0x62, 0x91, 0xAF, 0xE1, 0xC7, 0x48, 0x25, 0x39, 0x25, 0xDA, 0x39, 0xA5, 0xF3, 0x9A, 0x1C, 0x55, 0x7F, 0xFA, 0xCD, 0x34, 0xC6, 0x2E - } + }, + + // NTAG42x 4 - NTAG426 + { + 0x04, 0xB3, 0x04, 0xDC, 0x4C, 0x61, 0x5F, 0x53, + 0x26, 0xFE, 0x93, 0x83, 0xDD, 0xEC, 0x9A, 0xA8, + 0x92, 0xDF, 0x3A, 0x57, 0xFA, 0x7F, 0xFB, 0x32, + 0x76, 0x19, 0x2B, 0xC0, 0xEA, 0xA2, 0x52, 0xED, + 0x45, 0xA8, 0x65, 0xE3, 0xB0, 0x93, 0xA3, 0xD0, + 0xDC, 0xE5, 0xBE, 0x29, 0xE9, 0x2F, 0x13, 0x92, + 0xCE, 0x7D, 0xE3, 0x21, 0xE3, 0xE5, 0xC5, 0x2B, 0x3A + }, + + // NTAG42x 3 - NTAG 424 DNA + { + 0x04, 0x0E, 0x98, 0xE1, 0x17, 0xAA, 0xA3, 0x64, + 0x57, 0xF4, 0x31, 0x73, 0xDC, 0x92, 0x0A, 0x87, + 0x57, 0x26, 0x7F, 0x44, 0xCE, 0x4E, 0xC5, 0xAD, + 0xD3, 0xC5, 0x40, 0x75, 0x57, 0x1A, 0xEB, 0xBF, + 0x7B, 0x94, 0x2A, 0x97, 0x74, 0xA1, 0xD9, 0x4A, + 0xD0, 0x25, 0x72, 0x42, 0x7E, 0x5A, 0xE0, 0xA2, + 0xDD, 0x36, 0x59, 0x1B, 0x1F, 0xB3, 0x4F, 0xCF, 0x3D + }, }; uint8_t i; @@ -185,6 +207,16 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign case 0: publickeyname = "NXP DESFire Light"; break; + case 1: + publickeyname = "NTAG42x 1-3 NTAG 424 DNA TagTamper, NTAG426 TT"; + break; + + case 3: + publickeyname = "NTAG42x 4 - NTAG426"; + break; + case 4: + publickeyname = "NTAG42x 3 - NTAG 424 DNA"; + break; default: publickeyname = "Unknown DESFire, post on forum"; break; From b91c4977af8126b1fbada47be79d8a3c8a9ee021 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Apr 2020 08:14:31 +0200 Subject: [PATCH 264/298] textual --- CHANGELOG.md | 1 + client/cmdhfmfdes.c | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2250e33c2..0bb2efbf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change - updated public keys info (@anon) - Change - mfc default keys removed dublicates (@iceman1001) . Change - mfc default keys got new entries found on TagInfo app (@anon) - Added `hf mfu ndef` - read and decode NDEF Type2 messages (@iceman1001) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 1ec0621f4..d9a30a877 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -137,7 +137,6 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0xDD, 0x36, 0x59, 0x1B, 0x1F, 0xB3, 0x4F, 0xCF, 0x3D }, - // DESFire Ev2 - wanted // DESFire Ev3 - wanted // NTAG42x 1-3 NTAG 424 DNA TagTamper, NTAG426 TT @@ -162,7 +161,7 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0x9A, 0x1C, 0x55, 0x7F, 0xFA, 0xCD, 0x34, 0xC6, 0x2E }, - // NTAG42x 4 - NTAG426 + // NTAG42x 4 - NTAG426, DESFire Ev2 { 0x04, 0xB3, 0x04, 0xDC, 0x4C, 0x61, 0x5F, 0x53, 0x26, 0xFE, 0x93, 0x83, 0xDD, 0xEC, 0x9A, 0xA8, @@ -210,9 +209,8 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign case 1: publickeyname = "NTAG42x 1-3 NTAG 424 DNA TagTamper, NTAG426 TT"; break; - case 3: - publickeyname = "NTAG42x 4 - NTAG426"; + publickeyname = "NTAG42x 4 - NTAG426, DESFire Ev2"; break; case 4: publickeyname = "NTAG42x 3 - NTAG 424 DNA"; From 3b4d5b56767b725a8beb22bf5ab221764459baad Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Apr 2020 08:25:24 +0200 Subject: [PATCH 265/298] remove dublicate --- client/cmdhfmfdes.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index d9a30a877..bfc842071 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -124,9 +124,10 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign #define PUBLIC_DESFIRE_ECDA_KEYLEN 57 + // DESFire Ev3 - wanted // ref: MIFARE Desfire Originality Signature Validation uint8_t nxp_desfire_keys[][PUBLIC_DESFIRE_ECDA_KEYLEN] = { - // DESFire Light + // NTAG42x 3 - NTAG 424 DNA, DESFire Light { 0x04, 0x0E, 0x98, 0xE1, 0x17, 0xAA, 0xA3, 0x64, 0x57, 0xF4, 0x31, 0x73, 0xDC, 0x92, 0x0A, 0x87, @@ -136,8 +137,6 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0xD0, 0x25, 0x72, 0x42, 0x7E, 0x5A, 0xE0, 0xA2, 0xDD, 0x36, 0x59, 0x1B, 0x1F, 0xB3, 0x4F, 0xCF, 0x3D }, - - // DESFire Ev3 - wanted // NTAG42x 1-3 NTAG 424 DNA TagTamper, NTAG426 TT { @@ -161,7 +160,7 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0x9A, 0x1C, 0x55, 0x7F, 0xFA, 0xCD, 0x34, 0xC6, 0x2E }, - // NTAG42x 4 - NTAG426, DESFire Ev2 + // NTAG42x 4 - NTAG426, DESFire Ev2 { 0x04, 0xB3, 0x04, 0xDC, 0x4C, 0x61, 0x5F, 0x53, 0x26, 0xFE, 0x93, 0x83, 0xDD, 0xEC, 0x9A, 0xA8, @@ -172,16 +171,6 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0xCE, 0x7D, 0xE3, 0x21, 0xE3, 0xE5, 0xC5, 0x2B, 0x3A }, - // NTAG42x 3 - NTAG 424 DNA - { - 0x04, 0x0E, 0x98, 0xE1, 0x17, 0xAA, 0xA3, 0x64, - 0x57, 0xF4, 0x31, 0x73, 0xDC, 0x92, 0x0A, 0x87, - 0x57, 0x26, 0x7F, 0x44, 0xCE, 0x4E, 0xC5, 0xAD, - 0xD3, 0xC5, 0x40, 0x75, 0x57, 0x1A, 0xEB, 0xBF, - 0x7B, 0x94, 0x2A, 0x97, 0x74, 0xA1, 0xD9, 0x4A, - 0xD0, 0x25, 0x72, 0x42, 0x7E, 0x5A, 0xE0, 0xA2, - 0xDD, 0x36, 0x59, 0x1B, 0x1F, 0xB3, 0x4F, 0xCF, 0x3D - }, }; uint8_t i; @@ -204,7 +193,7 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign char *publickeyname; switch(i) { case 0: - publickeyname = "NXP DESFire Light"; + publickeyname = "NTAG42x 3 - NTAG 424 DNA / DESFire Light"; break; case 1: publickeyname = "NTAG42x 1-3 NTAG 424 DNA TagTamper, NTAG426 TT"; @@ -212,9 +201,6 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign case 3: publickeyname = "NTAG42x 4 - NTAG426, DESFire Ev2"; break; - case 4: - publickeyname = "NTAG42x 3 - NTAG 424 DNA"; - break; default: publickeyname = "Unknown DESFire, post on forum"; break; From 61e59fa9138805238220a610c991759a228d46a1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Apr 2020 09:25:04 +0200 Subject: [PATCH 266/298] fix: 'hf mfu ndef - sig2 uses wrong index --- client/cmdhfmfu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 7acf7379b..09e0aff56 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2797,6 +2797,8 @@ static int CmdHF14MfuNDEF(const char *Cmd) { return PM3_ESOFT; } } + + PrintAndLogEx(INFO, "ICE:: %s", sprint_hex(records, maxsize)); DropField(); status = NDEFDecodeAndPrint(records, (size_t)maxsize, true); free(records); From 47d43cfc569957d44709a7645869827f4cac9273 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Apr 2020 09:34:03 +0200 Subject: [PATCH 267/298] text --- client/cmdhfmfu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 09e0aff56..af501d8f2 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2797,8 +2797,7 @@ static int CmdHF14MfuNDEF(const char *Cmd) { return PM3_ESOFT; } } - - PrintAndLogEx(INFO, "ICE:: %s", sprint_hex(records, maxsize)); + DropField(); status = NDEFDecodeAndPrint(records, (size_t)maxsize, true); free(records); From 16110985caf1bec1f0b8c7d393ad4e5cb27419ae Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Apr 2020 09:34:52 +0200 Subject: [PATCH 268/298] text --- client/mifare/ndef.c | 73 ++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index e3ba3997d..8f5e93a2e 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -145,18 +145,18 @@ static int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) static int ndefPrintHeader(NDEFHeader_t *header) { PrintAndLogEx(INFO, "Header:"); - PrintAndLogEx(NORMAL, "\tMessage Begin: %s", STRBOOL(header->MessageBegin)); - PrintAndLogEx(NORMAL, "\tMessage End: %s", STRBOOL(header->MessageEnd)); - PrintAndLogEx(NORMAL, "\tChunk Flag: %s", STRBOOL(header->ChunkFlag)); - PrintAndLogEx(NORMAL, "\tShort Record Bit: %s", STRBOOL(header->ShortRecordBit)); - PrintAndLogEx(NORMAL, "\tID Len Present: %s", STRBOOL(header->IDLenPresent)); - PrintAndLogEx(NORMAL, "\tType Name Format: [0x%02x] %s", header->TypeNameFormat, TypeNameFormat_s[header->TypeNameFormat]); + PrintAndLogEx(SUCCESS, "\tMessage Begin: %s", STRBOOL(header->MessageBegin)); + PrintAndLogEx(SUCCESS, "\tMessage End: %s", STRBOOL(header->MessageEnd)); + PrintAndLogEx(SUCCESS, "\tChunk Flag: %s", STRBOOL(header->ChunkFlag)); + PrintAndLogEx(SUCCESS, "\tShort Record Bit: %s", STRBOOL(header->ShortRecordBit)); + PrintAndLogEx(SUCCESS, "\tID Len Present: %s", STRBOOL(header->IDLenPresent)); + PrintAndLogEx(SUCCESS, "\tType Name Format: [0x%02x] %s", header->TypeNameFormat, TypeNameFormat_s[header->TypeNameFormat]); - PrintAndLogEx(NORMAL, "\tHeader length : %zu", header->len); - PrintAndLogEx(NORMAL, "\tType length : %zu", header->TypeLen); - PrintAndLogEx(NORMAL, "\tPayload length : %zu", header->PayloadLen); - PrintAndLogEx(NORMAL, "\tID length : %zu", header->IDLen); - PrintAndLogEx(NORMAL, "\tRecord length : %zu", header->RecLen); + PrintAndLogEx(SUCCESS, "\tHeader length : %zu", header->len); + PrintAndLogEx(SUCCESS, "\tType length : %zu", header->TypeLen); + PrintAndLogEx(SUCCESS, "\tPayload length : %zu", header->PayloadLen); + PrintAndLogEx(SUCCESS, "\tID length : %zu", header->IDLen); + PrintAndLogEx(SUCCESS, "\tRecord length : %zu", header->RecLen); return PM3_SUCCESS; } @@ -166,8 +166,8 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) { uint8_t sigType = sig[indx] & 0x7f; bool sigURI = sig[indx] & 0x80; - PrintAndLogEx(NORMAL, "\tsignature type: %s", ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA])); - PrintAndLogEx(NORMAL, "\tsignature uri: %s", (sigURI ? "present" : "not present")); + PrintAndLogEx(SUCCESS, "\tsignature type: %s", ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA])); + PrintAndLogEx(SUCCESS, "\tsignature uri: %s", (sigURI ? "present" : "not present")); size_t intsiglen = (sig[indx + 1] << 8) + sig[indx + 2]; // ecdsa 0x04 @@ -176,14 +176,14 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) { int slen = 24; if (sigType == stECDSA_P256) slen = 32; - PrintAndLogEx(NORMAL, "\tsignature [%zu]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); + PrintAndLogEx(SUCCESS, "\tsignature [%zu]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); uint8_t rval[300] = {0}; uint8_t sval[300] = {0}; int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); if (!res) { - PrintAndLogEx(NORMAL, "\t\tr: %s", sprint_hex(rval + 32 - slen, slen)); - PrintAndLogEx(NORMAL, "\t\ts: %s", sprint_hex(sval + 32 - slen, slen)); + PrintAndLogEx(SUCCESS, "\t\tr: %s", sprint_hex(rval + 32 - slen, slen)); + PrintAndLogEx(SUCCESS, "\t\ts: %s", sprint_hex(sval + 32 - slen, slen)); } } indx += intsiglen; @@ -191,7 +191,7 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) { if (sigURI) { size_t intsigurilen = (sig[indx] << 8) + sig[indx + 1]; indx += 2; - PrintAndLogEx(NORMAL, "\tsignature uri [%zu]: %.*s", intsigurilen, (int)intsigurilen, &sig[indx]); + PrintAndLogEx(SUCCESS, "\tsignature uri [%zu]: %.*s", intsigurilen, (int)intsigurilen, &sig[indx]); indx += intsigurilen; } @@ -199,8 +199,8 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) { uint8_t certCount = sig[indx] & 0x0f; bool certURI = sig[indx] & 0x80; - PrintAndLogEx(NORMAL, "\tcertificate format: %s", ((certFormat < sfNA) ? ndefCertificateFormat_s[certFormat] : ndefCertificateFormat_s[sfNA])); - PrintAndLogEx(NORMAL, "\tcertificates count: %d", certCount); + PrintAndLogEx(SUCCESS, "\tcertificate format: %s", ((certFormat < sfNA) ? ndefCertificateFormat_s[certFormat] : ndefCertificateFormat_s[sfNA])); + PrintAndLogEx(SUCCESS, "\tcertificates count: %d", certCount); // print certificates indx++; @@ -208,7 +208,7 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) { size_t intcertlen = (sig[indx + 1] << 8) + sig[indx + 2]; indx += 2; - PrintAndLogEx(NORMAL, "\tcertificate %d [%zu]: %s", i + 1, intcertlen, sprint_hex_inrow(&sig[indx], intcertlen)); + PrintAndLogEx(SUCCESS, "\tcertificate %d [%zu]: %s", i + 1, intcertlen, sprint_hex_inrow(&sig[indx], intcertlen)); indx += intcertlen; } @@ -216,7 +216,7 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) { if ((indx <= siglen) && certURI) { size_t inturilen = (sig[indx] << 8) + sig[indx + 1]; indx += 2; - PrintAndLogEx(NORMAL, "\tcertificate uri [%zu]: %.*s", inturilen, (int)inturilen, &sig[indx]); + PrintAndLogEx(SUCCESS, "\tcertificate uri [%zu]: %.*s", inturilen, (int)inturilen, &sig[indx]); } return PM3_SUCCESS; @@ -233,29 +233,28 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) { uint8_t hashType = sig[indx]; indx++; - PrintAndLogEx(NORMAL, "\tsignature type: %s", ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA])); - PrintAndLogEx(NORMAL, "\tsignature uri: %s", (sigURI ? "present" : "not present")); - PrintAndLogEx(NORMAL, "\thash type: %s", ((hashType == 0x02) ? "SHA-256" : "unknown")); + PrintAndLogEx(SUCCESS, "\tsignature type :\t" _GREEN_("%s"), ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA])); + PrintAndLogEx(SUCCESS, "\tsignature uri :\t\t%s", (sigURI ? "present" : "not present")); + PrintAndLogEx(SUCCESS, "\thash type :\t\t%s", ((hashType == 0x02) ? _GREEN_("SHA-256") : _RED_("unknown"))); size_t intsiglen = (sig[indx] << 8) + sig[indx + 1]; indx += 2; - + if (sigURI) { indx += 2; - PrintAndLogEx(NORMAL, "\tsignature uri [%zu]: %.*s", intsiglen, (int)intsiglen, &sig[indx]); + PrintAndLogEx(SUCCESS, "\tsignature uri [%zu]: %.*s", intsiglen, (int)intsiglen, &sig[indx]); indx += intsiglen; } else { - PrintAndLogEx(NORMAL, "\tsignature [%zu]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); + PrintAndLogEx(SUCCESS, "\tsignature [%zu]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); if (sigType == stECDSA_P192 || sigType == stECDSA_P256) { int slen = intsiglen / 2; if (slen == 24 || slen == 32) { - PrintAndLogEx(NORMAL, "\tsignature: ECDSA-%d", slen * 8); - PrintAndLogEx(NORMAL, "\t\tr: %s", sprint_hex(&sig[indx], slen)); - indx += slen; - PrintAndLogEx(NORMAL, "\t\ts: %s", sprint_hex(&sig[indx], slen)); + PrintAndLogEx(SUCCESS, "\tsignature : " _GREEN_("ECDSA-%d"), slen * 8); + PrintAndLogEx(SUCCESS, "\t\tr: %s", sprint_hex(&sig[indx], slen)); + PrintAndLogEx(SUCCESS, "\t\ts: %s", sprint_hex(&sig[indx + slen], slen)); } } else { - PrintAndLogEx(NORMAL, "\tsignature: unknown type"); + PrintAndLogEx(INFO, "\tsignature: unknown type"); } indx += intsiglen; } @@ -264,8 +263,8 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) { uint8_t certCount = sig[indx] & 0x0f; bool certURI = sig[indx] & 0x80; - PrintAndLogEx(NORMAL, "\tcertificate format: %s", ((certFormat < sfNA) ? ndefCertificateFormat_s[certFormat] : ndefCertificateFormat_s[sfNA])); - PrintAndLogEx(NORMAL, "\tcertificates count: %d", certCount); + PrintAndLogEx(SUCCESS, "\tcertificate format : " _GREEN_("%s"), ((certFormat < sfNA) ? ndefCertificateFormat_s[certFormat] : ndefCertificateFormat_s[sfNA])); + PrintAndLogEx(SUCCESS, "\tcertificates count : %d", certCount); // print certificates indx++; @@ -273,7 +272,7 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) { size_t intcertlen = (sig[indx + 1] << 8) + sig[indx + 2]; indx += 2; - PrintAndLogEx(NORMAL, "\tcertificate %d [%zu]: %s", i + 1, intcertlen, sprint_hex_inrow(&sig[indx], intcertlen)); + PrintAndLogEx(SUCCESS, "\tcertificate %d [%zu]: %s", i + 1, intcertlen, sprint_hex_inrow(&sig[indx], intcertlen)); indx += intcertlen; } @@ -281,14 +280,14 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) { if ((indx <= siglen) && certURI) { size_t inturilen = (sig[indx] << 8) + sig[indx + 1]; indx += 2; - PrintAndLogEx(NORMAL, "\tcertificate uri [%zu]: %.*s", inturilen, (int)inturilen, &sig[indx]); + PrintAndLogEx(SUCCESS, "\tcertificate uri [%zu]: %.*s", inturilen, (int)inturilen, &sig[indx]); } return PM3_SUCCESS; }; static int ndefDecodeSig(uint8_t *sig, size_t siglen) { - PrintAndLogEx(NORMAL, "\tsignature version: 0x%02x", sig[0]); + PrintAndLogEx(SUCCESS, "\tsignature version : \t" _GREEN_("0x%02x"), sig[0]); if (sig[0] != 0x01 && sig[0] != 0x20) { PrintAndLogEx(ERR, "signature version unknown."); return PM3_ESOFT; From f0ffe79569d1ae31d03a430db429da7de5dd5ef2 Mon Sep 17 00:00:00 2001 From: Daniel Underhay <27876907+dunderhay@users.noreply.github.com> Date: Fri, 3 Apr 2020 00:14:15 +1100 Subject: [PATCH 269/298] Add colour to hf mf chk and fchk output --- CHANGELOG.md | 1 + client/cmdhfmf.c | 51 +++++++++++++++++++------------------- client/mifare/mifarehost.c | 2 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bb2efbf7..9091fd4ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Add colour to `hf mf chk` and `hf mf fchk` (@dunderhay) - Change - updated public keys info (@anon) - Change - mfc default keys removed dublicates (@iceman1001) . Change - mfc default keys got new entries found on TagInfo app (@anon) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 89519b282..1a3c86972 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -248,10 +248,10 @@ static int usage_hf14_chk(void) { PrintAndLogEx(NORMAL, " t write keys to emulator memory\n"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf chk 0 A 1234567890ab -- target block 0, Key A using key 1234567890ab"); - PrintAndLogEx(NORMAL, " hf mf chk 0 A mfc_default_keys.dic -- target block 0, Key A using default dictionary file"); - PrintAndLogEx(NORMAL, " hf mf chk *1 ? t -- target all blocks, all keys, 1K, write to emulator memory"); - PrintAndLogEx(NORMAL, " hf mf chk *1 ? d -- target all blocks, all keys, 1K, write to file"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk 0 A 1234567890ab")" -- target block 0, Key A using key 1234567890ab"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk 0 A mfc_default_keys.dic")" -- target block 0, Key A using default dictionary file"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk *1 ? t")" -- target all blocks, all keys, 1K, write to emulator memory"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk *1 ? d")" -- target all blocks, all keys, 1K, write to file"); return PM3_SUCCESS; } static int usage_hf14_chk_fast(void) { @@ -269,12 +269,12 @@ static int usage_hf14_chk_fast(void) { PrintAndLogEx(NORMAL, " m use dictionary from flashmemory\n"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 1234567890ab -- target 1K using key 1234567890ab"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 mfc_default_keys.dic -- target 1K using default dictionary file"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 t -- target 1K, write to emulator memory"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 d -- target 1K, write to file"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 1234567890ab")" -- target 1K using key 1234567890ab"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 mfc_default_keys.dic")" -- target 1K using default dictionary file"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 t")" -- target 1K, write to emulator memory"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 d")" -- target 1K, write to file"); if (IfPm3Flash()) - PrintAndLogEx(NORMAL, " hf mf fchk 1 m -- target 1K, use dictionary from flashmemory"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf fchk 1 m")" -- target 1K, use dictionary from flashmemory"); return PM3_SUCCESS; } /* @@ -1447,7 +1447,7 @@ static int CmdHF14AMfNested(const char *Cmd) { jumptoend: PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "found keys:"); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); //print them printKeyTable(SectorsCnt, e_sector); @@ -1652,7 +1652,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { jumptoend: PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "found keys:"); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); //print them printKeyTable(SectorsCnt, e_sector); @@ -2463,7 +2463,7 @@ all_found: // Show the results to the user PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "found keys:"); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); printKeyTable(sectors_cnt, e_sector); @@ -2715,7 +2715,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { // strategys. 1= deep first on sector 0 AB, 2= width first on all sectors for (uint8_t strategy = 1; strategy < 3; strategy++) { - PrintAndLogEx(SUCCESS, "Running strategy %u", strategy); + PrintAndLogEx(INFO, "Running strategy %u", strategy); // main keychunk loop for (i = 0; i < keycnt; i += chunksize) { @@ -2746,7 +2746,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { } out: t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time in checkkeys (fast): %.1fs\n", (float)(t1 / 1000.0)); + PrintAndLogEx(INFO, "Time in checkkeys (fast): %.1fs\n", (float)(t1 / 1000.0)); // check.. uint8_t found_keys = 0; @@ -2764,7 +2764,7 @@ out: } else { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "found keys:"); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); printKeyTable(sectorsCnt, e_sector); @@ -3027,7 +3027,7 @@ static int CmdHF14AMfChk(const char *Cmd) { } } t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "\nTime in checkkeys: %.0f seconds\n", (float)t1 / 1000.0); + PrintAndLogEx(INFO, "\nTime in checkkeys: %.0f seconds\n", (float)t1 / 1000.0); // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? @@ -3075,7 +3075,7 @@ static int CmdHF14AMfChk(const char *Cmd) { out: PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "found keys:"); + PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); //print keys if (SectorsCnt == 1) @@ -3346,7 +3346,7 @@ static int CmdHF14AMfSim(const char *Cmd) { } showSectorTable(); } - + k_sectorsCount = MIFARE_4K_MAXSECTOR; return PM3_SUCCESS; } @@ -3549,9 +3549,9 @@ void printKeyTable(uint8_t sectorscnt, sector_t *e_sector) { void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_sector) { char strA[12 + 1] = {0}; char strB[12 + 1] = {0}; - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - PrintAndLogEx(NORMAL, "|sec| key A |res| key B |res|"); - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + PrintAndLogEx(SUCCESS, "|-----|----------------|---|----------------|---|"); + PrintAndLogEx(SUCCESS, "| Sec | key A |res| key B |res|"); + PrintAndLogEx(SUCCESS, "|-----|----------------|---|----------------|---|"); for (uint8_t i = 0; i < sectorscnt; i++) { snprintf(strA, sizeof(strA), "------------"); @@ -3564,7 +3564,7 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); if (e_sector[i].foundKey[0] > 1) { - PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%c")"| %s | " _YELLOW_("%c")"|" + PrintAndLogEx(SUCCESS, "| "_YELLOW_("%03d")"| " _GREEN_("%s")" | " _YELLOW_("%c")"| " _GREEN_("%s")" | " _YELLOW_("%c")"|" , i , strA, e_sector[i].foundKey[0] , strB, e_sector[i].foundKey[1] @@ -3576,14 +3576,14 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto if (start_sector == 0) s = i; - PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%d")"| %s | " _YELLOW_("%d")"|" + PrintAndLogEx(SUCCESS, "| "_YELLOW_("%03d")"| " _GREEN_("%s")" | " _YELLOW_("%d")"| " _GREEN_("%s")" | " _YELLOW_("%d")"|" , s , strA, e_sector[i].foundKey[0] , strB, e_sector[i].foundKey[1] ); } } - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + PrintAndLogEx(SUCCESS, "|-----|----------------|---|----------------|---|"); if (e_sector[0].foundKey[0] > 1) { PrintAndLogEx(INFO, "( " @@ -3597,7 +3597,7 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto ")" ); } else { - PrintAndLogEx(INFO, "( " _YELLOW_("0") ":Failed / " _YELLOW_("1") ":Success)"); + PrintAndLogEx(SUCCESS, "( " _YELLOW_("0") ":Failed / " _YELLOW_("1") ":Success)"); } } @@ -4955,4 +4955,3 @@ int CmdHFMF(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } - diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 9d1293b5b..1d19a7c6d 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -221,7 +221,7 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, // time to convert the returned data. uint8_t curr_keys = resp.oldarg[0]; - PrintAndLogEx(SUCCESS, "\nChunk: %.1fs | found %u/%u keys (%u)", (float)(t2 / 1000.0), curr_keys, (sectorsCnt << 1), size); + PrintAndLogEx(INFO, "\nChunk: %.1fs | found %u/%u keys (%u)", (float)(t2 / 1000.0), curr_keys, (sectorsCnt << 1), size); // all keys? if (curr_keys == sectorsCnt * 2 || lastChunk) { From e64e5fb65c15102123b68fec463f8ff98cf55477 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 2 Apr 2020 18:42:44 +0300 Subject: [PATCH 270/298] added some ndef tlv types --- client/mifare/ndef.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 8f5e93a2e..b7c4a8108 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -422,6 +422,7 @@ int NDEFRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { return PM3_SUCCESS; } +// http://apps4android.org/nfc-specifications/NFCForum-TS-Type-2-Tag_1.1.pdf int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { size_t indx = 0; @@ -442,6 +443,24 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { indx += len; break; } + case 0x01: { + indx++; + uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); + PrintAndLogEx(INFO, "-- NDEF Lock Control."); + if (len != 3) + PrintAndLogEx(WARNING, "NDEF Lock Control block size must be 3 instead of %d.", len); + indx += len; + break; + } + case 0x02: { + indx++; + uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); + PrintAndLogEx(INFO, "-- NDEF Memory Control."); + if (len != 3) + PrintAndLogEx(WARNING, "NDEF Memory Control block size must be 3 instead of %d.", len); + indx += len; + break; + } case 0x03: { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); From 627499247f37c4a7df03673e539bc566d1ccbd65 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 2 Apr 2020 20:21:51 +0300 Subject: [PATCH 271/298] TLV ndef lock and memory control decoding --- client/mifare/ndef.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index b7c4a8108..8974334eb 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -447,8 +447,20 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); PrintAndLogEx(INFO, "-- NDEF Lock Control."); - if (len != 3) + if (len != 3) { PrintAndLogEx(WARNING, "NDEF Lock Control block size must be 3 instead of %d.", len); + } else { + uint8_t ByteOffset = (ndef[indx] >> 4) & 0x0f; + uint8_t PagesAddr = ndef[indx] & 0x0f; + uint8_t Size = ndef[indx + 1]; + uint8_t BytesPerPage = (ndef[indx + 2] >> 4) & 0x0f; + uint8_t BytesLockedPerLockBit = ndef[indx + 2] & 0x0f; + PrintAndLogEx(SUCCESS, "PagesAddr. number of pages: %d", PagesAddr); + PrintAndLogEx(SUCCESS, "ByteOffset. number of bytes: %d", ByteOffset); + PrintAndLogEx(SUCCESS, "Size. size in bits of the lock area: %d. bytes approx: %d", Size, Size / 8); + PrintAndLogEx(SUCCESS, "BytesPerPage. number of bytes per page: %d", BytesPerPage); + PrintAndLogEx(SUCCESS, "BytesLockedPerLockBit. number of bytes that each dynamic lock bit is able to lock: %d", BytesLockedPerLockBit); + } indx += len; break; } @@ -456,8 +468,18 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); PrintAndLogEx(INFO, "-- NDEF Memory Control."); - if (len != 3) + if (len != 3) { PrintAndLogEx(WARNING, "NDEF Memory Control block size must be 3 instead of %d.", len); + } else { + uint8_t PagesAddr = (ndef[indx] >> 4) & 0x0f; + uint8_t ByteOffset = ndef[indx] & 0x0f; + uint8_t Size = ndef[indx + 1]; + uint8_t BytesPerPage = (ndef[indx + 2] >> 4) & 0x0f; + PrintAndLogEx(SUCCESS, "PagesAddr. number of pages: %d", PagesAddr); + PrintAndLogEx(SUCCESS, "ByteOffset. number of bytes: %d", ByteOffset); + PrintAndLogEx(SUCCESS, "Size. size in bits of the reserved area: %d. bytes approx: %d", Size, Size / 8); + PrintAndLogEx(SUCCESS, "BytesPerPage. number of bytes per page: %d", BytesPerPage); + } indx += len; break; } From 13d3b38eee9710f7730610db786951a1bc6e92a9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 2 Apr 2020 20:26:46 +0300 Subject: [PATCH 272/298] byte order according to http://apps4android.org/nfc-specifications/NFCForum-TS-Type-2-Tag_1.1.pdf page 10, sample: page 31 --- client/mifare/ndef.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 8974334eb..a563e9fd5 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -450,11 +450,11 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { if (len != 3) { PrintAndLogEx(WARNING, "NDEF Lock Control block size must be 3 instead of %d.", len); } else { - uint8_t ByteOffset = (ndef[indx] >> 4) & 0x0f; - uint8_t PagesAddr = ndef[indx] & 0x0f; + uint8_t PagesAddr = (ndef[indx] >> 4) & 0x0f; + uint8_t ByteOffset = ndef[indx] & 0x0f; uint8_t Size = ndef[indx + 1]; - uint8_t BytesPerPage = (ndef[indx + 2] >> 4) & 0x0f; - uint8_t BytesLockedPerLockBit = ndef[indx + 2] & 0x0f; + uint8_t BytesLockedPerLockBit = (ndef[indx + 2] >> 4) & 0x0f; + uint8_t BytesPerPage = ndef[indx + 2] & 0x0f; PrintAndLogEx(SUCCESS, "PagesAddr. number of pages: %d", PagesAddr); PrintAndLogEx(SUCCESS, "ByteOffset. number of bytes: %d", ByteOffset); PrintAndLogEx(SUCCESS, "Size. size in bits of the lock area: %d. bytes approx: %d", Size, Size / 8); @@ -474,7 +474,7 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { uint8_t PagesAddr = (ndef[indx] >> 4) & 0x0f; uint8_t ByteOffset = ndef[indx] & 0x0f; uint8_t Size = ndef[indx + 1]; - uint8_t BytesPerPage = (ndef[indx + 2] >> 4) & 0x0f; + uint8_t BytesPerPage = ndef[indx + 2] & 0x0f; PrintAndLogEx(SUCCESS, "PagesAddr. number of pages: %d", PagesAddr); PrintAndLogEx(SUCCESS, "ByteOffset. number of bytes: %d", ByteOffset); PrintAndLogEx(SUCCESS, "Size. size in bits of the reserved area: %d. bytes approx: %d", Size, Size / 8); From 4418281284656c4811da7f296ae385221582f20d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Apr 2020 21:16:28 +0200 Subject: [PATCH 273/298] chg: 'hf mfu ndef' - text record now correctly decode language and text parts. Thanks @bettse! --- client/mifare/ndef.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index a563e9fd5..996d8d767 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -45,7 +45,6 @@ static const char *ndefSigType_s[] = { "ECDSA-B233", "ECDSA-P256", "n/a" - }; static const char *ndefCertificateFormat_s[] = { @@ -229,7 +228,7 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) { uint8_t sigType = sig[indx] & 0x7f; bool sigURI = sig[indx] & 0x80; indx++; - + uint8_t hashType = sig[indx]; indx++; @@ -292,13 +291,13 @@ static int ndefDecodeSig(uint8_t *sig, size_t siglen) { PrintAndLogEx(ERR, "signature version unknown."); return PM3_ESOFT; } - + if (sig[0] == 0x01) return ndefDecodeSig1(sig, siglen); - + if (sig[0] == 0x20) return ndefDecodeSig2(sig, siglen); - + return PM3_ESOFT; } @@ -307,15 +306,24 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) { switch (ndef->TypeNameFormat) { case tnfWellKnownRecord: PrintAndLogEx(INFO, "Well Known Record"); - PrintAndLogEx(INFO, "\ttype : %.*s", (int)ndef->TypeLen, ndef->Type); + PrintAndLogEx(INFO, "\ttype\t: %.*s", (int)ndef->TypeLen, ndef->Type); if (!strncmp((char *)ndef->Type, "T", ndef->TypeLen)) { - PrintAndLogEx(INFO, "\ttext : " _GREEN_("%.*s"), (int)ndef->PayloadLen, ndef->Payload); + uint8_t utf8 = (ndef->Payload[0] >> 7); + uint8_t lc_len = ndef->Payload[0] & 0x3F; + PrintAndLogEx(INFO, + "\tUTF %d\t: " _GREEN_("%.*s") ", " _GREEN_("%.*s"), + (utf8 == 0) ? 8 : 16, + lc_len, + ndef->Payload + 1, + (int)ndef->PayloadLen - 1 - lc_len, + ndef->Payload + 1 + lc_len + ); } if (!strncmp((char *)ndef->Type, "U", ndef->TypeLen)) { PrintAndLogEx(INFO - , "\turi : " _GREEN_("%s%.*s") + , "\turi\t: " _GREEN_("%s%.*s") , (ndef->Payload[0] <= 0x23 ? URI_s[ndef->Payload[0]] : "[err]") , (int)(ndef->PayloadLen - 1) , &ndef->Payload[1] @@ -436,7 +444,6 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { case 0x00: { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); - PrintAndLogEx(SUCCESS, "-- NDEF NULL block."); if (len) PrintAndLogEx(WARNING, "NDEF NULL block size must be 0, got %d bytes", len); @@ -455,11 +462,11 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { uint8_t Size = ndef[indx + 1]; uint8_t BytesLockedPerLockBit = (ndef[indx + 2] >> 4) & 0x0f; uint8_t BytesPerPage = ndef[indx + 2] & 0x0f; - PrintAndLogEx(SUCCESS, "PagesAddr. number of pages: %d", PagesAddr); - PrintAndLogEx(SUCCESS, "ByteOffset. number of bytes: %d", ByteOffset); - PrintAndLogEx(SUCCESS, "Size. size in bits of the lock area: %d. bytes approx: %d", Size, Size / 8); - PrintAndLogEx(SUCCESS, "BytesPerPage. number of bytes per page: %d", BytesPerPage); - PrintAndLogEx(SUCCESS, "BytesLockedPerLockBit. number of bytes that each dynamic lock bit is able to lock: %d", BytesLockedPerLockBit); + PrintAndLogEx(SUCCESS, "PagesAddr. number of pages: %d", PagesAddr); + PrintAndLogEx(SUCCESS, "ByteOffset. number of bytes: %d", ByteOffset); + PrintAndLogEx(SUCCESS, "Size. size in bits of the lock area: %d. bytes approx: %d", Size, Size / 8); + PrintAndLogEx(SUCCESS, "BytesPerPage. number of bytes per page: %d", BytesPerPage); + PrintAndLogEx(SUCCESS, "BytesLockedPerLockBit. number of bytes that each dynamic lock bit is able to lock: %d", BytesLockedPerLockBit); } indx += len; break; @@ -475,10 +482,10 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { uint8_t ByteOffset = ndef[indx] & 0x0f; uint8_t Size = ndef[indx + 1]; uint8_t BytesPerPage = ndef[indx + 2] & 0x0f; - PrintAndLogEx(SUCCESS, "PagesAddr. number of pages: %d", PagesAddr); - PrintAndLogEx(SUCCESS, "ByteOffset. number of bytes: %d", ByteOffset); - PrintAndLogEx(SUCCESS, "Size. size in bits of the reserved area: %d. bytes approx: %d", Size, Size / 8); - PrintAndLogEx(SUCCESS, "BytesPerPage. number of bytes per page: %d", BytesPerPage); + PrintAndLogEx(SUCCESS, "PagesAddr. number of pages: %d", PagesAddr); + PrintAndLogEx(SUCCESS, "ByteOffset. number of bytes: %d", ByteOffset); + PrintAndLogEx(SUCCESS, "Size. size in bits of the reserved area: %d. bytes approx: %d", Size, Size / 8); + PrintAndLogEx(SUCCESS, "BytesPerPage. number of bytes per page: %d", BytesPerPage); } indx += len; break; From 3484cf165565dc84db851a49b2a06084063b5d3f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Apr 2020 07:22:54 +0200 Subject: [PATCH 274/298] text and return codes --- client/cmdhficlass.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index f4a62b6c1..72c5d885d 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -462,7 +462,7 @@ static int CmdHFiClassSim(const char *Cmd) { PrintAndLogEx(ERR, "A CSN should consist of 16 HEX symbols"); return usage_hf_iclass_sim(); } - PrintAndLogEx(NORMAL, " simtype: %02x csn: %s", simType, sprint_hex(CSN, 8)); + PrintAndLogEx(INFO, " simtype: %02x CSN: %s", simType, sprint_hex(CSN, 8)); } if (simType > 4) { @@ -505,7 +505,7 @@ static int CmdHFiClassSim(const char *Cmd) { PrintAndLogEx(INFO, "press Enter to cancel"); PacketResponseNG resp; clearCommandBuffer(); - SendCommandOLD(CMD_HF_ICLASS_SIMULATE, simType, NUM_CSNS, 0, csns, 8 * NUM_CSNS); + SendCommandMIX(CMD_HF_ICLASS_SIMULATE, simType, NUM_CSNS, 0, csns, 8 * NUM_CSNS); while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { tries++; @@ -520,7 +520,7 @@ static int CmdHFiClassSim(const char *Cmd) { } uint8_t num_mac = resp.oldarg[1]; bool success = (NUM_CSNS == num_mac); - PrintAndLogEx(NORMAL, "[%c] %d out of %d MAC obtained [%s]", (success) ? '+' : '!', num_mac, NUM_CSNS, (success) ? "OK" : "FAIL"); + PrintAndLogEx( (success) ? SUCCESS : WARNING, "[%c] %d out of %d MAC obtained [%s]", (success) ? '+' : '!', num_mac, NUM_CSNS, (success) ? "OK" : "FAIL"); if (num_mac == 0) break; @@ -554,7 +554,7 @@ static int CmdHFiClassSim(const char *Cmd) { PrintAndLogEx(INFO, "press Enter to cancel"); PacketResponseNG resp; clearCommandBuffer(); - SendCommandOLD(CMD_HF_ICLASS_SIMULATE, simType, NUM_CSNS, 0, csns, 8 * NUM_CSNS); + SendCommandMIX(CMD_HF_ICLASS_SIMULATE, simType, NUM_CSNS, 0, csns, 8 * NUM_CSNS); while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { tries++; @@ -569,7 +569,7 @@ static int CmdHFiClassSim(const char *Cmd) { } uint8_t num_mac = resp.oldarg[1]; bool success = ((NUM_CSNS * 2) == num_mac); - PrintAndLogEx(NORMAL, "[%c] %d out of %d MAC obtained [%s]", (success) ? '+' : '!', num_mac, NUM_CSNS * 2, (success) ? "OK" : "FAIL"); + PrintAndLogEx((success) ? SUCCESS : WARNING, "[%c] %d out of %d MAC obtained [%s]", (success) ? '+' : '!', num_mac, NUM_CSNS * 2, (success) ? "OK" : "FAIL"); if (num_mac == 0) break; @@ -645,7 +645,7 @@ static int CmdHFiClassReader_Replay(const char *Cmd) { if (param_gethex(Cmd, 0, MAC, 8)) { PrintAndLogEx(FAILED, "MAC must include 8 HEX symbols"); - return 1; + return PM3_EINVARG; } clearCommandBuffer(); @@ -1269,7 +1269,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { break; } // dump cmd switch off at device when finised. - + uint32_t blocksRead = resp.oldarg[1]; uint8_t isOK = resp.oldarg[0] & 0xff; if (!isOK && !blocksRead) { @@ -1949,21 +1949,21 @@ static int CmdHFiClassReadTagFile(const char *Cmd) { if (fsize <= 0) { PrintAndLogEx(ERR, "Error, when getting filesize"); fclose(f); - return 1; + return PM3_EFILE; } uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(WARNING, "Failed to allocate memory"); fclose(f); - return 1; + return PM3_EMALLOC; } size_t bytes_read = fread(dump, 1, fsize, f); fclose(f); uint8_t *csn = dump; - PrintAndLogEx(NORMAL, "------+--+-------------------------+\n"); - PrintAndLogEx(NORMAL, "CSN |00| %s|\n", sprint_hex(csn, 8)); + PrintAndLogEx(INFO, "------+--+-------------------------+\n"); + PrintAndLogEx(INFO, "CSN |00| %s|\n", sprint_hex(csn, 8)); printIclassDumpContents(dump, startblock, endblock, bytes_read); free(dump); return PM3_SUCCESS; @@ -2087,7 +2087,7 @@ static int CmdHFiClassCalcNewKey(const char *Cmd) { uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; if (!select_only(CSN, CCNR, false, true)) { DropField(); - return 0; + return PM3_ESOFT; } } @@ -2109,21 +2109,21 @@ static int loadKeys(char *filename) { if (fsize <= 0) { PrintAndLogEx(ERR, "Error, when getting filesize"); fclose(f); - return 1; + return PM3_EFILE; } uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(WARNING, "Failed to allocate memory"); fclose(f); - return 1; + return PM3_EMALLOC; } size_t bytes_read = fread(dump, 1, fsize, f); fclose(f); if (bytes_read > ICLASS_KEYS_MAX * 8) { PrintAndLogEx(WARNING, "File is too long to load - bytes: %zu", bytes_read); free(dump); - return 0; + return PM3_EFILE; } uint8_t i = 0; for (; i < bytes_read / 8; i++) From 1b6164be07917fcbef5cba7d9f6bf759569aa27b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Apr 2020 08:35:32 +0200 Subject: [PATCH 275/298] change, sprint_hex no long has an extra space in the end. This will break some output designs :smile: --- client/ui.c | 5 +++-- client/util.c | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/client/ui.c b/client/ui.c index bac8b2956..5097b28f1 100644 --- a/client/ui.c +++ b/client/ui.c @@ -80,10 +80,11 @@ int searchHomeFilePath(char **foundpath, const char *filename, bool create_home) if ((result != 0) && create_home) { #ifdef _WIN32 - if (_mkdir(path)) { + if (_mkdir(path)) #else - if (mkdir(path, 0700)) { + if (mkdir(path, 0700)) #endif + { fprintf(stderr, "Could not create user directory %s\n", path); free(path); return PM3_EFILE; diff --git a/client/util.c b/client/util.c index 226255536..36362f83b 100644 --- a/client/util.c +++ b/client/util.c @@ -211,6 +211,9 @@ void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex for (; i < minStrLen; i++, tmp += 1) sprintf(tmp, " "); + // remove last space + --tmp; + *tmp = '\0'; return; } @@ -346,7 +349,7 @@ char *sprint_hex_ascii(const uint8_t *data, const size_t len) { memset(buf, 0x00, UTIL_BUFFER_SIZE_SPRINT); size_t max_len = (len > 1010) ? 1010 : len; - snprintf(tmp, UTIL_BUFFER_SIZE_SPRINT, "%s| ", sprint_hex(data, max_len)); + snprintf(tmp, UTIL_BUFFER_SIZE_SPRINT, "%s | ", sprint_hex(data, max_len)); size_t i = 0; size_t pos = (max_len * 3) + 2; From 98553439aa5a2233bab3426e62a54ac50bdbca8b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Apr 2020 08:36:55 +0200 Subject: [PATCH 276/298] change 'hf iclass readtagfile' - improved param handling, better helptext, f filename s startblock e endblock --- client/cmdhficlass.c | 87 +++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 72c5d885d..a1a8c93b2 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -48,7 +48,7 @@ static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { }; static int usage_hf_iclass_sim(void) { - PrintAndLogEx(NORMAL, "Usage: hf iclass sim