Merge branch 'master' into master

Signed-off-by: Óscar Alfonso Díaz <oscar.alfonso.diaz@gmail.com>
This commit is contained in:
Óscar Alfonso Díaz 2023-05-23 13:11:37 +02:00 committed by GitHub
commit 6a8bb34eac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 162 additions and 35 deletions

View file

@ -4,6 +4,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased] ## [unreleased][unreleased]
- Added python3 script to convert amiibo nfc Flipper Zero files to eml files to be used with Proxmark3 (@OscarAkaElvis) - Added python3 script to convert amiibo nfc Flipper Zero files to eml files to be used with Proxmark3 (@OscarAkaElvis)
- Changed `hf mf restore` - Auth both key A and key B with default password (@wh201906)
- Changed `nfc decode -f` - now can detect and convert MFC dumpfiles to NDEF byte arrays (@iceman1001) - Changed `nfc decode -f` - now can detect and convert MFC dumpfiles to NDEF byte arrays (@iceman1001)
- Changed `nfc decode` - now handles EXTERNAL RECORDS better (@iceman1001) - Changed `nfc decode` - now handles EXTERNAL RECORDS better (@iceman1001)
- Fixed `nfc decode` - now handles NDEF Signature version1 records better (@iceman1001) - Fixed `nfc decode` - now handles NDEF Signature version1 records better (@iceman1001)
@ -62,6 +63,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Update documentation for installation on macOS with MacPorts (@linuxgemini) - Update documentation for installation on macOS with MacPorts (@linuxgemini)
- Added possible Paxton id to hitag2 tag info output - Added possible Paxton id to hitag2 tag info output
- Changed `hf mf sim` - reduce 50ms threshold to 6ms for reset to idle #1974 (@net147) - Changed `hf mf sim` - reduce 50ms threshold to 6ms for reset to idle #1974 (@net147)
- Update `amiibo_tools.lua` with new identifiers and create a python script `update_amiibo_tools_lua.py` to automate the process in the future. (@CorySolovewicz)
## [Nitride.4.16191][2023-01-29] ## [Nitride.4.16191][2023-01-29]
- Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox) - Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox)

View file

