mirror of
https://github.com/RfidResearchGroup/miLazyCracker.git
synced 2026-05-12 11:20:09 -07:00
updating scripts and patches
This commit is contained in:
committed by
iAmNotSuperman
parent
4a2cae50bc
commit
3d600ec4ea
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,17 @@
|
||||
# miLazyCracker
|
||||
Mifare Classic Plus - Hardnested Attack Implementation for SCL3711 LibNFC USB reader
|
||||
Mifare Classic Plus - Hardnested Attack Implementation for LibNFC USB readers (SCL3711, ASK LoGO, etc)
|
||||
|
||||
Installation:
|
||||
```bash
|
||||
./miLazyCrackerFreshInstall.sh
|
||||
```
|
||||
|
||||
Usage example: place a tag and enjoy
|
||||
```bash
|
||||
mkdir mydumps
|
||||
cd mydumps
|
||||
miLazyCracker
|
||||
```
|
||||
|
||||
This tool is comprised of work from:
|
||||
- Aram Verstegen (https://github.com/aczid/crypto1_bs)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
diff --git a/libnfc_crypto1_crack.c b/libnfc_crypto1_crack.c
|
||||
index 8a53f64..21feed2 100644
|
||||
--- a/libnfc_crypto1_crack.c
|
||||
+++ b/libnfc_crypto1_crack.c
|
||||
@@ -713,6 +713,17 @@ int main (int argc, const char * argv[]) {
|
||||
return 1;
|
||||
} else {
|
||||
printf("Found key: %012"PRIx64"\n", found_key);
|
||||
+ if (argc==7) {
|
||||
+ FILE *fpKey = NULL;
|
||||
+ fpKey = fopen(argv[6], "a");
|
||||
+ if (fpKey) {
|
||||
+ fprintf(fpKey, "%012llx\r\n", found_key);
|
||||
+ fclose(fpKey);
|
||||
+ } else {
|
||||
+ fprintf(stderr, "Cannot open: %s, exiting\n", argv[6]);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
printf("Tested %zu states\n", total_states_tested);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
||||
diff --git a/src/mfoc.c b/src/mfoc.c
|
||||
index 32ef6f7..babbe15 100644
|
||||
--- a/src/mfoc.c
|
||||
+++ b/src/mfoc.c
|
||||
@@ -756,7 +756,7 @@ int main(int argc, char *const argv[])
|
||||
}
|
||||
|
||||
// Finally save all keys + data to file
|
||||
- uint16_t dump_size = (t.num_blocks + 1) * t.num_sectors;
|
||||
+ uint16_t dump_size = (t.num_blocks + 1) * 16;
|
||||
if (fwrite(&mtDump, 1, dump_size, pfDump) != dump_size) {
|
||||
fprintf(stdout, "Error, cannot write dump\n");
|
||||
fclose(pfDump);
|
||||
@@ -0,0 +1,21 @@
|
||||
diff --git a/src/mfoc.c b/src/mfoc.c
|
||||
index 2c06b16..469b138 100644
|
||||
--- a/src/mfoc.c
|
||||
+++ b/src/mfoc.c
|
||||
@@ -307,7 +307,7 @@ int main(int argc, char *const argv[])
|
||||
}
|
||||
|
||||
// Test if a compatible MIFARE tag is used
|
||||
- if ((t.nt.nti.nai.btSak & 0x08) == 0) {
|
||||
+ if (((t.nt.nti.nai.btSak & 0x08) == 0) && (t.nt.nti.nai.btSak != 0x01)) {
|
||||
ERR("only Mifare Classic is supported");
|
||||
goto error;
|
||||
}
|
||||
@@ -318,6 +318,7 @@ int main(int argc, char *const argv[])
|
||||
// see http://www.nxp.com/documents/application_note/AN10833.pdf Section 3.2
|
||||
switch (t.nt.nti.nai.btSak)
|
||||
{
|
||||
+ case 0x01:
|
||||
case 0x08:
|
||||
case 0x88:
|
||||
printf("Found Mifare Classic 1k tag\n");
|
||||
@@ -0,0 +1,160 @@
|
||||
diff --git a/src/mfoc.c b/src/mfoc.c
|
||||
index 32ef6f7..889669d 100644
|
||||
--- a/src/mfoc.c
|
||||
+++ b/src/mfoc.c
|
||||
@@ -58,6 +58,48 @@
|
||||
|
||||
nfc_context *context;
|
||||
|
||||
+uint64_t knownKey = 0;
|
||||
+char knownKeyLetter = 'A';
|
||||
+uint32_t knownSector = 0;
|
||||
+uint32_t unknownSector = 0;
|
||||
+char unknownKeyLetter = 'A';
|
||||
+uint32_t unexpected_random = 0;
|
||||
+
|
||||
+// Determine the distance between two nonces.
|
||||
+// Assume that the difference is small, but we don't know which is first.
|
||||
+// Therefore try in alternating directions.
|
||||
+int32_t dist_nt(uint32_t nt1, uint32_t nt2) {
|
||||
+
|
||||
+ if (nt1 == nt2) return 0;
|
||||
+
|
||||
+ uint16_t i;
|
||||
+ uint32_t nttmp1 = nt1;
|
||||
+ uint32_t nttmp2 = nt2;
|
||||
+
|
||||
+ for (i = 1; i < (32768/8); ++i) {
|
||||
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i;
|
||||
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -i;
|
||||
+
|
||||
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+1;
|
||||
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+1);
|
||||
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+2;
|
||||
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+2);
|
||||
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+3;
|
||||
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+3);
|
||||
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+4;
|
||||
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+4);
|
||||
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+5;
|
||||
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+5);
|
||||
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+6;
|
||||
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+6);
|
||||
+ nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+7;
|
||||
+ nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+7);
|
||||
+ }
|
||||
+ // either nt1 or nt2 are invalid nonces
|
||||
+ return(-99999);
|
||||
+}
|
||||
+
|
||||
+
|
||||
int main(int argc, char *const argv[])
|
||||
{
|
||||
const nfc_modulation nm = {
|
||||
@@ -117,6 +159,7 @@ int main(int argc, char *const argv[])
|
||||
|
||||
mifare_cmd mc;
|
||||
FILE *pfDump = NULL;
|
||||
+ FILE *pfKey = NULL;
|
||||
|
||||
//File pointers for the keyfile
|
||||
FILE * fp;
|
||||
@@ -200,6 +243,14 @@ int main(int argc, char *const argv[])
|
||||
}
|
||||
// fprintf(stdout, "Output file: %s\n", optarg);
|
||||
break;
|
||||
+ case 'D':
|
||||
+ // Partial File output
|
||||
+ if (!(pfKey = fopen(optarg, "w"))) {
|
||||
+ fprintf(stderr, "Cannot open: %s, exiting\n", optarg);
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+ // fprintf(stdout, "Output file: %s\n", optarg);
|
||||
+ break;
|
||||
case 'h':
|
||||
usage(stdout, 0);
|
||||
break;
|
||||
@@ -421,14 +472,28 @@ int main(int argc, char *const argv[])
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
for (i = 0; i < (t.num_sectors); ++i) {
|
||||
- if(t.sectors[i].foundKeyA)
|
||||
+ if(t.sectors[i].foundKeyA){
|
||||
fprintf(stdout, "Sector %02d - Found Key A: %012llx ", i, bytes_to_num(t.sectors[i].KeyA, sizeof(t.sectors[i].KeyA)));
|
||||
- else
|
||||
+ memcpy(&knownKey, t.sectors[i].KeyA, 6);
|
||||
+ knownKeyLetter = 'A';
|
||||
+ knownSector = i;
|
||||
+ }
|
||||
+ else{
|
||||
fprintf(stdout, "Sector %02d - Unknown Key A ", i);
|
||||
- if(t.sectors[i].foundKeyB)
|
||||
+ unknownSector = i;
|
||||
+ unknownKeyLetter = 'A';
|
||||
+ }
|
||||
+ if(t.sectors[i].foundKeyB){
|
||||
fprintf(stdout, "Found Key B: %012llx\n", bytes_to_num(t.sectors[i].KeyB, sizeof(t.sectors[i].KeyB)));
|
||||
- else
|
||||
+ knownKeyLetter = 'B';
|
||||
+ memcpy(&knownKey, t.sectors[i].KeyB, 6);
|
||||
+ knownSector = i;
|
||||
+ }
|
||||
+ else{
|
||||
fprintf(stdout, "Unknown Key B\n");
|
||||
+ unknownSector = i;
|
||||
+ unknownKeyLetter = 'B';
|
||||
+ }
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
@@ -504,7 +569,18 @@ int main(int argc, char *const argv[])
|
||||
// Max probes for auth for each sector
|
||||
for (k = 0; k < probes; ++k) {
|
||||
// Try to authenticate to exploit sector and determine distances (filling denonce.distances)
|
||||
- mf_enhanced_auth(e_sector, 0, t, r, &d, pk, 'd', dumpKeysA); // AUTH + Get Distances mode
|
||||
+ int authresult = mf_enhanced_auth(e_sector, 0, t, r, &d, pk, 'd', dumpKeysA); // AUTH + Get Distances mode
|
||||
+ if(authresult == -99999){
|
||||
+ //for now we return the last sector that is unknown
|
||||
+ nfc_close(r.pdi);
|
||||
+ nfc_exit(context);
|
||||
+ if(pfKey) {
|
||||
+ fprintf(pfKey, "%012llx;%d;%c;%d;%c", knownKey, knownSector, knownKeyLetter, unknownSector, unknownKeyLetter);
|
||||
+ fclose(pfKey);
|
||||
+ }
|
||||
+ return 9;
|
||||
+ }
|
||||
+
|
||||
printf("Sector: %d, type %c, probe %d, distance %d ", j, (dumpKeysA ? 'A' : 'B'), k, d.median);
|
||||
// Configure device to the previous state
|
||||
mf_configure(r.pdi);
|
||||
@@ -720,6 +796,7 @@ void usage(FILE *stream, int errno)
|
||||
fprintf(stream, " T nonce tolerance half-range, instead of default of 20\n (i.e., 40 for the total range, in both directions)\n");
|
||||
// fprintf(stream, " s specify the list of sectors to crack, for example -s 0,1,3,5\n");
|
||||
fprintf(stream, " O file in which the card contents will be written (REQUIRED)\n");
|
||||
+ fprintf(stream, " D file in which partial card info will be written in case PRNG is not vulnerable\n");
|
||||
fprintf(stream, "\n");
|
||||
fprintf(stream, "Example: mfoc -O mycard.mfd\n");
|
||||
fprintf(stream, "Example: mfoc -k ffffeeeedddd -O mycard.mfd\n");
|
||||
@@ -979,7 +1056,21 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
|
||||
|
||||
// Save the determined nonces distance
|
||||
d->distances[m] = nonce_distance(Nt, NtLast);
|
||||
- // fprintf(stdout, "distance: %05d\n", d->distances[m]);
|
||||
+ int checkForValidPRNG = dist_nt(Nt, NtLast);
|
||||
+ //printf("NT distance: %d\n", checkForValidPRNG);
|
||||
+
|
||||
+ // if no distance between, then we are in sync.
|
||||
+ if (checkForValidPRNG == 0) {
|
||||
+ printf("NT Distance is zero..........\n");
|
||||
+ } else {
|
||||
+ if (checkForValidPRNG == -99999) { // invalid nonce received
|
||||
+ ++unexpected_random;
|
||||
+ if (unexpected_random > 4) {
|
||||
+ printf("PRNG is not vulnerable to nested attack\n");
|
||||
+ return -99999;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
// Again, prepare and send {At}
|
||||
for (i = 0; i < 4; i++) {
|
||||
Regular → Executable
+62
-54
@@ -1,71 +1,79 @@
|
||||
#!/bin/bash
|
||||
|
||||
mfoc -O /tmp/asdf1234zxcvqwerlkjh0978.mfd
|
||||
myUID=$(nfc-list -t 1|sed -n 's/ //g;/UID/s/.*://p')
|
||||
TMPFILE_MFD="mfc_${myUID}_dump.mfd"
|
||||
TMPFILE_UNK="mfc_${myUID}_unknownMfocSectorInfo.txt"
|
||||
TMPFILE_FND="mfc_${myUID}_foundKeys.txt"
|
||||
|
||||
if [ -f "$TMPFILE_FND" ]; then
|
||||
mfoc -f "$TMPFILE_FND" -O "$TMPFILE_MFD" -D "$TMPFILE_UNK"
|
||||
else
|
||||
mfoc -O "$TMPFILE_MFD" -D "$TMPFILE_UNK"
|
||||
fi
|
||||
mfocResult=$?
|
||||
prngNotVulnerable=9
|
||||
keepTrying=1
|
||||
foundKeysForMFOC=" "
|
||||
|
||||
while [ $keepTrying -eq 1 ]
|
||||
do
|
||||
#echo "MFOC result: $mfocResult"
|
||||
if [ "$mfocResult" == "$prngNotVulnerable" ];then
|
||||
echo "MFOC not possible, detected hardened Mifare Classic"
|
||||
if [ "$mfocResult" -eq 9 ];then
|
||||
FILENAME="/tmp/unknownMfocSectorInfo_123456asdfqwer.txt"
|
||||
count=0
|
||||
while read LINE
|
||||
do
|
||||
let count++
|
||||
#echo "$count $LINE"
|
||||
done < $FILENAME
|
||||
while [ $keepTrying -eq 1 ]; do
|
||||
#echo "MFOC result: $mfocResult"
|
||||
if [ "$mfocResult" == "$prngNotVulnerable" ]; then
|
||||
echo "MFOC not possible, detected hardened Mifare Classic"
|
||||
if [ "$mfocResult" -eq 9 ]; then
|
||||
count=0
|
||||
while read LINE; do
|
||||
let count++
|
||||
#echo "$count $LINE"
|
||||
done < "$TMPFILE_UNK"
|
||||
|
||||
arr=(`echo $LINE | tr ';' ' '`)
|
||||
#echo ${arr[0]}
|
||||
#echo ${arr[1]}
|
||||
#echo ${arr[2]}
|
||||
#echo ${arr[3]}
|
||||
#echo ${arr[4]}
|
||||
arr=(`echo $LINE | tr ';' ' '`)
|
||||
#echo ${arr[0]}
|
||||
#echo ${arr[1]}
|
||||
#echo ${arr[2]}
|
||||
#echo ${arr[3]}
|
||||
#echo ${arr[4]}
|
||||
|
||||
knownKey=${arr[0]}
|
||||
knownSectorNum=${arr[1]}
|
||||
knownKeyLetter=${arr[2]}
|
||||
unknownSectorNum=${arr[3]}
|
||||
unknownKeyLetter=${arr[4]}
|
||||
knownBlockNum=$(($knownSectorNum * 4))
|
||||
unknownBlockNum=$(($unknownSectorNum * 4))
|
||||
echo "Trying HardNested Attack..."
|
||||
mycmd=(libnfc_crypto1_crack "$knownKey" "$knownBlockNum" "$knownKeyLetter" "$unknownBlockNum" "$unknownKeyLetter")
|
||||
echo "${mycmd[@]}"
|
||||
"${mycmd[@]}"
|
||||
knownKey=${arr[0]}
|
||||
knownSectorNum=${arr[1]}
|
||||
knownKeyLetter=${arr[2]}
|
||||
unknownSectorNum=${arr[3]}
|
||||
unknownKeyLetter=${arr[4]}
|
||||
knownBlockNum=$(($knownSectorNum * 4))
|
||||
unknownBlockNum=$(($unknownSectorNum * 4))
|
||||
echo "Trying HardNested Attack..."
|
||||
mycmd=(libnfc_crypto1_crack "$knownKey" "$knownBlockNum" "$knownKeyLetter" "$unknownBlockNum" "$unknownKeyLetter" "$TMPFILE_FND")
|
||||
echo "${mycmd[@]}"
|
||||
"${mycmd[@]}"
|
||||
else
|
||||
echo "mfoc returned: $mfocResult"
|
||||
keepTrying=0
|
||||
fi
|
||||
echo "mfoc returned: $mfocResult"
|
||||
keepTrying=0
|
||||
fi
|
||||
|
||||
cryptoCrackResult=$?
|
||||
if [ "$cryptoCrackResult" -eq 0 ];then
|
||||
FILENAME="/tmp/foundKey_Crapto1_Libnfc_1234567890qwerasdf.txt"
|
||||
while read LINE
|
||||
do
|
||||
echo "$LINE"
|
||||
done < $FILENAME
|
||||
while read LINE
|
||||
do
|
||||
echo "$LINE"
|
||||
done < "$TMPFILE_FND"
|
||||
|
||||
#arr=(`echo $LINE | tr ';' ' '`)
|
||||
#echo ${arr[0]}
|
||||
#echo ${arr[1]}
|
||||
#echo ${arr[2]}
|
||||
#foundKeysForMFOC="$foundKeysForMFOC-k ${arr[0]} "
|
||||
mycmd=(mfoc -f "$FILENAME" -O /tmp/asdf1234zxcvqwerlkjh0978.mfd)
|
||||
echo "${mycmd[@]}"
|
||||
"${mycmd[@]}"
|
||||
mfocResult=$?
|
||||
#arr=(`echo $LINE | tr ';' ' '`)
|
||||
#echo ${arr[0]}
|
||||
#echo ${arr[1]}
|
||||
#echo ${arr[2]}
|
||||
#foundKeysForMFOC="$foundKeysForMFOC-k ${arr[0]} "
|
||||
mycmd=(mfoc -f "$TMPFILE_FND" -O "$TMPFILE_MFD" -D "$TMPFILE_UNK")
|
||||
echo "${mycmd[@]}"
|
||||
"${mycmd[@]}"
|
||||
mfocResult=$?
|
||||
fi
|
||||
else
|
||||
keepTrying=0
|
||||
fi
|
||||
else
|
||||
keepTrying=0
|
||||
fi
|
||||
done
|
||||
|
||||
rm -rf /tmp/asdf1234zxcvqwerlkjh0978.mfd
|
||||
rm -rf /tmp/foundKey_Crapto1_Libnfc_1234567890qwerasdf.txt
|
||||
rm -rf /tmp/unknownMfocSectorInfo_123456asdfqwer.txt
|
||||
rm -f "$TMPFILE_UNK" "$TMPFILE_FND" "0x${myUID}_"*".txt"
|
||||
if [ $mfocResult -eq 0 ]; then
|
||||
echo -e "\n\nDump left in: $TMPFILE_MFD"
|
||||
else
|
||||
rm -f "$TMPFILE_MFD"
|
||||
fi
|
||||
|
||||
@@ -1,26 +1,40 @@
|
||||
#run this from inside miLazyCracker git repo
|
||||
#!/bin/bash
|
||||
|
||||
sudo apt-get install git
|
||||
sudo apt-get install libnfc-bin
|
||||
sudo apt-get install autoconf
|
||||
sudo apt-get install libnfc-dev
|
||||
set -x
|
||||
|
||||
#install MFOC
|
||||
git clone https://github.com/nfc-tools/mfoc.git
|
||||
# run this from inside miLazyCracker git repo
|
||||
|
||||
sudo apt-get install git libnfc-bin autoconf libnfc-dev
|
||||
|
||||
# install MFOC
|
||||
[ -d mfoc ] || git clone https://github.com/nfc-tools/mfoc.git
|
||||
cd mfoc
|
||||
cp ../mfoc.c src/ #copy in modified mfoc.c
|
||||
sudo autoreconf -vfi
|
||||
git reset --hard
|
||||
git clean -dfx
|
||||
# patch initially done against commit 48156f9b:
|
||||
patch -p1 < ../mfoc_test_prng.diff
|
||||
patch -p1 < ../mfoc_fix_4k_and_mini.diff
|
||||
patch -p1 < ../mfoc_support_tnp.diff
|
||||
autoreconf -vfi
|
||||
./configure
|
||||
sudo make
|
||||
make
|
||||
sudo make install
|
||||
|
||||
cd ..
|
||||
|
||||
#install Hardnested Attack Tool
|
||||
git clone https://github.com/aczid/crypto1_bs
|
||||
# install Hardnested Attack Tool
|
||||
[ -d crypto1_bs ] || git clone https://github.com/aczid/crypto1_bs
|
||||
cd crypto1_bs
|
||||
cp ../libnfc_crypto1_crack.c . #copy in modified .c
|
||||
git reset --hard
|
||||
git clean -dfx
|
||||
# patch initially done against commit 957702be:
|
||||
patch -p1 < ../crypto1_bs.diff
|
||||
make get_craptev1
|
||||
make get_crapto1
|
||||
make
|
||||
sudo cp libnfc_crypto1_crack /usr/bin
|
||||
sudo cp -a libnfc_crypto1_crack /usr/local/bin
|
||||
|
||||
cd ..
|
||||
|
||||
# install our script
|
||||
sudo cp -a miLazyCracker.sh /usr/local/bin/miLazyCracker
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
# uninstall dependencies
|
||||
#sudo apt-get remove git
|
||||
#sudo apt-get remove libnfc-bin
|
||||
#sudo apt-get remove autoconf
|
||||
#sudo apt-get remove libnfc-dev
|
||||
|
||||
# uninstall MFOC
|
||||
sudo rm -f /usr/local/bin/mfoc /usr/local/share/man/man1/mfoc.1
|
||||
|
||||
# uninstall Hardnested Attack Tool
|
||||
sudo rm -f /usr/local/bin/libnfc_crypto1_crack
|
||||
|
||||
# uninstall our script
|
||||
sudo rm -f /usr/local/bin/miLazyCracker
|
||||
Reference in New Issue
Block a user