@ -655,6 +655,7 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
*txlen = 0; *txlen = 0;
if (bPwd && (bAuthenticating == false) && write) { if (bPwd && (bAuthenticating == false) && write) {
SpinDelay(2);
if (hitag2_write_page(rx, rxlen, tx, txlen) == false) { if (hitag2_write_page(rx, rxlen, tx, txlen) == false) {
return false; return false;
} }

View file

@ -55,6 +55,9 @@ amiibo_tools.db =
["0x00000003039bff02"] = { ["0x00000003039bff02"] = {
name = "Mario - Power Up Band" name = "Mario - Power Up Band"
}, },
["0x000000030430ff02"] = {
name = "Golden - Power Up Band"
},
["0x0000010000190002"] = { ["0x0000010000190002"] = {
name = "Dr. Mario" name = "Dr. Mario"
}, },
@ -214,6 +217,9 @@ amiibo_tools.db =
["0x0100000003990902"] = { ["0x0100000003990902"] = {
name = "Link - Link's Awakening" name = "Link - Link's Awakening"
}, },
["0x0100000004180902"] = {
name = "Link - Tears of the Kingdom"
},
["0x0100010000160002"] = { ["0x0100010000160002"] = {
name = "Toon Link" name = "Toon Link"
}, },
@ -1834,6 +1840,9 @@ amiibo_tools.db =
["0x0800010003820002"] = { ["0x0800010003820002"] = {
name = "Inkling" name = "Inkling"
}, },
["0x0800010004150402"] = {
name = "Inkling - Yellow"
},
["0x08000200003f0402"] = { ["0x08000200003f0402"] = {
name = "Inkling Boy" name = "Inkling Boy"
}, },
@ -1870,9 +1879,15 @@ amiibo_tools.db =
["0x08050200038f0402"] = { ["0x08050200038f0402"] = {
name = "Octoling Boy" name = "Octoling Boy"
}, },
["0x08050200041b0402"] = {
name = "Octoling - Blue"
},
["0x0805030003900402"] = { ["0x0805030003900402"] = {
name = "Octoling Octopus" name = "Octoling Octopus"
}, },
["0x08060100041c0402"] = {
name = "Smallfry"
},
["0x09c0010102690e02"] = { ["0x09c0010102690e02"] = {
name = "Mario - Soccer" name = "Mario - Soccer"
}, },
@ -2374,6 +2389,9 @@ amiibo_tools.db =
["0x3380000003781402"] = { ["0x3380000003781402"] = {
name = "Solaire of Astora" name = "Solaire of Astora"
}, },
["0x33c0000004200002"] = {
name = "Kazuya"
},
["0x3480000000310002"] = { ["0x3480000000310002"] = {
name = "Mega Man" name = "Mega Man"
}, },
@ -2455,6 +2473,9 @@ amiibo_tools.db =
["0x3600010003620002"] = { ["0x3600010003620002"] = {
name = "Cloud - Player 2" name = "Cloud - Player 2"
}, },
["0x3601000004210002"] = {
name = "Sephiroth"
},
["0x3640000003a20002"] = { ["0x3640000003a20002"] = {
name = "Hero" name = "Hero"
}, },
@ -2520,6 +2541,12 @@ amiibo_tools.db =
}, },
["0x3c80000003a40002"] = { ["0x3c80000003a40002"] = {
name = "Terry" name = "Terry"
},
["0x3dc0000004220002"] = {
name = "Steve"
},
["0x3dc1000004230002"] = {
name = "Alex"
} }
}, },
game_series = { game_series = {
@ -2621,6 +2648,7 @@ amiibo_tools.db =
["0x324"] = "Bayonetta", ["0x324"] = "Bayonetta",
["0x334"] = "Pac-man", ["0x334"] = "Pac-man",
["0x338"] = "Dark Souls", ["0x338"] = "Dark Souls",
["0x33c"] = "Tekken",
["0x348"] = "Megaman", ["0x348"] = "Megaman",
["0x34c"] = "Street fighter", ["0x34c"] = "Street fighter",
["0x350"] = "Monster Hunter", ["0x350"] = "Monster Hunter",
@ -2635,7 +2663,8 @@ amiibo_tools.db =
["0x38c"] = "Diablo", ["0x38c"] = "Diablo",
["0x3a0"] = "Persona", ["0x3a0"] = "Persona",
["0x3b4"] = "Banjo Kazooie", ["0x3b4"] = "Banjo Kazooie",
["0x3c8"] = "Fatal Fury" ["0x3c8"] = "Fatal Fury",
["0x3dc"] = "Minecraft"
}, },
types = { types = {
["0x00"] = "Figure", ["0x00"] = "Figure",

View file

@ -1109,7 +1109,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
"Restore MIFARE Classic dump file to tag.\n" "Restore MIFARE Classic dump file to tag.\n"
"\n" "\n"
"The key file and dump file will program the card sector trailers.\n" "The key file and dump file will program the card sector trailers.\n"
"By default we authenticate to card with key B 0xFFFFFFFFFFFF.\n" "By default we authenticate to card with key 0xFFFFFFFFFFFF.\n"
"If access rights in dump file is all zeros, it will be replaced with default values\n" "If access rights in dump file is all zeros, it will be replaced with default values\n"
"\n" "\n"
"`--uid` param is used for filename templates `hf-mf-<uid>-dump.bin` and `hf-mf-<uid>-key.bin.\n" "`--uid` param is used for filename templates `hf-mf-<uid>-dump.bin` and `hf-mf-<uid>-key.bin.\n"
@ -1321,56 +1321,37 @@ static int CmdHF14AMfRestore(const char *Cmd) {
uint8_t wdata[26]; uint8_t wdata[26];
memcpy(wdata + 10, bldata, sizeof(bldata)); memcpy(wdata + 10, bldata, sizeof(bldata));
if (use_keyfile_for_auth) { for (int8_t kt = MF_KEY_B; kt > -1; kt--) {
for (int8_t kt = MF_KEY_B; kt > -1; kt--) { if (use_keyfile_for_auth) {
if (kt == MF_KEY_A) if (kt == MF_KEY_A)
memcpy(wdata, keyA[s], 6); memcpy(wdata, keyA[s], 6);
else else
memcpy(wdata, keyB[s], 6); memcpy(wdata, keyB[s], 6);
} else {
PrintAndLogEx(INFO, "block %3d: %s", mfFirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata))); // use default key to authenticate for the write command
memcpy(wdata, default_key, 6);
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, kt, 0, wdata, sizeof(wdata));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
if (isOK == 0) {
if (b == 0) {
PrintAndLogEx(INFO, "Writing to manufacture block w key %c ( " _RED_("fail") " )", (kt == MF_KEY_A) ? 'A' : 'B');
} else {
PrintAndLogEx(FAILED, "Write to block %u w key %c ( " _RED_("fail") " ) ", b, (kt == MF_KEY_A) ? 'A' : 'B');
}
} else {
// if success, skip to next block
break;
}
} else {
PrintAndLogEx(WARNING, "Command execute timeout");
}
} }
} else {
// use default key to authenticate for the write command
memcpy(wdata, default_key, 6);
PrintAndLogEx(INFO, "block %3d: %s", mfFirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata))); PrintAndLogEx(INFO, "block %3d: %s", mfFirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata)));
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, MF_KEY_B, 0, wdata, sizeof(wdata)); SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, kt, 0, wdata, sizeof(wdata));
PacketResponseNG resp; PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff; uint8_t isOK = resp.oldarg[0] & 0xff;
if (isOK == 0) { if (isOK == 0) {
if (b == 0) { if (b == 0) {
PrintAndLogEx(INFO, "Writing to manufacture block w key B ( " _RED_("fail") " )"); PrintAndLogEx(INFO, "Writing to manufacture block w key %c ( " _RED_("fail") " )", (kt == MF_KEY_A) ? 'A' : 'B');
} else { } else {
PrintAndLogEx(FAILED, "Write to block %u w key B ( " _RED_("fail") " )", b); PrintAndLogEx(FAILED, "Write to block %u w key %c ( " _RED_("fail") " ) ", b, (kt == MF_KEY_A) ? 'A' : 'B');
} }
} else {
// if success, skip to next block
break;
} }
} else { } else {
PrintAndLogEx(WARNING, "Command execute timeout"); PrintAndLogEx(WARNING, "Command execute timeout");
} }
} // end use_keyfile_for_auth }
} // end loop B } // end loop B
} // end loop S } // end loop S

View file

@ -2690,7 +2690,7 @@ static void wait4response(uint8_t b) {
int CmdHF14MfUTamper(const char *Cmd) { int CmdHF14MfUTamper(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfu tamper", CLIParserInit(&ctx, "hf mfu tamper",
"Set the congiguration of the NTAG 213TT tamper feature\n" "Set the configuration of the NTAG 213TT tamper feature\n"
"Supports:\n" "Supports:\n"
"NTAG 213TT\n", "NTAG 213TT\n",
"hf mfu tamper -e -> enable tamper feature\n" "hf mfu tamper -e -> enable tamper feature\n"
@ -4697,7 +4697,7 @@ static command_t CommandTable[] = {
{"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump onto a MFU MAGIC tag"}, {"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump onto a MFU MAGIC tag"},
{"view", CmdHF14AMfuView, AlwaysAvailable, "Display content from tag dump file"}, {"view", CmdHF14AMfuView, AlwaysAvailable, "Display content from tag dump file"},
{"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"}, {"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"},
{"tamper", CmdHF14MfUTamper, IfPm3Iso14443a, "Cofigure the tamper feature on an NTAG 213TT"}, {"tamper", CmdHF14MfUTamper, IfPm3Iso14443a, "Configure the tamper feature on an NTAG 213TT"},
{"---------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"}, {"---------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"},
{"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "Load Ultralight dump file into emulator memory"}, {"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "Load Ultralight dump file into emulator memory"},
{"esave", CmdHF14AMfuESave, IfPm3Iso14443a, "Save Ultralight dump file from emulator memory"}, {"esave", CmdHF14AMfuESave, IfPm3Iso14443a, "Save Ultralight dump file from emulator memory"},

View file

@ -0,0 +1,114 @@
#!/usr/bin/env python3
"""
-----------------------------------------------------------------------------
Name: update_amiibo_tools_lua.py
Author: Cory Solovewicz
Description:
This is a python script to automate what the updating of the amiibo_tools.lua
file which holds a lua table of all known amiibos. Previously updating the
amiibo_tools.lua was a very manual process.
This script automates the following original command:
curl https://raw.githubusercontent.com/N3evin/AmiiboAPI/master/database/amiibo.json | jq 'del(.amiibos[].release)' | jq 'del(.characters)' | pbcopy --> transform to table
And outputs the formatted file as amiibo_tools.lua
If everything goes well, this should be an updated copy of amiibo_tools.lua
which can then be placed in the /lualibs/ directory.
The temporary amiibo.json file is then deleted
Dependencies:
python3 -m pip install jq
How to run:
python update_amiibo_tools_lua.py
The script will create the file amiibo_tools.lua
After running, manually backup the original /lualibs/amiibo_tools.lua and move the
updated amiibo_tools.lua to the /lualibs/ directory.
-----------------------------------------------------------------------------
"""
import os
import re
import subprocess
import json
from jq import jq
def fetch_data():
print("Fetching amiibo.json")
# Perform the curl command
curl_command = "curl https://raw.githubusercontent.com/N3evin/AmiiboAPI/master/database/amiibo.json"
curl_process = subprocess.Popen(curl_command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = curl_process.communicate()
if curl_process.returncode != 0:
print("Error fetching data: ", error.decode())
return None
return output
def filter_data(data):
print("Filtering downloaded data")
# Convert the output to JSON and use jq to filter data
data_json = json.loads(data)
filtered_data_json = jq('del(.amiibos[].release) | del(.characters)').transform(data_json)
# Convert the filtered JSON data back to a string, preserving Unicode characters
filtered_data = json.dumps(filtered_data_json, indent=2, ensure_ascii=False)
return filtered_data
def save_data(filtered_data, filename):
# Save filtered data to file
with open(filename, 'w', encoding='utf-8') as file:
file.write(filtered_data)
print(f"Data saved to {filename}")
def process_file(filename):
# Open the file
with open(filename, 'r', encoding='utf-8') as file:
data = file.read()
# Perform the replacements
data = data.replace('"name"', 'name')
data = data.replace('"amiibo_series"', 'amiibo_series')
data = data.replace('"amiibos"', 'amiibos')
data = data.replace('"game_series"', 'game_series')
data = data.replace('"types"', 'types')
data = data.replace(':', ' =')
data = re.sub('"0x', '["0x', data)
data = re.sub('" =', '"] =', data)
# Prepend the text
prepend_text = 'local amiibo_tools = {}\n\n-- curl https://raw.githubusercontent.com/N3evin/AmiiboAPI/master/database/amiibo.json | jq \'del(.amiibos[].release)\' | jq \'del(.characters)\' | pbcopy --> transform to table\namiibo_tools.db =\n'
data = prepend_text + data
# Append the text
append_text = '\n\nreturn amiibo_tools\n'
data = data + append_text
return data
def write_to_file(data, filename):
# Write the output
with open(filename, 'w', encoding='utf-8') as file:
file.write(data)
print(f"Output written to {filename}")
def delete_file(filename):
try:
os.remove(filename)
print(f"Temporary file {filename} deleted")
except OSError as e:
print(f"Error deleting file {filename}: ", e)
def main():
data = fetch_data()
if data:
filtered_data = filter_data(data)
save_data(filtered_data, 'amiibo.json')
processed_data = process_file('amiibo.json')
write_to_file(processed_data, 'amiibo_tools.lua')
delete_file('amiibo.json')
if __name__ == "__main__":
main()